N2Accumulate¶
-
class N2Accumulate : public kotekan::Stage¶
Accumulate the high rate GPU output into integrated N2Buffers.
This stage accumulates output from the N2k GPU correlator into integrated visibility buffers.
ACCUMULATION BINNING STRATEGY
The GPU correlation frames are accumulated into bins. The binning strategy is either by “fixed number of frames” (bin_in_ERA false) or by Earth Rotation Angle (ERA, bin_in_ERA true). Both binning strategies ingest frames two at a time, so bins will always contain an even number of frames, and bin boundaries will always occur at an even frame count. If second-stage RFI excision (via the input RFIFrameMask) signals a frame should be dropped, both frames in the pair are dropped.
In “fixed number of frames” the beginning of bin 0 is at instrument start (seq = 0), and each bin covers exactly sub_integration_ntime * num_subintegrations_per_bin fpga seq numbers.
In “ERA” binning the beginning of bin 0 is when ERA = 0 just before 2000 Jan 1 Noon. Every Earth rotation (sidereal day) is divided into num_bins_per_rotation bins equally sized in ERA, with a bin edge at ERA = 0.
This stage will often come online after there is data in the pipeline (because of a node restart, an X-engine restart, or simply a delay between F-engine activation and X-engine). When started, it will check if the first frame it sees is the start of a bin. If so it will immediately begin accumulating. If not, it will drop frames until it sees the start of a bin, and then begin accumulating. An accumulation ends when the stage sees that the next frame will be in a new bin. At this point the accumulated visibility matrix is output, internal buffers and counters are reset, and a new accumulation begins.
The stage output is single-frequency N2FrameViews. At the end of an accumulation the stage loops through the input frequencies, for each one produces an N2FrameView with associated metadata. The frequencies are always released into the output buffer in the order they appear in the input arrays (ie. round robin). The output stream will see frames in the order: [T0F0 T0F1 T0F2 T1F0 T1F1 T1F2 …]
VARIANCE ESTIMATION
The output N2FrameViews include the visibility matrix (normalized by the number of good fpga samples in the accumulation) and the
weights: the reciprocal of the estimated variance of the visibilities. Because the visibilities may have a linear drift (due to fringes, etc) we cannot use the standard estimator, we want to measure the variance of the visibility apart from linear drift. To accomplish this, both variance estimators currently implemented follow an “even-odd” pattern, building up an estimate of the variance by differencing adjacent samples. Schematically for a data stream [x0 x1 x2 x3 x4…] both estimators build up a sum like:S2 = (x1 - x0)^2 + (x3 - x2)^2 + (x5 - x4)^2 + …
Only using even-odd pairs in this manner produces a noisier estimate of the variance, but allows for relatively simple normalization and improves memory bandwidth as frames can be loaded in chunks of 2 and then dropped.
The implemented estimators are “CHIMEv1” and “EvenOddPosDef”.
The “CHIMEv1” estimator is the original estimator used in CHIME. It differences the unnormalized correlations directly, which produces a biased estimate if the number of samples in each frame changes. A bias correction is applied, however, it is not guaranteed the resulting variance value is positive definite.
The “EvenOddPosDef” estimator differences normalized visibility samples and accounts for the number of samples in each. It produces an unbiased estimate of the variance and is positive definite, it only produces 0 if the visibilities in each pair are identical or there are no samples in the accumulation bin. On Gaussian data it has the same variance as the CHIMEv1 estimator.
TODO: - radiometer_chi2
num_integrations := samples_per_dataset / sub_integration_ntime num_freq := num_freq_per_n2k_frame
num_corr_blocks_lin := num_elements / 16 num_corr_blocks := num_corr_blocks_lin * (num_corr_blocks_lin + 1) / 2
num_count_blocks_lin := num_elements / 8 / 8 # 8 for blocksize,
8 for downsampling¶
num_count_blocks := num_count_blocks_lin * (num_count_blocks_lin + 1) / 2
- Buffers
in_bufCorrelation buffer from n2k. Blocked Lower Triangular.Format: NDArray int32 [num_integrations, num_freq, num_corr_blocks, 16, 16, 2]
Metadata:
chordMetadata
in_counts_bufCounts buffer from n2k. Blocked Lower TriangularFormat: NDArray int32 [num_integrations, num_freq, num_count_blocks, 8, 8]
Metadata:
chordMetadata
in_rficounts_bufRFIcounts buffer, the count of bad (rfimask=0) samples in the RFI mask in each n2k correlation.Format: NDArray int32 [num_integrations, num_freq]
Metadata:
chordMetadata
in_plcounts_bufPLcounts buffer, the count of bad (plmask=0) samples in the PL mask in each n2k correlation.Format: NDArray uint64 [num_integrations, num_freq]
Metadata:
chordMetadata
in_rfiframemask_bufRFIFrameMask buffer, a mask marking specific correlator samples to excise.Format: NDArray uint8 [num_integrations, num_freq]
Metadata:
chordMetadata
out_bufThe accumulated and tagged data.Format: N2Buffer. layout=FullUpperTri, num_ev=0
Metadata:
N2Metadata
- Param num_freq_per_n2k_frame:
int64_t Number of frequencies in buffers, required.
- Param num_subintegrations_per_bin:
int64_t Number of samples (subintegrations) to accumulate in each output frame. Default: 0.
- Param packet_loss_is_scalar:
bool Whether the packet loss (ie. the counts matrix) is a scalar in dish element or not. If so, all baselines use the same value from
counts, the first element in the buffer. Thefalsecase has not been implemented.- Param samples_per_data_set:
int64_t Total number of time samples covered by each input frame. nt_outer in n2k.
- Param sub_integration_ntime:
int64_t Number of time samples integrated in each entry in correlation and counts buffers. n2_inner in n2k.
- Param num_elements:
int64_t Number of elements (num_dish x num_pol) in the buffers.
- Param do_fringestop:
bool Whether to fringestop incoming correlations. Default: False
Public Functions
-
N2Accumulate(kotekan::Config &config, const std::string &unique_name, kotekan::bufferContainer &buffer_container)¶
-
~N2Accumulate() = default¶
-
virtual void main_thread() override¶
The main thread function for N2Accumulate.
This function is responsible for the main logic of the N2Accumulate class.
-
int64_t get_accum_abs_bin_idx(uint64_t seq)¶
Return a montonic index (counter) for the accumulation bin including seq. Will increase by 1 for each accumulation bin. If bins are smaller than input frames, bins will be skipped on output. The index may or may not begin at 0. Restart-safe.
- Parameters:
seq – Sequence tick for the moment in question
- Returns:
The index value for this accumulation bin.
-
int64_t calculate_ERA_bin_idx_from_time(const timespec &t_inst)¶
Calculate the accumulation bin index at a given time for ERA-binning.
- Parameters:
t_inst – Instrument time to calculate the bin index.
- Returns:
The index value for this accumulation bin.
-
EOP get_accum_bin_EOP(int64_t accum_bin_idx)¶
Return the Earth Orientation Parameters (EOP) for this accumulation bin. This will be the EOP at the center of the bin.
- Parameters:
accum_bin_idx – Index for the accumulation bin.
- Returns:
The EOP for the center of the bin.
-
bool is_seq_start_of_bin(uint64_t seq, int64_t bin_idx)¶
Check if the given sequence number is the beginning of the given accumulation bin.
- Parameters:
seq – Sequence number of a visibility sample
bin_idx – Index of the accumulation bin to check.
- Returns:
true if seq is the start of the bin.
-
void accum_corr_and_var(int32_t *vis_f, float *weight_f, const int32_t *corr_t0_f, const int32_t *corr_t1_f, double freq_MHz, EOP &target_eop, EOP &eop_t0, EOP &eop_t1, int32_t count_t0, int32_t count_t1, std::vector<std::complex<float>> &fringe_phase_t0, std::vector<std::complex<float>> &fringe_phase_t1)¶
-
bool output_and_reset(frameID &in_frame_id, frameID &in_rfiframemask_frame_id, frameID &out_frame_id)¶
Copy accumulated visibility matrix and weights to the output buffer, reset the visibility and weights matrices.
Helper function to keep code a bit more readable.
- Parameters:
in_frame_id – The input frame ID.
out_frame_id – The output frame ID.
- Returns:
bool True if successful, false otherwise.