Example script¶
This section demonstrates a simple example script.
Copying the script below into the rfigui
Lua editor will allow you to
interactively change this script.
function execute(data)
data:clear_mask()
for _,polarization in ipairs(data:get_polarizations()) do
local pol_data = data:convert_to_polarization(polarization)
pol_data = pol_data:convert_to_complex("amplitude")
aoflagger.high_pass_filter(pol_data, 51, 51, 3, 3)
aoflagger.visualize(pol_data, "Low-pass filtered", 0)
aoflagger.sumthreshold(pol_data, 1, 1, true, true)
aoflagger.scale_invariant_rank_operator(pol_data, 0.2, 0.2)
pol_data = pol_data:convert_to_complex("complex")
data:set_polarization_data(polarization, pol_data)
end -- end of polarization iterations
end
We will discuss this script line by line.
When AOFlagger calls the execute()
function, the script starts by calling
Data.clear_mask()
, which unsets all flags:
function execute(data)
data:clear_mask()
If the input data was already flagged, these flags are removed.
The next step is a for
loop over the different polarizations in the set:
for _,polarization in ipairs(data:get_polarizations()) do
Almost any flagging script will need such a loop, because most
operations can only work on a single polarization. The input data could consist
of 1-4 linear polarizations (XX, XY, YX, YY), circular polarizations
(LL, LR, RL, RR) or Stokes polarizations (I, Q, U, V).
Data.get_polarizations()
returns a table of strings, and ipairs
converts this to an iterator. A loop over a table captures an
(index, value) pair. In this case we only need the value (polarization
),
and ignore the index with the underscore.
To work on a single polarization only, Data.convert_to_polarization()
is
used to create a new data object that contains just that single polarization:
local pol_data = data:convert_to_polarization(polarization)
The new object is stored as local
variable. In Lua, any variable that is
not declared as local
, is a global. This might cause the data to be stored
longer than necessary, causing more memory usage, so local variables should be
preferred. [1]
Most input data sets are complex. Thresholding is more effective on the
amplitudes of the samples though. Function Data.convert_to_complex
is used
to calculate the amplitudes:
pol_data = pol_data:convert_to_complex("amplitude")
Another new object is created, but the previous pol_data
object is
overwritten.
The next step is high-pass filtering the data:
aoflagger.high_pass_filter(pol_data, 51, 51, 3, 3)
Function aoflagger.high_pass_filter()
filters the visibility data in
pol_data. A kernel of 51 x 51 samples is used (ntimes x nchannels), with a
Gaussian width of 3 samples in both directions.
The filtered data is “visualized” with function aoflagger.visualize()
:
aoflagger.visualize(pol_data, "Low-pass filtered", 0)
This statement makes it possible to display the result of filtering the
data in rfigui
. When the script is not running interactively from a
gui, the call is ignored. Note that visualize()
will be called for
all polarizations. The gui will recombine visualizations from different
polarizations, as long as they have the same name and sorting index.
The aoflagger.sumthreshold()
searches the (filtered) data for consecutive high
values in time or frequency:
aoflagger.sumthreshold(pol_data, 1, 1, true, true)
The resulting pol_data
object will now contain a flag mask. This flag mask
is morphologically extended in the time and frequency direction with the
aoflagger.scale_invariant_rank_operator()
function:
aoflagger.scale_invariant_rank_operator(pol_data, 0.2, 0.2)
Finally, the data are converted back to its original form, so that the
polarizations can be combined. The first step is to convert the data back
to complex values using Data.convert_to_complex()
:
pol_data = pol_data:convert_to_complex("complex")
This “conversion” can be seen as an update of the metadata. The phases
were lost while converting to amplitudes, so these are not restored, and
just assumed to be constant. The pol_data
now holds a complex data and
our new flag mask. The last step is to update the input data with our
new data using Data.set_polarization_data()
:
data:set_polarization_data(polarization, pol_data)
By iterating over all polarizations in the input set, the polarizations in the input data object are replaced one by one.
[1] | Data objects are emptied by AOFlagger at the end of the execute()
function, so the user should normally not worry about memory usage. |