LCOV - code coverage report
Current view: top level - singledishfiller/Filler - DataAccumulator.h (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 396 610 64.9 %
Date: 2024-12-11 20:54:31 Functions: 58 81 71.6 %

          Line data    Source code
       1             : /*
       2             :  * DataAccumulator.h
       3             :  *
       4             :  *  Created on: Jan 18, 2016
       5             :  *      Author: nakazato
       6             :  */
       7             : 
       8             : #ifndef SINGLEDISH_FILLER_DATAACCUMULATOR_H_
       9             : #define SINGLEDISH_FILLER_DATAACCUMULATOR_H_
      10             : 
      11             : #include <vector>
      12             : #include <cassert>
      13             : #include <memory>
      14             : #include <algorithm>
      15             : #include <numeric>
      16             : #include <functional>
      17             : 
      18             : #include <casacore/casa/BasicSL/String.h>
      19             : #include <casacore/casa/Arrays/Vector.h>
      20             : #include <casacore/casa/Arrays/Matrix.h>
      21             : #include <casacore/casa/Arrays/ArrayMath.h>
      22             : #include <casacore/casa/IO/ArrayIO.h>
      23             : #include <casacore/casa/Containers/Record.h>
      24             : 
      25             : #include <casacore/measures/Measures/Stokes.h>
      26             : 
      27             : #include <casacore/tables/Tables/TableRecord.h>
      28             : #include <singledishfiller/Filler/DataRecord.h>
      29             : #include <singledishfiller/Filler/FillerUtil.h>
      30             : 
      31             : using namespace casacore;
      32             : 
      33             : namespace {
      34             : template<class T>
      35       56696 : inline void resizeTo(T &array, casacore::IPosition const &shape) {
      36       56696 :     if (array.shape() != shape) {
      37         368 :         array.resize(shape, false);
      38             :     }
      39       56696 : }
      40             : 
      41             : template<class T>
      42       58476 : inline void setValue1(ssize_t n, T const *src, T *dst) {
      43   225175292 :     for (ssize_t i = 0; i < n; ++i) {
      44   225116816 :         dst[i] = src[i];
      45             :     }
      46       58476 : }
      47             : 
      48             : template<class T>
      49       57906 : inline void setValueToMatrixColumn(casacore::Vector<T> const &src,
      50             :         ssize_t icolumn, casacore::Matrix<T> &dst) {
      51       57906 :     casacore::IPosition const &shape = dst.shape();
      52       57906 :     ssize_t const nrow = shape[0];
      53       57906 :     ssize_t const ncolumn = shape[1];
      54       57906 :     if (icolumn >= ncolumn) {
      55           0 :         throw casacore::AipsError("Specified column doesn't exist.");
      56             :     }
      57             : 
      58             :     casacore::Bool b1, b2;
      59       57906 :     T *dst_p = dst.getStorage(b1);
      60       57906 :     T *work_p = dst_p + icolumn * nrow;
      61       57906 :     T const *src_p = src.getStorage(b2);
      62             : 
      63       57906 :     setValue1(nrow, src_p, work_p);
      64             : 
      65       57906 :     src.freeStorage(src_p, b2);
      66       57906 :     dst.putStorage(dst_p, b1);
      67       57906 : }
      68             : 
      69             : template<class T, class Executor>
      70       28838 : inline void shuffleTransposeMatrix(ssize_t n, size_t offset_src,
      71             :         casacore::Matrix<T> const &src, casacore::Matrix<T> &dst,
      72             :         std::vector<size_t> src_order = { }) {
      73       28838 :     if (offset_src > src.ncolumn() - 1)
      74           0 :         throw casacore::AipsError("offset too large");
      75             :     casacore::Bool b1, b2;
      76       28838 :     T const *src_p = src.getStorage(b1);
      77       28838 :     T *dst_p = dst.getStorage(b2);
      78       28838 :     T const *wsrc_p = src_p + offset_src * n;
      79       28838 :     T *wdst_p = dst_p;
      80             : 
      81       28838 :     Executor::execute(n, wsrc_p, wdst_p, src_order);
      82             : 
      83       28838 :     src.freeStorage(src_p, b1);
      84       28838 :     dst.putStorage(dst_p, b2);
      85       28838 : }
      86             : 
      87           0 : inline void getDefaultOrder(size_t const num_order,
      88             :         std::vector<size_t> &order) {
      89           0 :     order.resize(num_order);
      90           0 :     std::iota(order.begin(), order.end(), 0);
      91           0 : }
      92             : 
      93       56236 : inline bool setAndCheckOrder(size_t const required_size, size_t const max_value,
      94             :         std::vector<size_t> &order) {
      95       56236 :     if (order.size() == 0)
      96           0 :         getDefaultOrder(required_size, order);
      97             : 
      98       56236 :     if (order.size() < required_size) {
      99           0 :         return false;
     100             :     }
     101       56236 :     size_t max_idx = order[0];
     102      112472 :     for (size_t i = 1; i < order.size(); ++i) {
     103       56236 :         max_idx = std::max(max_idx, order[i]);
     104             :     }
     105       56236 :     return max_idx <= max_value;
     106             : }
     107             : 
     108             : struct ExecuteMatrix1 {
     109             :     template<class T>
     110         570 :     static void execute(ssize_t n, T const *src, T *dst,
     111             :             std::vector<size_t> /*in_order*/) {
     112         570 :         setValue1(n, src, dst);
     113         570 :     }
     114             : };
     115             : 
     116             : struct ExecuteMatrix2 {
     117             :     template<class T>
     118       28268 :     static void execute(ssize_t n, T const *src, T *dst,
     119             :             std::vector<size_t> src_order) {
     120             :         // need to set max_value=3 for 4 pol case
     121       28268 :         if (!setAndCheckOrder(2, 3, src_order))
     122           0 :             throw casacore::AipsError("got invalid order list");
     123       28268 :         T const *row0_p = src + src_order[0] * n;
     124       28268 :         T const *row1_p = src + src_order[1] * n;
     125   112583996 :         for (ssize_t i = 0; i < n; ++i) {
     126   112555728 :             dst[2 * i] = row0_p[i];
     127   112555728 :             dst[2 * i + 1] = row1_p[i];
     128             :         }
     129       28268 :     }
     130             : };
     131             : 
     132             : struct ExecuteMatrix4X {
     133             :     template<class T>
     134             :     static void execute(ssize_t /*n*/, T const */*src*/, T */*dst*/,
     135             :             std::vector<size_t> /*in_order*/) {
     136             :         throw std::runtime_error("");
     137             :     }
     138             : };
     139             : 
     140             : // polarization order assumption (auto, cross, cross, auto)
     141             : template<>
     142           0 : inline void ExecuteMatrix4X::execute(ssize_t n, casacore::Bool const *src,
     143             :         casacore::Bool *dst, std::vector<size_t> src_order) {
     144           0 :     if (!setAndCheckOrder(4, 3, src_order))
     145           0 :         throw casacore::AipsError("got invalid order list");
     146           0 :     casacore::Bool const *row0_p = src + src_order[0] * n;
     147           0 :     casacore::Bool const *row1_p = src + src_order[1] * n;
     148           0 :     casacore::Bool const *row2_p = src + src_order[2] * n;
     149           0 :     casacore::Bool const *row3_p = src + src_order[3] * n;
     150           0 :     for (ssize_t i = 0; i < n; ++i) {
     151           0 :         dst[4 * i + 0] = row0_p[i];
     152           0 :         casacore::Bool b = row1_p[i] || row2_p[i];
     153           0 :         dst[4 * i + 1] = b;
     154           0 :         dst[4 * i + 2] = b;
     155           0 :         dst[4 * i + 3] = row3_p[i];
     156             :     }
     157           0 : }
     158             : 
     159             : struct ExecuteMatrix4 {
     160             :     template<class T>
     161           0 :     static void execute(ssize_t n, T const *src, T *dst,
     162             :             std::vector<size_t> src_order) {
     163           0 :         if (!setAndCheckOrder(4, 3, src_order))
     164           0 :             throw casacore::AipsError("got invalid order list");
     165           0 :         T const *row0_p = src + src_order[0] * n;
     166           0 :         T const *row1_p = src + src_order[1] * n;
     167           0 :         T const *row2_p = src + src_order[2] * n;
     168           0 :         T const *row3_p = src + src_order[3] * n;
     169           0 :         for (ssize_t i = 0; i < n; ++i) {
     170           0 :             dst[4 * i + 0] = row0_p[i];
     171           0 :             dst[4 * i + 1] = row1_p[i];
     172           0 :             dst[4 * i + 2] = row2_p[i];
     173           0 :             dst[4 * i + 3] = row3_p[i];
     174             :         }
     175           0 :     }
     176             : };
     177             : 
     178           0 : inline void shuffleTransposeMatrix4F2C(ssize_t n,
     179             :         casacore::Matrix<casacore::Float> const &src,
     180             :         casacore::Matrix<casacore::Complex> &dst,
     181             :         std::vector<size_t> src_order = { }) {
     182           0 :     if (!setAndCheckOrder(4, 3, src_order))
     183           0 :         throw casacore::AipsError("got invalid order list");
     184             :     casacore::Bool b1, b2;
     185           0 :     casacore::Float const *src_p = src.getStorage(b1);
     186           0 :     casacore::Complex *dst_p = dst.getStorage(b2);
     187             : 
     188             :     // polarization order assumption (auto, cross, cross, auto)
     189           0 :     casacore::Float const *row0_p = src_p + src_order[0] * n;
     190           0 :     casacore::Float const *row1_p = src_p + src_order[1] * n;
     191           0 :     casacore::Float const *row2_p = src_p + src_order[2] * n;
     192           0 :     casacore::Float const *row3_p = src_p + src_order[3] * n;
     193           0 :     for (ssize_t i = 0; i < n; ++i) {
     194           0 :         dst_p[4 * i].real(row0_p[i]);
     195           0 :         dst_p[4 * i].imag(0.0f);
     196           0 :         casacore::Float fr = row1_p[i];
     197           0 :         casacore::Float fi = row2_p[i];
     198           0 :         dst_p[4 * i + 1].real(fr);
     199           0 :         dst_p[4 * i + 1].imag(fi);
     200           0 :         dst_p[4 * i + 2].real(fr);
     201           0 :         dst_p[4 * i + 2].imag(-fi);
     202           0 :         dst_p[4 * i + 3].real(row3_p[i]);
     203           0 :         dst_p[4 * i + 3].imag(0.0f);
     204             :     }
     205             : 
     206           0 :     src.freeStorage(src_p, b1);
     207           0 :     dst.putStorage(dst_p, b2);
     208           0 : }
     209             : 
     210             : ////// in-place reorder of MatrixColumn
     211             : //template<class T>
     212             : //inline void suffleMatrixColumn(casacore::Matrix<T> const &src,
     213             : //    std::vector<size_t> order) {
     214             : //    ssize_t n = src.nrow();
     215             : //    if (checkOrder(1, src.ncolumn()-1, order)) throw AipsError("Invalid order");
     216             : //    casacore::Matrix<T> const temp = src;
     217             : //  casacore::Bool b1, b2;
     218             : //  T const *src_p = src.getStorage(b1);
     219             : //  T const *temp_p = temp.getStorage(b2);
     220             : //  if (src_p==temp_p) {
     221             : //      throw casacore::AipsError("Failed to generate temp storage");
     222             : //  }
     223             : //  for (ssize_t j = 0; j < order.size(); ++j) {
     224             : //      setValue1(n, temp_p[order[j]*n], src_p[j*n]);
     225             : //  }
     226             : //  src.putStorage(src_p, b1);
     227             : //  temp.freeStorage(temp_p, b2);
     228             : //}
     229             : 
     230             : // get a vector of indices (out_idx) to sort in_data in accending order
     231             : template<typename T>
     232       29942 : inline void getSortIndex(casacore::Vector<T> in_data,
     233             :         std::vector<size_t> &out_idx) {
     234       29942 :     casacore::Vector<size_t> idx_vec(in_data.size());
     235       29942 :     casacore::indgen(idx_vec);
     236       29942 :     idx_vec.tovector(out_idx);
     237             : 
     238       29942 :     std::sort(out_idx.begin(), out_idx.end(),
     239       14384 :             [&in_data](size_t const &i, size_t const &j) -> bool {return in_data[i] < in_data[j];});
     240       29942 : }
     241             : }
     242             : 
     243             : namespace casa { //# NAMESPACE CASA - BEGIN
     244             : namespace sdfiller { //# NAMESPACE SDFILLER - BEGIN
     245             : 
     246             : class DataAccumulator;
     247             : 
     248             : class DataChunk {
     249             : public:
     250             :     friend DataAccumulator;
     251             : 
     252          92 :     DataChunk(casacore::String const &poltype) :
     253          92 :             num_pol_max_(4), num_chan_(0), data_(), flag_(), flag_row_(
     254          92 :                     num_pol_max_, false), tsys_(), tcal_(), weight_(
     255          92 :                     num_pol_max_, 1.0f), sigma_(weight_), poltype_(poltype), valid_pcorr_(), pcorr_type_(), get_chunk_(
     256         184 :                     nullptr), get_num_pol_(nullptr) {
     257             :         POST_START;
     258             : 
     259          92 :         setPolType(poltype);
     260             : 
     261             :         POST_END;
     262          92 :     }
     263             : 
     264         184 :     virtual ~DataChunk() {
     265         184 :     }
     266             : 
     267       14174 :     casacore::String getPolType() const {
     268       14174 :         return poltype_;
     269             :     }
     270             : 
     271             :     void resetPolType(casacore::String const &poltype) {
     272             :         initialize(num_chan_);
     273             :         setPolType(poltype);
     274             :     }
     275             : 
     276             :     casacore::uInt getNumPol() const {
     277             :         return get_num_pol_();
     278             :     }
     279             : 
     280       14174 :     void initialize(size_t num_chan) {
     281       14174 :         num_chan_ = num_chan;
     282       14174 :         casacore::IPosition const shape(2, num_chan_, num_pol_max_);
     283       14174 :         ::resizeTo(data_, shape);
     284       14174 :         ::resizeTo(flag_, shape);
     285       14174 :         ::resizeTo(tsys_, shape);
     286       14174 :         ::resizeTo(tcal_, shape);
     287       14174 :         pcorr_type_.resize(0);
     288       14174 :         tsys_ = -1.0f;
     289       14174 :         tcal_ = -1.0f;
     290       14174 :     }
     291             : 
     292       29942 :     void clear() {
     293       29942 :         num_chan_ = 0;
     294       29942 :         pcorr_type_.resize(0);
     295       29942 :     }
     296             : 
     297             :     bool readyToWrite() {
     298             :         return true;
     299             :     }
     300             : 
     301       28158 :     bool accumulate(DataRecord const &record) {
     302             :         POST_START;
     303             : 
     304       28158 :         if (!isValidRecord(record)) {
     305           0 :             return false;
     306             :         }
     307             : 
     308       28158 :         if (num_pol_max_ < pcorr_type_.size()) {
     309           0 :             return false;
     310             :         }
     311             : 
     312       28158 :         casacore::Vector<casacore::Float> const &data = record.data;
     313       28158 :         if (num_chan_ == 0) {
     314       14174 :             size_t num_chan = data.size();
     315       14174 :             initialize(num_chan);
     316             :         }
     317             : 
     318             :         // Polarization
     319       28158 :         casacore::Stokes::StokesTypes pcorr = record.pol;
     320             :         // check for consistency between pol_type and stokes
     321       28158 :         bool consistent = false;
     322      140790 :         for (size_t i = 0; i < valid_pcorr_.size(); ++i) {
     323      112632 :             consistent |= (valid_pcorr_[i] == (Int) pcorr);
     324             :         }
     325       28158 :         if (!consistent) {
     326           0 :             throw casacore::AipsError(
     327           0 :                     "Got inconsistent polarization with poltype");
     328             :         }
     329             :         // check if pcorr is the new corr type to be added
     330       42142 :         for (size_t i = 0; i < pcorr_type_.size(); ++i) {
     331       13984 :             if (pcorr == pcorr_type_[i]) {
     332           0 :                 throw casacore::AipsError(
     333             :                         "DataChunk already has polarization "
     334           0 :                                 + casacore::Stokes::name(pcorr));
     335             :             }
     336             :         }
     337             :         // new polarization type
     338       28158 :         pcorr_type_.push_back(pcorr);
     339             :         // Matrices in DataRecord is stacked in the order of accumulation
     340       28158 :         size_t const colid = pcorr_type_.size() - 1;
     341             : 
     342       28158 :         casacore::Vector<casacore::Bool> const &flag = record.flag;
     343       28158 :         casacore::Bool flagrow = record.flag_row;
     344             : 
     345       28158 :         if (data.shape() != flag.shape()) {
     346           0 :             return false;
     347             :         }
     348             : 
     349       28158 :         casacore::Vector<casacore::Float> tsys;
     350       28158 :         if (!record.tsys.empty()) {
     351             : //      std::cout << "tsys is not empty: " << record.tsys[0] << std::endl;
     352       28158 :             tsys.assign(record.tsys);
     353             :         }
     354       28158 :         casacore::Vector<casacore::Float> tcal;
     355       28158 :         if (!record.tcal.empty()) {
     356             : //      std::cout << "tcal is not empty: " << record.tcal << std::endl;
     357         990 :             tcal.assign(record.tcal);
     358             :         }
     359             : 
     360       28158 :         if (data.nelements() != num_chan_) {
     361           0 :             return false;
     362             :         }
     363             : 
     364             :         // Filling Matrices[chan, pol] in DataRecord. The Matrices are column (channel) major
     365             :         //data_.column(colid) = data;
     366       28158 :         ::setValueToMatrixColumn(data, colid, data_);
     367             :         //flag_.column(colid) = flag;
     368       28158 :         ::setValueToMatrixColumn(flag, colid, flag_);
     369       28158 :         flag_row_[colid] = flagrow;
     370       28158 :         if (tsys.size() == num_chan_) {
     371             :             //tsys_.column(polid) = tsys;
     372         600 :             ::setValueToMatrixColumn(tsys, colid, tsys_);
     373       27558 :         } else if (!tsys.empty()) {
     374       27558 :             tsys_(0, colid) = tsys[0];
     375             :         }
     376       28158 :         if (tcal.size() == num_chan_) {
     377             :             //tcal_.column(polid) = tcal;
     378         990 :             ::setValueToMatrixColumn(tcal, colid, tcal_);
     379       27168 :         } else if (!tcal.empty()) {
     380           0 :             tcal_(0, colid) = tcal[0];
     381             :         }
     382             : 
     383       28158 :         return true;
     384       28158 :     }
     385             : 
     386       29942 :     bool get(MSDataRecord &record) {
     387       29942 :         bool return_value = get_chunk_(record);
     388       29942 :         return return_value;
     389             :     }
     390             : 
     391             : private:
     392             :     // Functions to return if accumulated corr types are conformant set, e.g.,
     393             :     // liner polarization should have XX and YY for dual pol.
     394             :     // assumption: pcorr_type_ has StokesTypes consistent with poltype_ and
     395             :     // not redundant (assured by accumulate())
     396       29942 :     bool isFullPol() const {
     397       29942 :         return pcorr_type_.size() == 4;
     398             :     }
     399       29942 :     bool isDualPol() const {
     400       29942 :         if (pcorr_type_.size() != 2)
     401       15958 :             return false;
     402       13984 :         casacore::Int pcorr0 = valid_pcorr_[0];
     403       13984 :         casacore::Int pcorr1 = valid_pcorr_[valid_pcorr_.size() - 1];
     404       14384 :         return (pcorr_type_[0] == pcorr0 && pcorr_type_[1] == pcorr1)
     405       14384 :                 || (pcorr_type_[0] == pcorr1 && pcorr_type_[1] == pcorr0);
     406             :     }
     407       15958 :     bool isSinglePol0() const {
     408       15958 :         return (pcorr_type_.size() == 1
     409       15958 :                 && valid_pcorr_[0] == (Int) pcorr_type_[0]);
     410             :     }
     411       15768 :     bool isSinglePol1() const {
     412       15768 :         return (pcorr_type_.size() == 1
     413       15768 :                 && valid_pcorr_[valid_pcorr_.size() - 1] == (Int) pcorr_type_[0]);
     414             :     }
     415       28158 :     bool isValidRecord(DataRecord const &record) {
     416       28158 :         return !record.data.empty() && !record.flag.empty();
     417             :     }
     418          92 :     void setPolType(casacore::String const &poltype) {
     419             :         POST_START;
     420             : 
     421          92 :         poltype_ = poltype;
     422          92 :         if (poltype_ == "linear") {
     423       30034 :             get_chunk_ = [&](MSDataRecord &r) {return DataChunk::getLinear(r);};
     424          92 :             get_num_pol_ = [&]() {return DataChunk::getNumPolLinear();};
     425          92 :             valid_pcorr_.resize(4);
     426          92 :             valid_pcorr_[0] = casacore::Stokes::XX;
     427          92 :             valid_pcorr_[1] = casacore::Stokes::XY;
     428          92 :             valid_pcorr_[2] = casacore::Stokes::YX;
     429          92 :             valid_pcorr_[3] = casacore::Stokes::YY;
     430           0 :         } else if (poltype_ == "circular") {
     431           0 :             get_chunk_ = [&](MSDataRecord &r) {return DataChunk::getCircular(r);};
     432           0 :             get_num_pol_ = [&]() {return DataChunk::getNumPolCircular();};
     433           0 :             valid_pcorr_.resize(4);
     434           0 :             valid_pcorr_[0] = casacore::Stokes::RR;
     435           0 :             valid_pcorr_[1] = casacore::Stokes::RL;
     436           0 :             valid_pcorr_[2] = casacore::Stokes::LR;
     437           0 :             valid_pcorr_[3] = casacore::Stokes::LL;
     438           0 :         } else if (poltype_ == "stokes") {
     439           0 :             get_chunk_ = [&](MSDataRecord &r) {return DataChunk::getStokes(r);};
     440           0 :             get_num_pol_ = [&]() {return DataChunk::getNumPolStokes();};
     441           0 :             valid_pcorr_.resize(4);
     442           0 :             valid_pcorr_[0] = casacore::Stokes::I;
     443           0 :             valid_pcorr_[1] = casacore::Stokes::Q;
     444           0 :             valid_pcorr_[2] = casacore::Stokes::U;
     445           0 :             valid_pcorr_[3] = casacore::Stokes::V;
     446           0 :         } else if (poltype_ == "linpol") {
     447           0 :             get_chunk_ = [&](MSDataRecord &r) {return DataChunk::getLinpol(r);};
     448           0 :             get_num_pol_ = [&]() {return DataChunk::getNumPolLinpol();};
     449           0 :             valid_pcorr_.resize(2);
     450           0 :             valid_pcorr_[0] = casacore::Stokes::Plinear;
     451           0 :             valid_pcorr_[1] = casacore::Stokes::Pangle;
     452             :         } else {
     453           0 :             throw casacore::AipsError(
     454           0 :                     casacore::String("Invalid poltype") + poltype);
     455             :         }
     456             : 
     457             :         POST_END;
     458          92 :     }
     459             :     size_t const num_pol_max_;
     460             :     size_t num_chan_;
     461             :     casacore::Matrix<casacore::Float> data_;
     462             :     casacore::Matrix<casacore::Bool> flag_;
     463             :     casacore::Vector<casacore::Bool> flag_row_;
     464             :     casacore::Matrix<casacore::Float> tsys_;
     465             :     casacore::Matrix<casacore::Float> tcal_;
     466             :     casacore::Vector<casacore::Float> weight_;
     467             :     casacore::Vector<casacore::Float> sigma_;
     468             : 
     469             :     casacore::String poltype_;
     470             :     casacore::Vector<casacore::Int> valid_pcorr_;
     471             :     std::vector<casacore::Stokes::StokesTypes> pcorr_type_;
     472             :     std::function<bool(MSDataRecord &)> get_chunk_;
     473             :     std::function<casacore::uInt()> get_num_pol_;
     474             : 
     475             :     // Tsys and Tcal assignment for 2 & 4 pols. Auto-correlation components of pol should be used.
     476       13984 :     void setTsys2(MSDataRecord &record, std::vector<size_t> order = { }) {
     477             :         // safeguard to avoid processing empty array
     478       13984 :         if (tsys_.empty()) {
     479           0 :             return;
     480             :         }
     481             : 
     482       13984 :         assert(tsys_.ncolumn() == num_pol_max_);
     483       13984 :         if (!setAndCheckOrder(2, tsys_.ncolumn() - 1, order)) {
     484           0 :             throw casacore::AipsError("got invalid order list");
     485             :         }
     486       13984 :         size_t apol0 = order[0], apol1 = order[order.size() - 1];
     487             : 
     488             :         // clear Tsys
     489       13984 :         record.setTsysSize(0, 0);
     490             : 
     491       13984 :         if (num_chan_ == 1) {
     492         200 :             record.setTsysSize(2, 1);
     493         200 :             record.tsys(0, 0) = tsys_(0, apol0);
     494         200 :             record.tsys(1, 0) = tsys_(0, apol1);
     495       13784 :         } else if (casacore::anyGT(tsys_, 0.0f)) {
     496             :             // valid spectral Tsys data are available
     497       10376 :             casacore::IPosition const startpos0(2, 1, apol0);
     498       10376 :             casacore::IPosition const endpos0(2, num_chan_ - 1, apol0);
     499       10376 :             casacore::IPosition const startpos1(2, 1, apol1);
     500       10376 :             casacore::IPosition const endpos1(2, num_chan_ - 1, apol1);
     501       10376 :             if (casacore::anyGT(tsys_(startpos0, endpos0), 0.0f)
     502       10376 :                 || casacore::anyGT(tsys_(startpos1, endpos1), 0.0f)) {
     503             :                 // spectral Tsys
     504         100 :                 record.setTsysSize(2, num_chan_);
     505         200 :                 shuffleTransposeMatrix<casacore::Float, ExecuteMatrix2>(
     506         100 :                         num_chan_, 0, tsys_, record.tsys, { apol0, apol1 });
     507             :             } else {
     508             :                 // valid Tsys data are only for channel 0
     509             :                 // so treat as scalar Tsys
     510       10276 :                 record.setTsysSize(2, 1);
     511       10276 :                 record.tsys(0, 0) = tsys_(0, apol0);
     512       10276 :                 record.tsys(1, 0) = tsys_(0, apol1);
     513             :             }
     514       10376 :         }
     515             :     }
     516             : 
     517       13984 :     void setTcal2(MSDataRecord &record, std::vector<size_t> order = { }) {
     518             :         // safeguard to avoid processing empty array
     519       13984 :         if (tcal_.empty()) {
     520           0 :             return;
     521             :         }
     522             : 
     523       13984 :         assert(tcal_.ncolumn() == num_pol_max_);
     524       13984 :         if (!setAndCheckOrder(2, tcal_.ncolumn()-1, order)) {
     525           0 :             throw casacore::AipsError("got invalid order list");
     526             :         }
     527       13984 :         size_t apol0 = order[0], apol1 = order[order.size() - 1];
     528             : 
     529             :         // clear Tcal
     530       13984 :         record.setTcalSize(0, 0);
     531             : 
     532       13984 :         if (num_chan_ == 1) {
     533         200 :             record.setTcalSize(2, 1);
     534         200 :             record.tcal(0, 0) = tcal_(0, apol0);
     535         200 :             record.tcal(1, 0) = tcal_(0, apol1);
     536       13784 :         } else if (casacore::anyGT(tcal_, 0.0f)) {
     537             :             // valid spectral Tcal data are available
     538         200 :             casacore::IPosition const startpos0(2, 1, apol0);
     539         200 :             casacore::IPosition const endpos0(2, num_chan_ - 1, apol0);
     540         200 :             casacore::IPosition const startpos1(2, 1, apol1);
     541         200 :             casacore::IPosition const endpos1(2, num_chan_ - 1, apol1);
     542         200 :             if (casacore::anyGT(tcal_(startpos0, endpos0), 0.0f)
     543         200 :                 || casacore::anyGT(tcal_(startpos1, endpos1), 0.0f)) {
     544             :                 // spectral Tcal
     545         200 :                 record.setTcalSize(2, num_chan_);
     546         400 :                 shuffleTransposeMatrix<casacore::Float, ExecuteMatrix2>(
     547         200 :                         num_chan_, 0, tcal_, record.tcal, { apol0, apol1 });
     548             :             } else {
     549             :                 // valid Tcal data are only for channel 0
     550             :                 // so treat as scalar Tcal
     551           0 :                 record.setTcalSize(2, 1);
     552           0 :                 record.tcal(0, 0) = tcal_(0, apol0);
     553           0 :                 record.tcal(1, 0) = tcal_(0, apol1);
     554             :             }
     555         200 :         }
     556             :     }
     557             : 
     558         190 :     void setTsys1(MSDataRecord &record, ssize_t start_src) {
     559         190 :         if (tsys_.empty()) {
     560             :             // no Tsys data. do nothing.
     561           0 :             return;
     562         190 :         } else if (num_chan_ == 1) {
     563           0 :             record.setTsysSize(1, 1);
     564           0 :             record.tsys(0, 0) = tsys_(0, start_src);
     565         190 :         } else if (casacore::anyGT(tsys_, 0.0f)) {
     566         190 :             casacore::IPosition const startpos(2, 1, start_src);
     567         190 :             casacore::IPosition const endpos(2, num_chan_ - 1, start_src);
     568         190 :             if (casacore::anyGT(tsys_(startpos, endpos), 0.0f)) {
     569             :                 // should be spectral Tsys
     570           0 :                 record.setTsysSize(1, num_chan_);
     571           0 :                 shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     572           0 :                     start_src, tsys_, record.tsys);
     573             :             } else {
     574             :                 // valid Tsys data are only for channel 0
     575             :                 // so treat as scalar Tsys
     576         190 :                 record.setTsysSize(1, 1);
     577         190 :                 record.tsys(0, 0) = tsys_(0, start_src);
     578             :             }
     579         190 :         }
     580             :     }
     581             : 
     582         190 :     void setTcal1(MSDataRecord &record, ssize_t start_src) {
     583         190 :         if (tcal_.empty()) {
     584             :             // no Tcal data. do nothing.
     585           0 :             return;
     586         190 :         } else if (num_chan_ == 1) {
     587           0 :             record.setTcalSize(1, 1);
     588           0 :             record.tcal(0, 0) = tcal_(0, start_src);
     589         190 :         } else if (casacore::anyGT(tcal_, 0.0f)) {
     590         190 :             casacore::IPosition const startpos(2, 1, start_src);
     591         190 :             casacore::IPosition const endpos(2, num_chan_ - 1, start_src);
     592         190 :             if (casacore::anyGT(tcal_(startpos, endpos), 0.0f)) {
     593             :                 // should be spectral Tcal
     594         190 :                 record.setTcalSize(1, num_chan_);
     595         380 :                 shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     596         190 :                     start_src, tcal_, record.tcal);
     597             :             } else {
     598             :                 // valid Tcal data are only for channel 0
     599             :                 // so treat as scalar Tcal
     600           0 :                 record.setTcalSize(1, 1);
     601           0 :                 record.tcal(0, 0) = tcal_(0, start_src);
     602             :             }
     603         190 :         }
     604             :     }
     605             : 
     606       29942 :     bool getLinear(MSDataRecord &record) {
     607             :         POST_START;
     608             : 
     609       29942 :         casacore::Vector<casacore::Int> const col_stokes(pcorr_type_);
     610       29942 :         std::vector<size_t> pol_idx_order;
     611       29942 :         getSortIndex(col_stokes, pol_idx_order);
     612             : 
     613       29942 :         casacore::Vector<casacore::Float> weight;
     614       29942 :         casacore::Vector<casacore::Float> sigma;
     615       29942 :         if (isFullPol()) {
     616             :             // POL 0, 1, 2, and 3
     617             : //      std::cout << "set data/flag" << std::endl;
     618           0 :             record.setComplex();
     619           0 :             record.setDataSize(4, num_chan_);
     620           0 :             shuffleTransposeMatrix4F2C(num_chan_, data_, record.complex_data,
     621             :                     pol_idx_order);
     622           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix4X>(num_chan_,
     623           0 :                     0, flag_, record.flag, pol_idx_order);
     624           0 :             record.flag_row = anyEQ(flag_row_, true);
     625             : //      std::cout << "weight = " << record.weight << std::endl;
     626             : 
     627             : //      std::cout << "set tsys" << std::endl;
     628           0 :             setTsys2(record, pol_idx_order);
     629             : 
     630             : //      std::cout << "set tcal " << tcal_ << std::endl;
     631           0 :             setTcal2(record, pol_idx_order);
     632             : 
     633           0 :             record.num_pol = 4;
     634       29942 :         } else if (isDualPol()) {
     635             :             // POL 0 and 1
     636             : //      std::cout << "set data/flag" << std::endl;
     637       13984 :             record.setFloat();
     638       13984 :             record.setDataSize(2, num_chan_);
     639       27968 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix2>(num_chan_,
     640       13984 :                     0, data_, record.float_data, pol_idx_order);
     641       27968 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix2>(num_chan_, 0,
     642       13984 :                     flag_, record.flag, pol_idx_order);
     643       13984 :             record.flag_row = flag_row_[0] || flag_row_[1];
     644             : //      std::cout << "weight = " << record.weight << std::endl;
     645             : 
     646             : //      std::cout << "set tsys" << std::endl;
     647       13984 :             setTsys2(record, pol_idx_order);
     648             : 
     649             : //      std::cout << "set tcal " << tcal_ << std::endl;
     650       13984 :             setTcal2(record, pol_idx_order);
     651             : 
     652       13984 :             record.num_pol = 2;
     653       15958 :         } else if (isSinglePol0()) {
     654             :             // only POL 0
     655             : //      std::cout << "set data/flag (pol 0)" << std::endl;
     656         190 :             record.setFloat();
     657         190 :             record.setDataSize(1, num_chan_);
     658         380 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     659         190 :                     0, data_, record.float_data, pol_idx_order);
     660         380 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix1>(num_chan_, 0,
     661         190 :                     flag_, record.flag, pol_idx_order);
     662         190 :             record.flag_row = flag_row_(0);
     663             : 
     664         190 :             setTsys1(record, 0);
     665             : 
     666             : //      std::cout << "set tcal " << tcal_ << std::endl;
     667         190 :             setTcal1(record, 0);
     668             : 
     669         190 :             record.num_pol = 1;
     670       15768 :         } else if (isSinglePol1()) {
     671             :             // only POL 1
     672             : //      std::cout << "set data/flag (pol 1)" << std::endl;
     673           0 :             record.setFloat();
     674           0 :             record.setDataSize(1, num_chan_);
     675           0 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     676           0 :                     0, data_, record.float_data, pol_idx_order);
     677           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix1>(num_chan_, 0,
     678           0 :                     flag_, record.flag, pol_idx_order);
     679           0 :             record.flag_row = flag_row_(1);
     680             : 
     681           0 :             setTsys1(record, 0);
     682             : 
     683             : //      std::cout << "set tcal " << tcal_ << std::endl;
     684           0 :             setTcal1(record, 0);
     685             : 
     686           0 :             record.num_pol = 1;
     687       15768 :         } else if (pcorr_type_.size() == 0) {
     688             : //      std::cout << "DataChunk is not ready for get" << std::endl;
     689       15768 :             return false;
     690             :         } else {// means strange combination of polarization types in DataChunk
     691           0 :             throw AipsError("non-conforming combination of polarization accumulated");
     692             :         }
     693       42332 :         for (casacore::Int i = 0; i < record.num_pol; ++i) {
     694       28158 :             record.corr_type[i] = col_stokes[pol_idx_order[i]];
     695             :         }
     696             : 
     697             :         POST_END;
     698       14174 :         return true;
     699       29942 :     }
     700             : 
     701           0 :     bool getCircular(MSDataRecord &record) {
     702           0 :         return getLinear(record);
     703             :     }
     704             : 
     705           0 :     bool getStokes(MSDataRecord &record) {
     706             :         POST_START;
     707             : 
     708           0 :         casacore::Vector<casacore::Int> const col_stokes(pcorr_type_);
     709           0 :         std::vector<size_t> pol_idx_order;
     710           0 :         getSortIndex(col_stokes, pol_idx_order);
     711             : 
     712           0 :         record.setFloat();
     713           0 :         if (isFullPol()) {
     714           0 :             record.setDataSize(4, num_chan_);
     715           0 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix4>(num_chan_,
     716           0 :                     0, data_, record.float_data, pol_idx_order);
     717           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix4>(num_chan_, 0,
     718           0 :                     flag_, record.flag, pol_idx_order);
     719           0 :             record.flag_row = anyTrue(flag_row_);
     720             : 
     721           0 :             record.num_pol = 4;
     722           0 :         } else if (isSinglePol0()) {
     723           0 :             record.setDataSize(1, num_chan_);
     724           0 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     725           0 :                     0, data_, record.float_data, pol_idx_order);
     726           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix1>(num_chan_, 0,
     727           0 :                     flag_, record.flag, pol_idx_order);
     728           0 :             record.flag_row = flag_row_[0];
     729             : 
     730           0 :             record.num_pol = 1;
     731           0 :         } else if (pcorr_type_.size() == 0) {
     732           0 :             return false;
     733             :         } else {// means strange combination of polarization types in DataChunk
     734           0 :             throw AipsError("non-conforming combination of polarization accumulated");
     735             :         }
     736           0 :         for (casacore::Int i = 0; i < record.num_pol; ++i) {
     737           0 :             record.corr_type[i] = col_stokes[pol_idx_order[i]];
     738             :         }
     739             : 
     740             :         POST_END;
     741           0 :         return true;
     742           0 :     }
     743             : 
     744           0 :     bool getLinpol(MSDataRecord &record) {
     745             :         POST_START;
     746             : 
     747           0 :         casacore::Vector<casacore::Int> const col_stokes(pcorr_type_);
     748           0 :         std::vector<size_t> pol_idx_order;
     749           0 :         getSortIndex(col_stokes, pol_idx_order);
     750             : 
     751           0 :         record.setFloat();
     752           0 :         if (isDualPol()) {
     753             :             // POL 0 and 1
     754           0 :             record.setDataSize(2, num_chan_);
     755           0 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix2>(num_chan_,
     756           0 :                     0, data_, record.float_data, pol_idx_order);
     757           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix2>(num_chan_, 0,
     758           0 :                     flag_, record.flag, pol_idx_order);
     759           0 :             record.flag_row = flag_row_[0] || flag_row_[1];
     760           0 :             record.num_pol = 2;
     761           0 :         } else if (isSinglePol0()) {
     762           0 :             record.setDataSize(1, num_chan_);
     763           0 :             shuffleTransposeMatrix<casacore::Float, ExecuteMatrix1>(num_chan_,
     764           0 :                     0, data_, record.float_data, pol_idx_order);
     765           0 :             shuffleTransposeMatrix<casacore::Bool, ExecuteMatrix1>(num_chan_, 0,
     766           0 :                     flag_, record.flag, pol_idx_order);
     767           0 :             record.flag_row = flag_row_[0];
     768             : 
     769           0 :             record.num_pol = 1;
     770           0 :         } else if (pcorr_type_.size() == 0) {
     771           0 :             return false;
     772             :         } else {// means strange combination of polarization types in DataChunk
     773           0 :             throw AipsError("non-conforming combination of polarization accumulated");
     774             :         }
     775           0 :         for (casacore::Int i = 0; i < record.num_pol; ++i) {
     776           0 :             record.corr_type[i] = col_stokes[pol_idx_order[i]];
     777             :         }
     778             : 
     779             :         POST_END;
     780           0 :         return true;
     781           0 :     }
     782             : 
     783           0 :     casacore::uInt getNumPolLinear() const {
     784           0 :         if (isFullPol()) {
     785           0 :             return 4;
     786           0 :         } else if (isDualPol()) {
     787           0 :             return 2;
     788           0 :         } else if (isSinglePol0() || isSinglePol1()) {
     789           0 :             return 1;
     790             :         } else {
     791           0 :             return 0;
     792             :         }
     793             :     }
     794             : 
     795           0 :     casacore::uInt getNumPolCircular() const {
     796           0 :         return getNumPolLinear();
     797             :     }
     798             : 
     799           0 :     casacore::uInt getNumPolStokes() const {
     800           0 :         if (isFullPol()) {
     801           0 :             return 4;
     802           0 :         } else if (isSinglePol0()) {
     803           0 :             return 1;
     804             :         } else {
     805           0 :             return 0;
     806             :         }
     807             :     }
     808             : 
     809           0 :     casacore::uInt getNumPolLinpol() const {
     810           0 :         if (isDualPol()) {
     811           0 :             return 2;
     812           0 :         } else if (isSinglePol0()) {
     813           0 :             return 1;
     814             :         } else {
     815           0 :             return 0;
     816             :         }
     817             :     }
     818             : };
     819             : 
     820             : class DataAccumulator {
     821             : private:
     822             :     struct DataAccumulatorKey {
     823             :         casacore::Int antenna_id;
     824             :         casacore::Int field_id;
     825             :         casacore::Int feed_id;
     826             :         casacore::Int spw_id;
     827             :         casacore::String pol_type;
     828             :         casacore::String intent;
     829             : 
     830             :         template<class T, class C>
     831      623786 :         bool comp(T const &a, T const &b, C const &c) const {
     832      623786 :             if (a < b) {
     833       56685 :                 return true;
     834      567101 :             } else if (a == b) {
     835      532744 :                 return c();
     836             :             } else {
     837       34357 :                 return false;
     838             :             }
     839             :         }
     840             : 
     841      147174 :         bool operator()(DataAccumulatorKey const &lhs,
     842             :                 DataAccumulatorKey const &rhs) const {
     843      294348 :             return comp(lhs.antenna_id, rhs.antenna_id,
     844      102942 :                     [&]() {return comp(lhs.field_id, rhs.field_id,
     845      102942 :                                 [&]() {return comp(lhs.feed_id, rhs.feed_id,
     846      102942 :                                             [&]() {return comp(lhs.spw_id, rhs.spw_id,
     847       83893 :                                                         [&]() {return comp(lhs.pol_type, rhs.pol_type,
     848      560505 :                                                                     [&]() {return comp(lhs.intent, rhs.intent,
     849     1303704 :                                                                                 []() {return false;});});});});});});
     850             :         }
     851             :     };
     852             : 
     853             : public:
     854           7 :     DataAccumulator() :
     855          14 :             pool_(), antenna_id_(), spw_id_(), field_id_(), feed_id_(), scan_(), subscan_(), intent_(), direction_(), interval_(), indexer_(), time_(
     856          21 :                     -1.0), is_free_() {
     857           7 :     }
     858             : 
     859           7 :     virtual ~DataAccumulator() {
     860             :         POST_START;
     861             : 
     862          99 :         for (auto iter = pool_.begin(); iter != pool_.end(); ++iter) {
     863          92 :             delete *iter;
     864             :         }
     865             : 
     866             :         POST_END;
     867           7 :     }
     868             : 
     869        2078 :     size_t getNumberOfChunks() const {
     870        2078 :         return pool_.size();
     871             :     }
     872             : 
     873             :     size_t getNumberOfActiveChunks() const {
     874             :         return std::count_if(pool_.begin(), pool_.end(),
     875             :                 [](DataChunk * const &c) {
     876             :                     return c->getNumPol() > 0;
     877             :                 });
     878             :     }
     879             : 
     880             :     bool queryForGet(DataRecord const &record) const {
     881             :         casacore::Double const time = record.time;
     882             :         bool is_ready = (0.0 <= time_) && !(time_ == time);
     883             :         return is_ready;
     884             :     }
     885             : 
     886       28158 :     bool queryForGet(casacore::Double const &time) const {
     887       28158 :         bool is_ready = (0.0 <= time_) && !(time_ == time);
     888       28158 :         return is_ready;
     889             :     }
     890             : 
     891        2078 :     void clear() {
     892       32020 :         for (auto iter = pool_.begin(); iter != pool_.end(); ++iter) {
     893       29942 :             (*iter)->clear();
     894             :         }
     895        2078 :         time_ = -1.0;
     896        2078 :     }
     897             : 
     898       29942 :     bool get(size_t ichunk, MSDataRecord &record) {
     899             :         POST_START;
     900             : 
     901       29942 :         if (pool_.size() == 0) {
     902           0 :             return false;
     903       29942 :         } else if (ichunk >= pool_.size()) {
     904           0 :             return false;
     905             :         }
     906       29942 :         bool status = pool_[ichunk]->get(record);
     907             : //    std::cout << "get Chunk status = " << status << std::endl;
     908       29942 :         if (!status) {
     909       15768 :             record.clear();
     910       15768 :             return status;
     911             :         }
     912       14174 :         record.time = time_;
     913       14174 :         record.pol_type = pool_[ichunk]->getPolType();
     914       14174 :         record.antenna_id = antenna_id_[ichunk];
     915       14174 :         record.spw_id = spw_id_[ichunk];
     916       14174 :         record.field_id = field_id_[ichunk];
     917       14174 :         record.feed_id = feed_id_[ichunk];
     918       14174 :         record.scan = scan_[ichunk];
     919       14174 :         record.subscan = subscan_[ichunk];
     920       14174 :         record.intent = intent_[ichunk];
     921       14174 :         record.direction = direction_[ichunk];
     922       14174 :         record.interval = interval_[ichunk];
     923       14174 :         record.temperature = temperature_[ichunk];
     924       14174 :         record.pressure = pressure_[ichunk];
     925       14174 :         record.rel_humidity = rel_humidity_[ichunk];
     926       14174 :         record.wind_speed = wind_speed_[ichunk];
     927       14174 :         record.wind_direction = wind_direction_[ichunk];
     928             : 
     929             :         POST_END;
     930       14174 :         return status;
     931             :     }
     932             : 
     933       28158 :     bool accumulate(DataRecord const &record) {
     934             :         POST_START;
     935             : 
     936       28158 :         if (!isValidRecord(record)) {
     937             : //      std::cout << "record is not a valid one" << std::endl;
     938           0 :             return false;
     939             :         }
     940             : 
     941       28158 :         casacore::Double time = record.time;
     942       28158 :         if (time_ < 0.0) {
     943        2078 :             time_ = time;
     944             :         }
     945       28158 :         if (time_ != time) {
     946             : //      std::cout << "timestamp mismatch" << std::endl;
     947           0 :             return false;
     948             :         }
     949       28158 :         casacore::Int antennaid = record.antenna_id;
     950       28158 :         casacore::Int spwid = record.spw_id;
     951       28158 :         casacore::Int fieldid = record.field_id;
     952       28158 :         casacore::Int feedid = record.feed_id;
     953       28158 :         casacore::Int scan = record.scan;
     954       28158 :         casacore::Int subscan = record.subscan;
     955       28158 :         casacore::String intent = record.intent;
     956       28158 :         casacore::String poltype = record.pol_type;
     957       28158 :         DataAccumulatorKey key;
     958       28158 :         key.antenna_id = record.antenna_id;
     959       28158 :         key.field_id = record.field_id;
     960       28158 :         key.feed_id = record.feed_id;
     961       28158 :         key.spw_id = record.spw_id;
     962       28158 :         key.intent = record.intent;
     963       28158 :         key.pol_type = record.pol_type;
     964       28158 :         casacore::Matrix<casacore::Double> const &direction = record.direction;
     965       28158 :         casacore::Double interval = record.interval;
     966       28158 :         casacore::Float temperature = record.temperature;
     967       28158 :         casacore::Float pressure = record.pressure;
     968       28158 :         casacore::Float rel_humidity = record.rel_humidity;
     969       28158 :         casacore::Float wind_speed = record.wind_speed;
     970       28158 :         casacore::Float wind_direction = record.wind_direction;
     971       28158 :         bool status = false;
     972       28158 :         auto iter = indexer_.find(key);
     973             : //        std::cout << "(ant, spw, pol, pol_type, field, feed, intent) = ("
     974             : //                << key.antenna_id << ", " << key.spw_id << ", " << record.pol<< ", " << key.pol_type << ", " << key.field_id << ", " << key.feed_id
     975             : //                << ", " << key.intent << ", "
     976             : //                << std::endl;
     977       28158 :         if (iter != indexer_.end()) {
     978       28066 :             casacore::uInt index = iter->second;
     979       28066 :             status = pool_[index]->accumulate(record);
     980       28066 :             if (status) {
     981       28066 :                 antenna_id_[index] = antennaid;
     982       28066 :                 spw_id_[index] = spwid;
     983       28066 :                 field_id_[index] = fieldid;
     984       28066 :                 feed_id_[index] = feedid;
     985       28066 :                 scan_[index] = scan;
     986       28066 :                 subscan_[index] = subscan;
     987       28066 :                 intent_[index] = intent;
     988       28066 :                 direction_[index].assign(direction);
     989       28066 :                 interval_[index] = interval;
     990       28066 :                 temperature_[index] = temperature;
     991       28066 :                 pressure_[index] = pressure;
     992       28066 :                 rel_humidity_[index] = rel_humidity;
     993       28066 :                 wind_speed_[index] = wind_speed;
     994       28066 :                 wind_direction_[index] = wind_direction;
     995             :             }
     996             :         } else {
     997          92 :             pool_.push_back(new DataChunk(poltype));
     998          92 :             antenna_id_.push_back(-1);
     999          92 :             spw_id_.push_back(-1);
    1000          92 :             field_id_.push_back(-1);
    1001          92 :             feed_id_.push_back(-1);
    1002          92 :             scan_.push_back(-1);
    1003          92 :             subscan_.push_back(-1);
    1004          92 :             intent_.push_back("");
    1005          92 :             direction_.push_back(casacore::Matrix<casacore::Double>());
    1006          92 :             interval_.push_back(-1.0);
    1007          92 :             temperature_.push_back(0.0f);
    1008          92 :             pressure_.push_back(0.0f);
    1009          92 :             rel_humidity_.push_back(0.0f);
    1010          92 :             wind_speed_.push_back(0.0f);
    1011          92 :             wind_direction_.push_back(0.0f);
    1012          92 :             casacore::uInt index = pool_.size() - 1;
    1013          92 :             indexer_[key] = index;
    1014          92 :             status = pool_[index]->accumulate(record);
    1015          92 :             if (status) {
    1016          92 :                 antenna_id_[index] = antennaid;
    1017          92 :                 spw_id_[index] = spwid;
    1018          92 :                 field_id_[index] = fieldid;
    1019          92 :                 feed_id_[index] = feedid;
    1020          92 :                 scan_[index] = scan;
    1021          92 :                 subscan_[index] = subscan;
    1022          92 :                 intent_[index] = intent;
    1023          92 :                 direction_[index].assign(direction);
    1024          92 :                 interval_[index] = interval;
    1025          92 :                 temperature_[index] = temperature;
    1026          92 :                 pressure_[index] = pressure;
    1027          92 :                 rel_humidity_[index] = rel_humidity;
    1028          92 :                 wind_speed_[index] = wind_speed;
    1029          92 :                 wind_direction_[index] = wind_direction;
    1030             :             }
    1031             :         }
    1032             : 
    1033             : //    std::cout << "status = " << status << std::endl;
    1034             : //    std::cout << "key (a" << key.antenna_id << ",f" << key.field_id << ",s"
    1035             : //        << key.spw_id << ",i" << key.intent << ",p" << key.pol_type << ",d"
    1036             : //        << key.feed_id << "(index " << indexer_[key] << "): TIME="
    1037             : //        << time_ << " INTERVAL=" << interval << " polno=" << record.pol << std::endl;
    1038             :         POST_END;
    1039       28158 :         return status;
    1040       28158 :     }
    1041             : 
    1042             :     casacore::String getPolType(size_t ichunk) const {
    1043             :         assert(ichunk < pool_.size());
    1044             :         return pool_[ichunk]->getPolType();
    1045             :     }
    1046             : 
    1047             :     casacore::uInt getNumPol(size_t ichunk) const {
    1048             :         assert(ichunk < pool_.size());
    1049             :         return pool_[ichunk]->getNumPol();
    1050             :     }
    1051             : 
    1052             : private:
    1053       28158 :     bool isValidRecord(DataRecord const &record) {
    1054             : //    std::cout << record.time << " " << record.interval << " "
    1055             : //        << record.antenna_id << " " << record.field_id << " " << record.feed_id
    1056             : //        << " " << record.spw_id << " " << record.scan << " " << record.subscan
    1057             : //        << " " << record.direction << std::endl;
    1058       28158 :         return record.time > 0.0 && record.interval > 0.0
    1059       28158 :                 && record.antenna_id >= 0 && record.field_id >= 0
    1060       28158 :                 && record.feed_id >= 0 && record.spw_id >= 0 && record.scan >= 0
    1061       56316 :                 && record.subscan >= 0 && !record.direction.empty();
    1062             :     }
    1063             : 
    1064             :     std::vector<DataChunk *> pool_;
    1065             :     std::vector<casacore::Int> antenna_id_;
    1066             :     std::vector<casacore::Int> spw_id_;
    1067             :     std::vector<casacore::Int> field_id_;
    1068             :     std::vector<casacore::Int> feed_id_;
    1069             :     std::vector<casacore::Int> scan_;
    1070             :     std::vector<casacore::Int> subscan_;
    1071             :     std::vector<casacore::String> intent_;
    1072             :     std::vector<casacore::Matrix<casacore::Double> > direction_;
    1073             :     std::vector<casacore::Double> interval_;
    1074             :     std::vector<casacore::Float> temperature_;
    1075             :     std::vector<casacore::Float> pressure_;
    1076             :     std::vector<casacore::Float> rel_humidity_;
    1077             :     std::vector<casacore::Float> wind_speed_;
    1078             :     std::vector<casacore::Float> wind_direction_;
    1079             :     std::map<DataAccumulatorKey, casacore::uInt, DataAccumulatorKey> indexer_;
    1080             :     casacore::Double time_;
    1081             :     std::vector<bool> is_free_;
    1082             : };
    1083             : 
    1084             : } //# NAMESPACE SDFILLER - END
    1085             : } //# NAMESPACE CASA - END
    1086             : 
    1087             : #endif /* SINGLEDISH_FILLER_DATAACCUMULATOR_H_ */

Generated by: LCOV version 1.16