virtual void stream_body(wi_run_state &run_state) override { run_state.start_substream(0.0); thread main_t(&vdif_assembler::run, assembler); for (;;) { float *intensity; float *weights; ssize_t stride; bool zero_flag = false; run_state.setup_write(nt_maxwrite, intensity, weights, stride, zero_flag); assembler->get_intensity_chunk(intensity,stride); //initialize weight to 1.0 for (int i = 0; i < nfreq; i++) { for (int j = 0; j < nt_maxwrite; j++) { weights[i*stride + j] = 1.0; } } //cout << "Bonsai received a chunk." << endl; run_state.finalize_write(nt_maxwrite); } run_state.end_substream(); main_t.join(); }
void psrfits_stream::stream_body(wi_run_state &run_state) { // FIXME psrfits_stream currently sets the initial time of the stream to zero. // What's a sensible way to determine an initial time from a 'struct psrfits'? double t0 = 0.0; run_state.start_substream(t0); while (!p->eof) { float *intensity; float *weights; ssize_t stride; bool zero_flag = false; run_state.setup_write(this->nt_maxwrite, intensity, weights, stride, zero_flag); // Transpose and convert uint8 -> float for (ssize_t it = 0; it < nt_maxwrite; it++) for (ssize_t ifreq = 0; ifreq < nfreq; ifreq++) intensity[ifreq*stride + it] = (float)p->data[it*nfreq + ifreq]; // psrfits weights are per-(frequency,chunk), not per-(frequency,sample) for (ssize_t ifreq = 0; ifreq < nfreq; ifreq++) { float w = p->freq_weights[ifreq]; if (w < 0.0) throw runtime_error(p->filename + ": negative weight in file, this is currently treated as an error"); for (ssize_t it = 0; it < nt_maxwrite; it++) weights[ifreq*stride + it] = w; } run_state.finalize_write(this->nt_maxwrite); p->read_next_row(); } run_state.end_substream(); }
// // This overrides the pure virtual function wi_stream::stream_body() and defines the stream. // For a high-level overview, see comments in rf_pipelines.hpp (in class wi_stream). // The 'run_state' argument contains ring buffers which the stream will write data into. // virtual void stream_body(wi_run_state &run_state) override { std::random_device rd; std::mt19937 rng(rd()); std::normal_distribution<float> dist(0, sample_rms); // In general a stream can be composed of multiple "substreams" (see rf_pipelines.hpp). // Here we put everything into a single stream, with nominal starting time t=0. run_state.start_substream(0.0); // Current position in stream (such that 0 <= it0 < nt_tot, where nt_tot is the stream length) ssize_t it0 = 0; while (it0 < nt_tot) { // Number of samples to write in this block ssize_t nt = min(nt_maxwrite, nt_tot-it0); // Call wi_run_state::setup_write() to reserve space in the ring buffers. // For details, see comments in rf_pipelines.hpp (in class wi_run_state). float *intensity; float *weights; ssize_t stride; bool zero_flag = false; // no need to zero buffers, since we'll overwrite them shortly run_state.setup_write(nt, intensity, weights, stride, zero_flag); // After setup_write() returns, the 'intensity' and 'weights' pointers point to memory // regions in the ring buffers. These are logical 2D arrays of shape (nfreq,nt), laid // out in memory so that time samples are adjacent, but frequencies are separated by // offset 'stride'. Therefore, the memory location of the intensity array element with // (frequency,time) indices (ifreq,it) is intensity[ifreq*stride+it], and similarly for // the weights. // Fill the intensity array with Gaussian random numbers, and initialize the weights to 1. for (ssize_t ifreq = 0; ifreq < nfreq; ifreq++) { for (ssize_t it = 0; it < nt; it++) { intensity[ifreq*stride + it] = dist(rng); weights[ifreq*stride + it] = 1.0; } } // Call wi_run_state::finalize_write() after filling the arrays, to advance the ring buffers. // After finalize_write() returns, the intensity and weights pointers are no longer valid. run_state.finalize_write(nt); it0 += nt; } run_state.end_substream(); }