LCOV - code coverage report
Current view: top level - msvis/MSVis - AveragingTvi2.cc (source / functions) Hit Total Coverage
Test: casa_coverage.info Lines: 774 903 85.7 %
Date: 2023-10-25 08:47:59 Functions: 114 140 81.4 %

          Line data    Source code
       1             : #include <casacore/casa/Arrays/ArrayMath.h>
       2             : #include <casacore/casa/Arrays/ArrayPartMath.h>
       3             : #include <casacore/casa/BasicMath/Functors.h>
       4             : #include <stdcasa/UtilJ.h>
       5             : #include <msvis/MSVis/AveragingTvi2.h>
       6             : #include <msvis/MSVis/AveragingVi2Factory.h>
       7             : #include <msvis/MSVis/MsRows.h>
       8             : #include <msvis/MSVis/VisBufferComponents2.h>
       9             : #include <msvis/MSVis/VisBuffer2.h>
      10             : #include <msvis/MSVis/VisBufferImpl2.h>
      11             : #include <msvis/MSVis/Vbi2MsRow.h>
      12             : #include <msvis/MSVis/VisibilityIterator2.h>
      13             : #include <tuple>
      14             : #include <set>
      15             : 
      16             : using std::set;
      17             : 
      18             : using namespace casacore;
      19             : namespace casa {
      20             : 
      21             : namespace vi {
      22             : 
      23             : namespace avg {
      24             : 
      25             : using casa::ms::MsRow;
      26             : 
      27             : 
      28             : ///////////////////////////////////////////////////////////
      29             : //
      30             : // VbAvg: Averaging VisBuffer
      31             : //
      32             : /*
      33             : 
      34             : Definition: A baseline sample (baseline for short) is a table row
      35             : with a particular (antenna1, antenna2) pair at a particular time.
      36             : 
      37             : 
      38             : Averaging does not cross chunk boundaries of the input VI so the
      39             : input VI determines what values are averaged together.  For example,
      40             : if the input VI is allows data from multiple scans into the same chunk
      41             : then some averaging across scans can occur; in this case the scan number
      42             : of the result will be the scan number of the first baseline instance
      43             : seen.
      44             : 
      45             : Row-level value treatment
      46             : =========================
      47             : 
      48             : The average is approximately computed on a per baseline basis:
      49             : 
      50             : averaged_baseline (antenna1, antenna2) =
      51             :     sumOverAveragingInterval (baseline (antenna1, antenna2)) /
      52             :     nBaselinesFoundInInterval
      53             : 
      54             : How row-level values are computed
      55             : ---------------------------------
      56             : 
      57             : Time - Set to time of first baseline making up the average plus
      58             :        half of the averaging interval.
      59             : Antenna1 - Copied from instance of baseline
      60             : Antenna2 - Copied from instance of baseline
      61             : Feed1 - Copied from instance of baseline
      62             : Feed2 - Copied from instance of baseline
      63             : Flag_Row - The flag row is the logical "and" of the flag rows
      64             :            averaged together.
      65             : Data_Desc_Id - Copied from instance of baseline
      66             : Processor_Id - Copied from instance of baseline
      67             : Field_Id - Copied from instance of baseline
      68             : Interval - Set to averaging interval
      69             : Exposure - Minimum of the interval and the sum of the exposures
      70             :            from unflagged rows
      71             : Time_Centroid - sum (timeCentroid[i] * exposure[i]) / sum (exposure[i])
      72             : Scan_Number - Copied from instance of baseline
      73             : Sigma - ???
      74             : Array_Id - Copied from instance of baseline
      75             : Observation_Id - Copied from instance of baseline
      76             : State_Id - Copied from instance of baseline
      77             : Uvw - Weighted average of the UVW values for the baseline
      78             : Weight - ???
      79             : 
      80             : Cube-level value treatment
      81             : --------------------------
      82             : 
      83             : For each baseline (i.e., antenna1, antenna2 pair) the average is
      84             : computed for each correlation (co) and channel (ch) of the data cube.
      85             : 
      86             : Data - sum (f(weightSpectrum (co, ch)) * data (co, ch)) /
      87             :        sum (f(weightSpectrum (co, ch)))
      88             :        f :== optional function applied to the weights; default is unity function.
      89             : Corrected_Data - Same was for Data however, VI setup can disable producing
      90             :                  averaged Corrected_Data
      91             : Model_Data - Same was for Data however, VI setup can disable producing
      92             :              averaged Model_Data
      93             : Weight_Spectrum - sum (weightSpectrum (co, ch))
      94             : Flag - Each averaged flag (correlation, channel) is the logical "and"
      95             :        of the flag (correlation, channel) making up the average.
      96             : 
      97             : */
      98             : 
      99             : 
     100             : class BaselineIndex {
     101             : 
     102             : public:
     103             : 
     104             :     // make noncopyable...
     105             :     BaselineIndex( const BaselineIndex& ) = delete;
     106             :     BaselineIndex& operator=( const BaselineIndex& ) = delete;
     107             : 
     108             :     BaselineIndex ();
     109             :     ~BaselineIndex ();
     110             : 
     111             :     Int operator () (Int antenna1, Int antenna2, Int spectralWindow);
     112             :     void configure (Int nAntennas, Int nSpw, const VisBuffer2 * vb);
     113             : 
     114             : 
     115             : private:
     116             : 
     117             :     enum {Empty = -1};
     118             : 
     119             :     class SpwIndex : public Matrix<Int>{
     120             : 
     121             :     public:
     122             : 
     123       14709 :         SpwIndex (Int n) : Matrix<Int> (n, n, Empty) {}
     124             : 
     125             :         Int
     126    11224050 :         getBaselineNumber (Int antenna1, Int antenna2, Int & nBaselines)
     127             :         {
     128    11224050 :             Int i = (* this) (antenna1, antenna2);
     129             : 
     130    11224050 :             if (i == Empty){
     131             : 
     132      277570 :                 i = nBaselines ++;
     133      277570 :                 (* this) (antenna1, antenna2) = i;
     134             :             }
     135             : 
     136    11224050 :             return i;
     137             :         }
     138             : 
     139             :     private:
     140             : 
     141             :     };
     142             : 
     143             :     typedef vector<SpwIndex *> Index;
     144             : 
     145             :     SpwIndex * addSpwIndex (Int spw);
     146             :     Matrix<Int> * createMatrix ();
     147             :     void destroy();
     148             :     SpwIndex * getSpwIndex (Int spw);
     149             : 
     150             :     Index index_p;
     151             :     Int nAntennas_p;
     152             :     Int nBaselines_p;
     153             :     Int nSpw_p;
     154             : 
     155             : };
     156             : 
     157         362 : BaselineIndex::BaselineIndex ()
     158             : : nAntennas_p (0),
     159             :   nBaselines_p (0),
     160         362 :   nSpw_p (0)
     161         362 : {}
     162             : 
     163         362 : BaselineIndex::~BaselineIndex ()
     164             : {
     165         362 :     destroy();
     166         362 : }
     167             : 
     168             : Int
     169    11224050 : BaselineIndex::operator () (Int antenna1, Int antenna2, Int spectralWindow)
     170             : {
     171    11224050 :     SpwIndex * spwIndex = getSpwIndex (spectralWindow);
     172    11224050 :     if (spwIndex == 0){
     173           0 :         addSpwIndex (spectralWindow);
     174             :     }
     175             : 
     176    11224050 :     Int i = spwIndex->getBaselineNumber (antenna1, antenna2, nBaselines_p);
     177             : 
     178    11224050 :     return i;
     179             : }
     180             : 
     181             : 
     182             : 
     183             : BaselineIndex::SpwIndex *
     184       14709 : BaselineIndex::addSpwIndex (Int i)
     185             : {
     186             :     // Delete an existing SpwIndex so that we start fresh
     187             : 
     188       14709 :     delete index_p [i];
     189             : 
     190             :     // Create a new SpwIndex and insert it into the main index.
     191             : 
     192       14709 :     index_p [i] = new SpwIndex (nAntennas_p);
     193             : 
     194       14709 :     return index_p [i];
     195             : }
     196             : 
     197             : void
     198       14667 : BaselineIndex::configure (Int nAntennas, Int nSpw, const VisBuffer2 * vb)
     199             : {
     200             :     // Capture the shape parameters
     201             : 
     202       14667 :     nAntennas_p = nAntennas;
     203       14667 :     nSpw_p = nSpw;
     204       14667 :     nBaselines_p = 0;
     205             : 
     206             :     // Get rid of the existing index
     207             : 
     208       14667 :     destroy ();
     209       14667 :     index_p = Index (nSpw_p, (SpwIndex *) 0);
     210             : 
     211             :     // Fill out the index based on the contents of the first VB.
     212             :     // Usually this will determine the pattern for all of the VBs to be
     213             :     // averaged together so that is the ordering the index should
     214             :     // capture.
     215             : 
     216      312511 :     for (rownr_t i = 0; i < vb->nRows(); i++){
     217             : 
     218             :         // Eagerly flesh out the Spw's index
     219             : 
     220      297844 :         Int spw = vb->spectralWindows() (i);
     221      297844 :         Int antenna1 = vb->antenna1()(i);
     222      297844 :         Int antenna2 = vb->antenna2()(i);
     223             : 
     224      297844 :         (* this) (antenna1, antenna2, spw);
     225             :     }
     226       14667 : }
     227             : 
     228             : void
     229       15029 : BaselineIndex::destroy ()
     230             : {
     231             :     // Delete all the dynamically allocated spectral window indices.
     232             :     // The vector destructor will take care of index_p itself.
     233             : 
     234       87514 :     for (Index::iterator i = index_p.begin();
     235       87514 :          i != index_p.end();
     236       72485 :          i++){
     237             : 
     238       72485 :         delete (* i);
     239             :     }
     240       15029 : }
     241             : 
     242             : BaselineIndex::SpwIndex *
     243    11224050 : BaselineIndex::getSpwIndex (Int spw)
     244             : {
     245    11224050 :     AssertCc (spw < (int) index_p.size());
     246             : 
     247    11224050 :     SpwIndex * spwIndex = index_p [spw];
     248             : 
     249    11224050 :     if (spwIndex == 0){
     250       14709 :         spwIndex = addSpwIndex (spw);
     251             :     }
     252             : 
     253    11224050 :     return spwIndex;
     254             : }
     255             : 
     256             : template <typename T>
     257             : class PrefilledMatrix {
     258             : 
     259             : public:
     260             : 
     261        1086 :     PrefilledMatrix () : matrix_p (0, 0, 0), nChannels_p (0), nCorrelations_p (0) {}
     262             : 
     263             :     const Matrix<T> &
     264     1956556 :     getMatrix (Int nCorrelations, Int nChannels, const T & value)
     265             :     {
     266     1956556 :         if (nCorrelations != nCorrelations_p || nChannels != nChannels_p ||
     267     1955389 :             value != value_p){
     268             : 
     269        1167 :             nCorrelations_p = nCorrelations;
     270        1167 :             nChannels_p = nChannels;
     271        1167 :             value_p = value;
     272             : 
     273        1167 :             matrix_p.assign (Matrix<T> (nCorrelations_p, nChannels_p, value_p));
     274             :         }
     275             : 
     276     1956556 :         return matrix_p;
     277             :     }
     278             : 
     279             : private:
     280             : 
     281             :     Matrix<T> matrix_p;
     282             :     Int nChannels_p;
     283             :     Int nCorrelations_p;
     284             :     T value_p;
     285             : 
     286             : };
     287             : 
     288             : template <typename T>
     289             : class CachedPlaneAvg : public ms::CachedArrayBase {
     290             : 
     291             : public:
     292             : 
     293             : typedef const Cube<T> & (casa::vi::avg::VbAvg::* Accessor) () const;
     294             : 
     295      606549 : CachedPlaneAvg (Accessor accessor) : accessor_p (accessor) {}
     296             : 
     297             : Matrix<T> &
     298    11444150 : getCachedPlane (casa::vi::avg::VbAvg * vb, Int row)
     299             : {
     300    11444150 :     if (! isCached()){
     301             : 
     302             :         //cache_p.reference ((vb ->* accessor_p)().xyPlane (row)); // replace with something more efficient
     303    10929663 :         referenceMatrix (cache_p, (vb ->* accessor_p)(), row);
     304    10929663 :         setCached ();
     305             :     }
     306             : 
     307    11444150 :     return cache_p;
     308             : }
     309             : 
     310             : private:
     311             : 
     312             :     static void
     313    10929663 :     referenceMatrix (Matrix<T> & cache, const Cube<T> & src, Int row)
     314             :     {
     315    21859326 :         IPosition shape = src.shape ();
     316    10929663 :         shape.resize (2);
     317             : 
     318             :         // This is a bit sleazy but it seems to be helpful to performance.
     319             :         // Assumes contiguously stored cube.
     320             : 
     321    10929663 :         T * storage = const_cast <T *> (& src (IPosition (3, 0, 0, row)));
     322             : 
     323    10929663 :         cache.takeStorage (shape, storage, casacore::SHARE);
     324    10929663 :     }
     325             : 
     326             :     Accessor accessor_p;
     327             :     Matrix<T> cache_p;
     328             : };
     329             : 
     330             : 
     331             : class VbAvg;
     332             : 
     333             : /**
     334             :  * Holds multiple rows in a buffer. changeRow() alternates between rows. The details
     335             :  * of how the rows are handled need to be traced to its parent class, Vbi2MsRow, and its
     336             :  * parent MsRow.
     337             :  */
     338             : class MsRowAvg : public ms::Vbi2MsRow {
     339             : 
     340             : public:
     341             : 
     342             :     MsRowAvg (rownr_t row, const VbAvg * vb);
     343             : 
     344             :     // Constructor for read/write access
     345             : 
     346             :     MsRowAvg (rownr_t row, VbAvg * vb);
     347             : 
     348     1213098 :     virtual ~MsRowAvg () {}
     349             : 
     350             :     Bool baselinePresent () const;
     351             :     /// For how many of the rows reachable by changeRow() does baselinePresent(() hold?
     352             :     /// That's equivalent to asking how many baselines are being
     353             :     Int nBaselinesPresent () const;
     354             : 
     355             :     Vector<Bool> correlationFlagsMutable ();
     356             :     const Matrix<Int> & counts () const;
     357             :     Int countsBaseline () const;
     358    21852412 :     Matrix<Bool> & flagsMutable () { return Vbi2MsRow::flagsMutable();}
     359             :     Double intervalLast () const;
     360             :     Double timeFirst () const;
     361             :     Double timeLast () const;
     362             :     Vector<Double> uvwFirst ();
     363             : 
     364             :     void setBaselinePresent (Bool isPresent);
     365             :     void setCounts (const Matrix<Int> &);
     366             :     void setCountsBaseline (Int);
     367             :     void setIntervalLast (Double);
     368             :     void setTimeFirst (Double);
     369             :     void setTimeLast (Double);
     370             : 
     371             :     Double getNormalizationFactor();
     372             :     void setNormalizationFactor(Double normalizationFactor);
     373             :     void accumulateNormalizationFactor(Double normalizationFactor);
     374             : 
     375             :     /**
     376             :      * For bookkeeping. Input row indices that have been added so far in the current row
     377             :      * (set with changeRow). This is a list of input rows attached to this averaged row,
     378             :      * needed to build the map of input->output row indices when this row is transferred to
     379             :      * the output/averaged buffer.
     380             :      */
     381             :     std::vector<Int> inputRowIdxs() { return inputRowIdxs_p[row()]; }
     382             :     /**
     383             :      * Adds into the 'inputRowIdxs' list the index of an input row from the buffer being
     384             :      * averaged.
     385             :      * @param idx the index of the input row in the input buffer
     386             :      */
     387    10926206 :     void addInputRowIdx(Int idx) {
     388    10926206 :         inputRowIdxs_p[row()].push_back(idx);
     389    10926206 :     }
     390             :     /**
     391             :      * Clear the list of input rows attached to this row. This is used once the row is
     392             :      * transferred to the output/averaged buffer (typically after every average interval).
     393             :      */
     394             :     void clearRowIdxs() { inputRowIdxs_p[row()].clear(); }
     395             : 
     396             : private:
     397             : 
     398             :     void configureCountsCache ();
     399             : 
     400             :     mutable CachedPlaneAvg<Int> countsCache_p;
     401             :     Vector<Double> normalizationFactor_p;
     402             :     VbAvg * vbAvg_p; // [use]
     403             :     // map: input buffer row index -> output buffer row index
     404             :     std::map<Int, std::vector<Int>> inputRowIdxs_p;
     405             : };
     406             : 
     407             : /**
     408             :  * It looks like the intended usage of this VbAvg class (from AveragingTvi2::
     409             :  * produceSubchunk()) is as follows:
     410             :  *
     411             :  * // Use a "VbAvg vbAvg":
     412             :  * VisBufferImpl2 * vbToFill = // get/create output (averaged) buffer
     413             :  * vbToFill->setFillable(true);
     414             :  * vbAvg.setBufferToFill(vbToFill);
     415             :  * // we have the input buffer (to be averaged) in "VisibilityIteratorImpl2 vii;
     416             :  * while (vii->more()) {
     417             :  *    ...
     418             :  *    vbAvg.accumulate(vb, subhunk);
     419             :  * }
     420             :  * vbAvg.finalizeAverages();
     421             :  * vbAvg.finalizeBufferFillnig();
     422             :  */
     423             : class VbAvg : public VisBufferImpl2 {
     424             : 
     425             : public:
     426             : 
     427             :     friend class MsRowAvg;
     428             : 
     429             :     VbAvg (const AveragingParameters & averagingParameters, ViImplementation2 * vi);
     430             : 
     431             :     void accumulate (const VisBuffer2 * vb, const Subchunk & subchunk);
     432             :     const Cube<Int> & counts () const;
     433             :     Bool empty () const;
     434             :     void finalizeBufferFilling ();
     435             :     void finalizeAverages ();
     436             :     MsRowAvg * getRow (Int row) const;
     437             :     MsRowAvg * getRowMutable (Int row);
     438             :     Bool isComplete () const;
     439             :     Bool isUsingUvwDistance () const;
     440             :     void markEmpty ();
     441             :     int nSpectralWindowsInBuffer () const;
     442             :     void setBufferToFill (VisBufferImpl2 *);
     443             :     void startChunk (ViImplementation2 *);
     444             :     Int getBaselineIndex (Int antenna1, Int antenna2, Int spw) const;
     445             :     // Vector with row idx in the averaged/ooutput buffers
     446         529 :     const std::vector<size_t> & row2AvgRow() const { return row2AvgRow_p; };
     447             : 
     448             : protected:
     449             : 
     450             :     class Doing {
     451             :     public:
     452             : 
     453         362 :         Doing ()
     454         362 :         : correctedData_p (false),
     455             :           modelData_p (false),
     456             :           observedData_p (false),
     457             :           floatData_p(false),
     458             :           onlymetadata_p(true),
     459             :           weightSpectrumIn_p (false),
     460             :           sigmaSpectrumIn_p (false),
     461             :           weightSpectrumOut_p (false),
     462         362 :           sigmaSpectrumOut_p (false)
     463         362 :         {}
     464             : 
     465             :         Bool correctedData_p;
     466             :         Bool modelData_p;
     467             :         Bool observedData_p;
     468             :         Bool floatData_p;
     469             :         Bool onlymetadata_p;
     470             :         Bool weightSpectrumIn_p;
     471             :         Bool sigmaSpectrumIn_p;
     472             :         Bool weightSpectrumOut_p;
     473             :         Bool sigmaSpectrumOut_p;
     474             :     };
     475             : 
     476             :     class AccumulationParameters {
     477             : 
     478             :     public:
     479             : 
     480    10926206 :         AccumulationParameters (MsRow * rowInput, MsRowAvg * rowAveraged, const Doing & doing)
     481    10926206 :         : correctedIn_p (doing.correctedData_p ? rowInput->corrected().data() : 0),
     482    10926206 :           correctedOut_p (doing.correctedData_p ? rowAveraged->correctedMutable ().data(): 0),
     483    10926206 :           flagCubeIn_p (rowInput->flags().data()),
     484    10926206 :           flagCubeOut_p (rowAveraged->flagsMutable().data()),
     485    11019497 :           floatDataIn_p (doing.floatData_p ? rowInput->singleDishData().data() : 0),
     486    11019497 :           floatDataOut_p (doing.floatData_p ? rowAveraged->singleDishDataMutable().data() : 0),
     487    10926206 :           modelIn_p (doing.modelData_p ? rowInput->model().data(): 0),
     488    10926206 :           modelOut_p (doing.modelData_p ? rowAveraged->modelMutable().data() : 0),
     489    10926206 :           observedIn_p (doing.observedData_p ? rowInput->observed().data() : 0),
     490    10926206 :           observedOut_p (doing.observedData_p ? rowAveraged->observedMutable().data() : 0),
     491    21852412 :           sigmaIn_p (& rowInput->sigma()),
     492    21852412 :           sigmaOut_p (& rowAveraged->sigmaMutable()),
     493    10926206 :           sigmaSpectrumIn_p (doing.sigmaSpectrumIn_p ? rowInput->sigmaSpectrum().data() : 0),
     494    10926206 :           sigmaSpectrumOut_p (doing.sigmaSpectrumOut_p ? rowAveraged->sigmaSpectrumMutable().data() : 0),
     495    21852412 :           weightIn_p (& rowInput->weight()),
     496    21852412 :           weightOut_p (& rowAveraged->weightMutable()),
     497    10926206 :           weightSpectrumIn_p (doing.weightSpectrumIn_p ? rowInput->weightSpectrum().data() : 0),
     498   142040678 :           weightSpectrumOut_p (doing.weightSpectrumOut_p ? rowAveraged->weightSpectrumMutable().data() : 0)
     499    10926206 :         {}
     500             : 
     501   779200874 :         void incrementCubePointers()
     502             :         {
     503             :             // For improved performance this class is designed to sweep the cube data elements in this row
     504             :             // in the order (correlation0, channel0), (correlation1, channel1), etc.
     505             : 
     506   779200874 :             correctedIn_p && correctedIn_p ++;
     507   779200874 :             correctedOut_p && correctedOut_p ++;
     508   779200874 :             flagCubeIn_p && flagCubeIn_p ++;
     509   779200874 :             flagCubeOut_p && flagCubeOut_p ++;
     510   779200874 :             floatDataIn_p && floatDataIn_p ++;
     511   779200874 :             floatDataOut_p && floatDataOut_p ++;
     512   779200874 :             modelIn_p && modelIn_p ++;
     513   779200874 :             modelOut_p && modelOut_p ++;
     514   779200874 :             observedIn_p && observedIn_p ++;
     515   779200874 :             observedOut_p && observedOut_p ++;
     516   779200874 :             sigmaSpectrumIn_p && sigmaSpectrumIn_p ++;
     517   779200874 :             sigmaSpectrumOut_p && sigmaSpectrumOut_p ++;
     518   779200874 :             weightSpectrumIn_p && weightSpectrumIn_p ++;
     519   779200874 :             weightSpectrumOut_p && weightSpectrumOut_p ++;
     520   779200874 :         }
     521             : 
     522             :         inline const Complex *
     523   239315578 :         correctedIn ()
     524             :         {
     525   239315578 :             assert (correctedIn_p != 0);
     526   239315578 :             return correctedIn_p;
     527             :         }
     528             : 
     529             :         inline Complex *
     530   239315578 :         correctedOut ()
     531             :         {
     532   239315578 :             assert (correctedOut_p != 0);
     533   239315578 :             return correctedOut_p;
     534             :         }
     535             : 
     536             :         inline const Float *
     537   192072192 :         floatDataIn ()
     538             :         {
     539   192072192 :             return floatDataIn_p;
     540             :         }
     541             : 
     542             :         inline Float *
     543   192072192 :         floatDataOut ()
     544             :         {
     545   192072192 :             return floatDataOut_p;
     546             :         }
     547             : 
     548             :         inline const Complex *
     549   234413636 :         modelIn ()
     550             :         {
     551   234413636 :             assert (modelIn_p != 0);
     552   234413636 :             return modelIn_p;
     553             :         }
     554             : 
     555             :         inline Complex *
     556   234413636 :         modelOut ()
     557             :         {
     558   234413636 :             assert (modelOut_p != 0);
     559   234413636 :             return modelOut_p;
     560             :         }
     561             : 
     562             :         inline const Complex *
     563   335197513 :         observedIn ()
     564             :         {
     565   335197513 :             assert (observedIn_p != 0);
     566   335197513 :             return observedIn_p;
     567             :         }
     568             : 
     569             :         inline Complex *
     570   335197513 :         observedOut ()
     571             :         {
     572   335197513 :             assert (observedOut_p != 0);
     573   335197513 :             return observedOut_p;
     574             :         }
     575             : 
     576             :         inline const Bool *
     577             :         flagCubeIn ()
     578             :         {
     579             :             assert (flagCubeIn_p != 0);
     580             :             return flagCubeIn_p;
     581             :         }
     582             : 
     583             :         inline Bool *
     584             :         flagCubeOut ()
     585             :         {
     586             :             assert (flagCubeOut_p != 0);
     587             :             return flagCubeOut_p;
     588             :         }
     589             : 
     590             :         inline const Float *
     591   527269705 :         sigmaSpectrumIn ()
     592             :         {
     593   527269705 :             return sigmaSpectrumIn_p;
     594             :         }
     595             : 
     596             :         inline Float *
     597   335197513 :         sigmaSpectrumOut ()
     598             :         {
     599   335197513 :             assert (sigmaSpectrumOut_p != 0);
     600   335197513 :             return sigmaSpectrumOut_p;
     601             :         }
     602             : 
     603             :         inline const Float *
     604   239315578 :         weightSpectrumIn ()
     605             :         {
     606   239315578 :             assert (weightSpectrumIn_p != 0);
     607   239315578 :             return weightSpectrumIn_p;
     608             :         }
     609             : 
     610             :         inline Float *
     611   776740639 :         weightSpectrumOut ()
     612             :         {
     613   776740639 :             assert (weightSpectrumOut_p != 0);
     614   776740639 :             return weightSpectrumOut_p;
     615             :         }
     616             : 
     617             :         inline const Vector<Float> &
     618             :         weightIn ()
     619             :         {
     620             :             assert (weightIn_p != 0);
     621             :             return *weightIn_p;
     622             :         }
     623             : 
     624             :         inline Vector<Float> &
     625             :         weightOut ()
     626             :         {
     627             :             assert (weightOut_p != 0);
     628             :             return *weightOut_p;
     629             :         }
     630             : 
     631             :         inline const Vector<Float> &
     632             :         sigmaIn ()
     633             :         {
     634             :             assert (sigmaIn_p != 0);
     635             :             return *sigmaIn_p;
     636             :         }
     637             : 
     638             :         inline Vector<Float> &
     639             :         sigmaOut ()
     640             :         {
     641             :             assert (sigmaOut_p != 0);
     642             :             return *sigmaOut_p;
     643             :         }
     644             : 
     645             : 
     646             : 
     647             :     private:
     648             : 
     649             :         const Complex * correctedIn_p;
     650             :         Complex * correctedOut_p;
     651             :         const Bool * flagCubeIn_p;
     652             :         Bool * flagCubeOut_p;
     653             :         const Float * floatDataIn_p;
     654             :         Float * floatDataOut_p;
     655             :         const Complex * modelIn_p;
     656             :         Complex * modelOut_p;
     657             :         const Complex * observedIn_p;
     658             :         Complex * observedOut_p;
     659             :         const Vector<Float> * sigmaIn_p;
     660             :         Vector<Float> * sigmaOut_p;
     661             :         const Float * sigmaSpectrumIn_p;
     662             :         Float * sigmaSpectrumOut_p;
     663             :         const Vector<Float> * weightIn_p;
     664             :         Vector<Float> * weightOut_p;
     665             :         const Float * weightSpectrumIn_p;
     666             :         Float * weightSpectrumOut_p;
     667             : 
     668             : 
     669             :     };
     670             : 
     671             :     std::pair<Bool, Vector<Double> > accumulateCubeData (MsRow * rowInput, MsRowAvg * rowAveraged);
     672             :     void accumulateElementForCubes (AccumulationParameters & accumulationParameters,
     673             :                                     Bool zeroAccumulation);
     674             :     template<typename T>
     675             :     void
     676             :     accumulateElementForCube (const T * unweightedValue,
     677             :                               Float weight,
     678             :                               Bool zeroAccumulation,
     679             :                               T * accumulator);
     680             : 
     681             :     template <typename T>
     682             :     T accumulateRowDatum (const T & averagedValue, const T & inputValue,
     683             :                           Bool resetAverage);
     684             : 
     685             : 
     686             : 
     687             :     void accumulateExposure (const VisBuffer2 *);
     688             :     /*
     689             :      * Called once per row in the input buffer
     690             :      * @param rowInput row from the input buffer being averaged
     691             :      * @param rowAveraged changing "accumulator" row for the output buffer
     692             :      * @param subchunk - hard to understand
     693             :      * @param iidx index of the input row in the input buffer
     694             :      */
     695             :     void accumulateOneRow (MsRow * rowInput, MsRowAvg * rowAveraged,
     696             :                            const Subchunk & subchunk, Int iidx);
     697             :     void accumulateRowData (MsRow * rowInput, MsRowAvg * rowAveraged, Double adjustedWeight,
     698             :                             Bool rowFlagged);
     699             :     void accumulateTimeCentroid (const VisBuffer2 * input);
     700             :     void captureIterationInfo (VisBufferImpl2 * dstVb, const VisBuffer2 * srcVb,
     701             :                                const Subchunk & subchunk);
     702             :     void copyBaseline (Int sourceBaseline, Int targetBaseline);
     703             :     template<typename T>
     704             :     void copyBaselineScalar (Int sourceBaseline, Int targetBaseline,
     705             :                              Vector<T> & columnVector);
     706             :     template<typename T>
     707             :     void copyCubePlaneIf (Bool condition, Int sourceBaseline,
     708             :                           Int targetBaseline, Cube<T> & cube);
     709             :     void copyIdValues (MsRow * rowInput, MsRowAvg * rowAveraged);
     710             :     void copyIdValue (Int inputId, Int & averagedId);
     711             :     void finalizeBaseline (MsRowAvg *);
     712             :     void finalizeBaselineIfNeeded (MsRow * rowInput, MsRowAvg * rowAveraged,
     713             :                                    const Subchunk & subchunk);
     714             :     void finalizeCubeData (MsRowAvg *);
     715             :     void finalizeRowData (MsRowAvg *);
     716             :     AccumulationParameters * getAccumulationParameters (MsRow * rowInput,
     717             :                                                         MsRowAvg * rowAveraged);
     718             :     Int getBaselineIndex (const MsRow *) const;
     719             :     void initializeBaseline (MsRow * rowInput, MsRowAvg * rowAveraged,
     720             :                              const Subchunk & subchunk);
     721             :     Int nBaselines () const;
     722             :     void prepareIds (const VisBuffer2 * vb);
     723             :     void removeMissingBaselines ();
     724             : 
     725             : private:
     726             : 
     727             :     void setupVbAvg (const VisBuffer2 *);
     728             :     void setupArrays (Int nCorrelations, Int nChannels, Int nBaselines);
     729             :     void setupBaselineIndices (Int nAntennas, const VisBuffer2 * vb);
     730             : 
     731             :     /// A baseline being averaged into a MSRowAvg is put into the output/averaged buffer and
     732             :     /// set as not present
     733             :     void transferBaseline (MsRowAvg *);
     734             : 
     735             :     template <typename T>
     736             :     static T
     737       16992 :     distanceSquared (const Vector<T> & p1, const Vector<T> & p2)
     738             :     {
     739       16992 :         assert (p1.size() == 3 && p2.size() == 3);
     740             : 
     741       16992 :         T distanceSquared = 0;
     742             : 
     743       67968 :         for (Int i = 0; i < 3; i++){
     744       50976 :             T delta = p1[i] - p2[i];
     745       50976 :             distanceSquared += delta * delta;
     746             :         }
     747             : 
     748       16992 :         return distanceSquared;
     749             :     }
     750             : 
     751             :     Double averagingInterval_p;
     752             :     AveragingOptions averagingOptions_p;
     753             :     const ViImplementation2 * averagingVii_p;
     754             :     mutable BaselineIndex baselineIndex_p; // map of antenna1,antenna2 to row number in this VB.
     755             :     Vector<Bool> baselinePresent_p; // indicates whether baseline has any data
     756             :     Vector<Double> normalizationFactor_p; // indicates whether baseline has any data
     757             :     VisBufferImpl2 * bufferToFill_p;
     758             :     Bool complete_p; // average is complete
     759             :     Matrix<Bool> correlationFlags_p; // used for weight accumulation
     760             :     Cube<Int> counts_p; // number of items summed together for each correlation, channel, baseline item.
     761             :     Vector<Int> countsBaseline_p; // number of items summed together for each baseline.
     762             :     Doing doing_p;
     763             :     Bool empty_p; // true when buffer hasn't seen any data
     764             :     Vector<Double> intervalLast_p;
     765             :     Double maxTimeDistance_p;
     766             :     Double maxUvwDistanceSquared_p;
     767             :     Bool needIterationInfo_p;
     768             :     VisBufferComponents2 optionalComponentsToCopy_p;
     769             :     Int rowIdGenerator_p;
     770             :     Double sampleInterval_p;
     771             :     Double startTime_p; // time of the first sample in average
     772             :     Vector<Double> timeFirst_p;
     773             :     Vector<Double> timeLast_p;
     774             :     mutable PrefilledMatrix<Bool> trueBool_p;
     775             :     Matrix<Double> uvwFirst_p;
     776             :     Bool usingUvwDistance_p;
     777             :     mutable PrefilledMatrix<Int> zeroInt_p;
     778             :     mutable PrefilledMatrix<Float> zeroFloat_p;
     779             : 
     780             :     std::vector<size_t> row2AvgRow_p;
     781             : 
     782             :     LogIO logger_p;
     783             : };
     784             : 
     785             : ///////////////////////////////////////////////////////////
     786             : //
     787             : // Set of Averaging VisBuffers, one per active DD ID
     788             : 
     789             : 
     790             : //class VbSet {
     791             : //
     792             : //public:
     793             : //
     794             : //    VbSet (const AveragingParameters & averagingParameters);
     795             : //    ~VbSet ();
     796             : //
     797             : //    void accumulate (const VisBuffer2 *, const Subchunk & subchunk);
     798             : //    void finalizeBufferFilling ();
     799             : //    void setBufferToFill (VisBuffer2 *);
     800             : //
     801             : //
     802             : //    VbAvg * add (Int ddId);
     803             : //    Bool anyAveragesReady(Int ddid = -1) const;
     804             : //    Bool contains (Int ddId) const;
     805             : ////    void finalizeAverage (Int ddId);
     806             : //    void finalizeAverages ();
     807             : //    void finalizeRowIfNeeded (ms::MsRow * rowInput, avg::MsRowAvg * rowAveraged, const Subchunk & subchunk);
     808             : //    void flush (Bool okIfNonempty = false, ViImplementation2 * vi = 0); // delete all averagers
     809             : //    Int getFirstReadyDdid () const;
     810             : //    void transferAverage (Int ddId, VisBuffer2 * vb);
     811             : //    Bool vbPastAveragingInterval (const VisBuffer2 * vb) const;
     812             : //    void zero ();
     813             : //
     814             : //protected:
     815             : //
     816             : //    void seeIfCubeColumnsExist (ViImplementation2 * vi);
     817             : //
     818             : //private:
     819             : //
     820             : //    typedef map<Int, VbAvg *> Averagers;
     821             : //
     822             : //    const Double averagingInterval_p;
     823             : //    AveragingOptions averagingOptions_p;
     824             : //    const AveragingParameters averagingParameters_p;
     825             : //    Bool doingCorrectedData_p;
     826             : //    Bool doingModelData_p;
     827             : //    Bool doingObservedData_p;
     828             : //    Bool doingWeightSpectrum_p;
     829             : //    Bool doingsigmaSpectrum_p;
     830             : //    Averagers vbAveragers_p;
     831             : //};
     832             : 
     833           0 : MsRowAvg::MsRowAvg (rownr_t row, const VbAvg * vb)
     834             : : Vbi2MsRow (row, vb),
     835             :   countsCache_p (& VbAvg::counts),
     836             :   normalizationFactor_p(0.0),
     837           0 :   vbAvg_p (const_cast<VbAvg *> (vb))
     838             : {
     839           0 :     configureCountsCache();
     840           0 : }
     841             : 
     842             : 
     843             : // Constructor for read/write access
     844             : 
     845      606549 : MsRowAvg::MsRowAvg (rownr_t row, VbAvg * vb)
     846             : : Vbi2MsRow (row, vb),
     847             :   countsCache_p (& VbAvg::counts),
     848             :   normalizationFactor_p(0.0),
     849      606549 :   vbAvg_p (vb)
     850             : {
     851      606549 :     configureCountsCache();
     852      606549 : }
     853             : 
     854             : Bool
     855    22207594 : MsRowAvg::baselinePresent () const
     856             : {
     857    22207594 :     return vbAvg_p->baselinePresent_p (row ());
     858             : }
     859             : 
     860             : Int
     861    10926206 : MsRowAvg::nBaselinesPresent () const
     862             : {
     863    21852412 :     return std::count(vbAvg_p->baselinePresent_p.begin(), vbAvg_p->baselinePresent_p.end(),
     864    32778618 :                       true);
     865             : }
     866             : 
     867             : void
     868      606549 : MsRowAvg::configureCountsCache ()
     869             : {
     870      606549 :     addToCachedArrays (countsCache_p);
     871      606549 : }
     872             : 
     873             : const Matrix<Int> &
     874    10955011 : MsRowAvg::counts () const
     875             : {
     876    10955011 :     return countsCache_p.getCachedPlane (dynamic_cast<VbAvg *> (getVbi()), row());
     877             : }
     878             : 
     879             : Vector<Bool>
     880    11415345 : MsRowAvg::correlationFlagsMutable ()
     881             : {
     882    11415345 :     return vbAvg_p->correlationFlags_p.column (row());
     883             : }
     884             : 
     885             : Int
     886    21881613 : MsRowAvg::countsBaseline () const
     887             : {
     888    21881613 :     return vbAvg_p->countsBaseline_p (row ());
     889             : }
     890             : 
     891             : void
     892      978278 : MsRowAvg::setBaselinePresent (Bool value)
     893             : {
     894      978278 :     vbAvg_p->baselinePresent_p (row ()) = value;
     895      978278 : }
     896             : 
     897             : 
     898             : void
     899    11415345 : MsRowAvg::setCountsBaseline (Int value)
     900             : {
     901    11415345 :     vbAvg_p->countsBaseline_p (row ()) = value;
     902    11415345 : }
     903             : 
     904             : Double
     905      439630 : MsRowAvg::intervalLast () const
     906             : {
     907      439630 :     return vbAvg_p->intervalLast_p (row ());
     908             : }
     909             : 
     910             : 
     911             : Double
     912    23042259 : MsRowAvg::timeFirst () const
     913             : {
     914    23042259 :     return vbAvg_p->timeFirst_p (row ());
     915             : }
     916             : 
     917             : Double
     918      489139 : MsRowAvg::timeLast () const
     919             : {
     920      489139 :     return vbAvg_p->timeLast_p (row ());
     921             : }
     922             : 
     923             : Vector<Double>
     924      506131 : MsRowAvg::uvwFirst ()
     925             : {
     926      506131 :     return vbAvg_p->uvwFirst_p.column (row());
     927             : }
     928             : 
     929             : 
     930             : void
     931      489139 : MsRowAvg::setCounts (const Matrix<Int> & value)
     932             : {
     933      489139 :     Matrix<Int> & theCounts = countsCache_p.getCachedPlane (dynamic_cast<VbAvg *> (getVbi()), row());
     934      489139 :     theCounts = value;
     935      489139 : }
     936             : 
     937             : void
     938    10926206 : MsRowAvg::setIntervalLast (Double value)
     939             : {
     940    10926206 :     vbAvg_p->intervalLast_p (row ()) = value;
     941    10926206 : }
     942             : 
     943             : 
     944             : void
     945      489139 : MsRowAvg::setTimeFirst (Double value)
     946             : {
     947      489139 :     vbAvg_p->timeFirst_p (row ()) = value;
     948      489139 : }
     949             : 
     950             : void
     951    11415345 : MsRowAvg::setTimeLast (Double value)
     952             : {
     953    11415345 :     vbAvg_p->timeLast_p (row ()) = value;
     954    11415345 : }
     955             : 
     956      489139 : Double MsRowAvg::getNormalizationFactor()
     957             : {
     958      489139 :         return vbAvg_p->normalizationFactor_p (row ());
     959             : }
     960             : 
     961      978378 : void MsRowAvg::setNormalizationFactor(Double normalizationFactor)
     962             : {
     963      978378 :         vbAvg_p->normalizationFactor_p (row ()) = normalizationFactor;
     964      978378 : }
     965             : 
     966    10926206 : void MsRowAvg::accumulateNormalizationFactor(Double normalizationFactor)
     967             : {
     968    10926206 :         vbAvg_p->normalizationFactor_p (row ()) += normalizationFactor;
     969    10926206 : }
     970             : 
     971         362 : VbAvg::VbAvg (const AveragingParameters & averagingParameters, ViImplementation2 * vii)
     972             : : VisBufferImpl2 (vii, VbRekeyable),
     973         724 :   averagingInterval_p (averagingParameters.getAveragingInterval ()),
     974         724 :   averagingOptions_p (averagingParameters.getOptions()),
     975             :   averagingVii_p (vii),
     976             :   bufferToFill_p (0),
     977             :   complete_p (false),
     978             :   doing_p (), // all false until determined later on
     979             :   empty_p (true),
     980         362 :   maxTimeDistance_p (averagingParameters.getAveragingInterval() * (0.999)),
     981             :         // Shrink it just a bit for roundoff
     982         362 :   maxUvwDistanceSquared_p (pow(averagingParameters.getMaxUvwDistance(),2)),
     983             :   needIterationInfo_p (true),
     984             :   rowIdGenerator_p (0),
     985             :   sampleInterval_p (0),
     986             :   startTime_p (0),
     987        1086 :   usingUvwDistance_p (averagingParameters.getOptions().contains (AveragingOptions::BaselineDependentAveraging))
     988         362 : {}
     989             : 
     990             : /**
     991             :  * Calculates the row index in the output buffer, given an averaged row, a baseline index
     992             :  * corresponding to this averaged row, and the magic "rowIdGenerator" of the VbAvg.
     993             :  *
     994             :  * @param nrows number of rows in the input buffer being averaged
     995             :  * @param baselineIndex index of the baseline being averaged into the rowAveraged
     996             :  * @param rowAveraged "accumulator" row being produced for the output buffer
     997             :  * @param rowIdGen the rowIdGenerator of the VbAvg, which increases (in a not so clean way)
     998             :  *        for every new baseline inside every chunk
     999             :  */
    1000             : Int
    1001    10926206 : calcOutRowIdx(Int nrows, Int baselineIndex, const MsRowAvg* rowAveraged, Int rowIdGen)
    1002             : {
    1003    10926206 :     auto nBasePresent = rowAveraged->nBaselinesPresent();
    1004             :     // check whether multiple time steps are being averaged into the output buffer
    1005             :     // (row blocking or similar feature is enabled)
    1006    10926206 :     const bool multitime =  nrows > nBasePresent;
    1007             : 
    1008    10926206 :     if (!multitime) {
    1009             :         // There is only one time step, so the index must be simply the baseline index.
    1010             :         // with row blocking disabled, it doesn't seem to be possible to make sense out of
    1011             :         // rowIdgenerator_p for the purpose of this calculation -> skip the more general
    1012             :         // calculation from below and just use baseline index.
    1013    10639679 :         return baselineIndex;
    1014             :     }
    1015             : 
    1016             :     // the rowIdgenerator_p that we get in rowIdGen increases +1 for every new baseline.
    1017             :     // It is not really a proper (input) row id. After all baselines have been seen for a
    1018             :     // time step, the rows of the next time steps will get the same id.
    1019             :     // And to turn it into a valid output id we need the following
    1020             :     // "divide_with_roundup + multiply + baseline_index"
    1021      286527 :     Int rowIdG_div_baselines_roundup = 0;
    1022      286527 :     if (nBasePresent > 0)
    1023      286527 :         rowIdG_div_baselines_roundup = (rowIdGen + nBasePresent - 1)/ nBasePresent;
    1024      286527 :     const Int id = rowIdG_div_baselines_roundup * nBasePresent + baselineIndex;
    1025             : 
    1026      286527 :     return id;
    1027             : }
    1028             : 
    1029             : void
    1030      591882 : VbAvg::accumulate (const VisBuffer2 * vb, const Subchunk & subchunk)
    1031             : {
    1032      591882 :     if (empty_p){
    1033       14667 :         setupVbAvg (vb);
    1034             :     }
    1035             : 
    1036      591882 :     if (needIterationInfo_p){
    1037       39498 :         captureIterationInfo (bufferToFill_p, vb, subchunk);
    1038       39498 :         needIterationInfo_p = false;
    1039             :     }
    1040             : 
    1041      591882 :     assert (bufferToFill_p != 0);
    1042             : 
    1043      591882 :     MsRowAvg * rowAveraged = getRowMutable (0);
    1044      591882 :     MsRow * rowInput = vb->getRow (0);
    1045             : 
    1046      591882 :     auto nrows = vb->nRows();
    1047      591882 :     row2AvgRow_p.resize(nrows);
    1048    11518088 :     for (rownr_t row = 0; row < nrows; ++row){
    1049             : 
    1050    10926206 :         rowInput->changeRow (row);
    1051    10926206 :         Int baselineIndex = getBaselineIndex (rowInput);
    1052             : 
    1053    10926206 :         rowAveraged->changeRow (baselineIndex);
    1054             : 
    1055    10926206 :         accumulateOneRow (rowInput, rowAveraged, subchunk, row);
    1056             : 
    1057    10926206 :         row2AvgRow_p[row] = calcOutRowIdx(nrows, baselineIndex, rowAveraged,
    1058             :                                           rowIdGenerator_p);
    1059             :     }
    1060             : 
    1061      591882 :     delete rowAveraged;
    1062      591882 :     delete rowInput;
    1063             : 
    1064      591882 : }
    1065             : 
    1066             : void
    1067    10926206 : VbAvg::accumulateOneRow (MsRow * rowInput, MsRowAvg * rowAveraged, const Subchunk & subchunk,
    1068             :                          Int iidx)
    1069             : {
    1070    10926206 :     finalizeBaselineIfNeeded (rowInput, rowAveraged, subchunk);
    1071             : 
    1072    10926206 :     if (! rowAveraged->baselinePresent())
    1073             :     {
    1074             : 
    1075      489139 :         initializeBaseline (rowInput, rowAveraged, subchunk);
    1076             :     }
    1077             : 
    1078             :     // bookkeeping - save for later that this input row is being averaged into the output row
    1079    10926206 :     rowAveraged->addInputRowIdx(iidx);
    1080             : 
    1081             :     // Accumulate data that is matrix-valued (e.g., vis, visModel, etc.).
    1082             :     // The computation of time centroid requires the use of the weight column
    1083             :     // adjusted for the flag cube.  Get the before and after weight accumulation
    1084             :     // and the difference is the adjusted weight for this row.
    1085             : 
    1086    21852412 :     Vector<Double> adjustedWeights;
    1087    10926206 :     Bool rowFlagged = false;
    1088             : 
    1089    10926206 :     std::tie (rowFlagged, adjustedWeights) = accumulateCubeData (rowInput, rowAveraged);
    1090             : 
    1091    10926206 :     Double adjustedWeight = 0;
    1092    53434930 :     for (Int c = 0; c < nCorrelations(); c++){
    1093             : 
    1094    42508724 :         adjustedWeight += adjustedWeights (c);
    1095             :     }
    1096             : 
    1097             :     // Accumulate the non matrix-valued data
    1098    10926206 :     accumulateRowData (rowInput, rowAveraged, adjustedWeight, rowFlagged);
    1099    10926206 : }
    1100             : 
    1101             : //void
    1102             : //VbAvg::accumulate (const VisBuffer2 * vb, const Subchunk & subchunk)
    1103             : //{
    1104             : //    // "Add" the contents of this buffer to the accumulation.
    1105             : //
    1106             : //    if (empty_p){
    1107             : //
    1108             : //        // Initialize the buffer if this is the first time bit of data that it is
    1109             : //        // being used after either creation or clearing.
    1110             : //
    1111             : //        prepareForFirstData (vb, subchunk);
    1112             : //
    1113             : //        empty_p = false;
    1114             : //    }
    1115             : //
    1116             : //    // Averaging can be computed as flagged or unflagged.  If all the inputs to a
    1117             : //    // datum are flagged, then the averaged datum (e.g., a visibility point)
    1118             : //    // will also be flagged.  For an unflagged averaged datum, it will represent
    1119             : //    // the average of all of the unflagged points for that datum.  This is done
    1120             : //    // by assuming the accumulation is flagged and continuing to accumulate
    1121             : //    // flagged points until the first unflagged point for a datum is encountered;
    1122             : //    // when this happens the count is zeroed and the averaged datum's flag is cleared.
    1123             : //
    1124             : //    // Loop over all of the rows in the VB.  Map each one to a baseline and then accumulate
    1125             : //    // the values for each correlation,channel cell.  Each row in the accumulating VB corresponds
    1126             : //    // to one baseline (i.e., pair of (antenna1, antenna2) where antenna1 <= antenna2).
    1127             : //
    1128             : //    ThrowIf (vb->nRows() > nBaselines(),
    1129             : //             String::format ("Expected %d baselines in VisBuffer but it contained %d rows",
    1130             : //                             nBaselines(), nRows()));
    1131             : //
    1132             : //    for (Int row = 0; row < vb->nRows(); row ++){
    1133             : //
    1134             : //        // Accumulate data for fields that are scalars (and uvw) in each row
    1135             : //
    1136             : //        accumulateRowData (vb, row);
    1137             : //
    1138             : //        // Accumulate data that is matrix-valued (e.g., vis, visModel, etc.)
    1139             : //
    1140             : //        accumulateCubeData (vb, row);
    1141             : //    }
    1142             : //}
    1143             : 
    1144             : void
    1145       52303 : VbAvg::finalizeBufferFilling ()
    1146             : {
    1147       52303 :     bufferToFill_p->appendRowsComplete();
    1148       52303 :     bufferToFill_p = 0; // decouple
    1149       52303 : }
    1150             : 
    1151             : template<typename T>
    1152             : inline void
    1153  2112937071 : VbAvg::accumulateElementForCube (const T * unweightedValue,
    1154             :                                  Float weight,
    1155             :                                  Bool zeroAccumulation,
    1156             :                                  T * accumulator)
    1157             : {
    1158             :     // Update the sum for this model visibility cube element.
    1159             : 
    1160  2112937071 :     if (zeroAccumulation){
    1161   466150265 :         * accumulator = (* unweightedValue) * weight;
    1162             :     }
    1163             :     else{
    1164  1646786806 :         * accumulator += (* unweightedValue) * weight;
    1165             :     }
    1166  2112937071 : }
    1167             : 
    1168             : 
    1169             : std::pair<Bool, Vector<Double> >
    1170    10926206 : VbAvg::accumulateCubeData (MsRow * rowInput, MsRowAvg * rowAveraged)
    1171             : {
    1172             :     // Accumulate the sums needed for averaging of cube data (e.g., visibility).
    1173             : 
    1174    10926206 :     const Matrix<Bool> & inputFlags = rowInput->flags ();
    1175    10926206 :     Matrix<Bool> & averagedFlags = rowAveraged->flagsMutable ();
    1176    21852412 :     Matrix<Int>  counts = rowAveraged->counts ();
    1177    21852412 :     Vector<Bool>  correlationFlagged = rowAveraged->correlationFlagsMutable ();
    1178             : 
    1179    10926206 :     AccumulationParameters accumulationParameters (rowInput, rowAveraged, doing_p);
    1180             :         // is a member variable to reduce memory allocations (jhj)
    1181             : 
    1182    21852412 :     IPosition shape = inputFlags.shape();
    1183    10926206 :     const Int nChannels = shape (1);
    1184    10926206 :     const Int nCorrelations = shape (0);
    1185             : 
    1186    10926206 :     Bool rowFlagged = true;  // true if all correlations and all channels flagged
    1187             : 
    1188   290066643 :     for (Int channel = 0; channel < nChannels; channel ++){
    1189             : 
    1190  1058341311 :         for (Int correlation = 0; correlation < nCorrelations; correlation ++){
    1191             : 
    1192             :             // Based on the current flag state of the accumulation and the current flag
    1193             :             // state of the correlation,channel, accumulate the data (or not).  Accumulate
    1194             :             // flagged data until the first unflagged datum appears.  Then restart the
    1195             :             // accumulation with that datum.
    1196             : 
    1197   779200874 :             Bool inputFlagged = inputFlags (correlation, channel);
    1198   779200874 :             if (rowFlagged && ! inputFlagged){
    1199    10264464 :                 rowFlagged = false;
    1200             :             }
    1201             :             //rowFlagged = rowFlagged && inputFlagged;
    1202   779200874 :             Bool accumulatorFlagged = averagedFlags (correlation, channel);
    1203             : 
    1204   779200874 :             if (! accumulatorFlagged && inputFlagged){
    1205     2460235 :                 accumulationParameters.incrementCubePointers();
    1206     2460235 :                 continue;// good accumulation, bad data so toss it.
    1207             :             }
    1208             : 
    1209             :             // If changing from flagged to unflagged for this cube element, reset the
    1210             :             // accumulation count to 1; otherwise increment the count.
    1211             : 
    1212   776740639 :             Bool flagChange = (accumulatorFlagged && ! inputFlagged);
    1213   776740639 :             Bool zeroAccumulation = flagChange || counts (correlation, channel) == 0;
    1214             : 
    1215   776740639 :             if (flagChange){
    1216   149933639 :                 averagedFlags (correlation, channel) = false;
    1217             :             }
    1218             : 
    1219   776740639 :             if (zeroAccumulation){
    1220   156680159 :                 counts (correlation, channel) = 1;
    1221             :             }
    1222             :             else{
    1223   620060480 :                 counts (correlation, channel) += 1;
    1224             :             }
    1225             : 
    1226             :             // Accumulate the sum for each cube element
    1227             : 
    1228   776740639 :             accumulateElementForCubes (accumulationParameters,
    1229             :                                        zeroAccumulation); // zeroes out accumulation
    1230             : 
    1231   776740639 :             accumulationParameters.incrementCubePointers();
    1232             : 
    1233             :             // Update correlation Flag
    1234             : 
    1235   776740639 :             if (correlationFlagged (correlation) && ! inputFlagged){
    1236     1571394 :                 correlationFlagged (correlation) = false;
    1237             :             }
    1238             :         }
    1239             :     }
    1240             : 
    1241    21852412 :     Vector<Double> adjustedWeight = Vector<Double> (nCorrelations, 1);
    1242    10926206 :     if (doing_p.correctedData_p)
    1243             :     {
    1244    47967333 :         for (Int correlation = 0; correlation < nCorrelations; correlation ++)
    1245             :         {
    1246    38292074 :                 adjustedWeight(correlation) = rowInput->weight(correlation);
    1247             :         }
    1248             :     }
    1249     1250947 :     else if (doing_p.observedData_p || doing_p.floatData_p)
    1250             :     {
    1251     3920812 :         for (Int correlation = 0; correlation < nCorrelations; correlation ++)
    1252             :         {
    1253     2979222 :                 adjustedWeight(correlation) = AveragingTvi2::sigmaToWeight(rowInput->sigma (correlation));
    1254             :         }
    1255             :     }
    1256             : 
    1257    21852412 :     return std::make_pair (rowFlagged, adjustedWeight);
    1258             : }
    1259             : 
    1260             : 
    1261             : inline void
    1262   776740639 : VbAvg::accumulateElementForCubes (AccumulationParameters & accumulationParameters,
    1263             :                                   Bool zeroAccumulation)
    1264             : {
    1265             : 
    1266             :         // NOTE: The channelized flag check comes from the calling context (continue statement)
    1267   776740639 :         float weightCorrected = 1.0f;
    1268   776740639 :         float weightObserved = 1.0f;
    1269   776740639 :         const float One = 1.0f;
    1270             : 
    1271   776740639 :         if (doing_p.correctedData_p)
    1272             :         {
    1273             :                 // The weight corresponding to CORRECTED_DATA is that stored in WEIGHT
    1274   239315578 :                 weightCorrected = * accumulationParameters.weightSpectrumIn ();
    1275             : 
    1276             : 
    1277             :                 // Accumulate weighted average contribution (normalization will come at the end)
    1278   239315578 :                 accumulateElementForCube (      accumulationParameters.correctedIn (),
    1279             :                                                                         weightCorrected, zeroAccumulation,
    1280             :                                                                         accumulationParameters.correctedOut ());
    1281             : 
    1282             :                 // The weight resulting from weighted average is the sum of the weights
    1283   239315578 :                 accumulateElementForCube (      & weightCorrected,
    1284             :                                                                         One, zeroAccumulation,
    1285             :                                                                         accumulationParameters.weightSpectrumOut ());
    1286             :         }
    1287             : 
    1288   776740639 :         if (doing_p.observedData_p)
    1289             :         {
    1290             :                 // The weight corresponding to DATA is that derived from the rms stored in SIGMA
    1291             :                 // This has to
    1292   335197513 :                 weightObserved = AveragingTvi2::sigmaToWeight(* accumulationParameters.sigmaSpectrumIn ());
    1293             : 
    1294             :                 // Accumulate weighted average contribution (normalization will come at the end)
    1295             : 
    1296   335197513 :                 accumulateElementForCube (      accumulationParameters.observedIn (),
    1297             :                                                                         weightObserved, zeroAccumulation,
    1298             :                                                                         accumulationParameters.observedOut ());
    1299             : 
    1300   335197513 :                 if (not doing_p.correctedData_p)
    1301             :                 {
    1302             :                         // The weight resulting from weighted average is the sum of the weights
    1303   266666226 :                         accumulateElementForCube (      & weightObserved,
    1304             :                                                                                 One, zeroAccumulation,
    1305             :                                                                                 accumulationParameters.weightSpectrumOut ());
    1306             :                 }
    1307             : 
    1308             :         // This will always create a sigma spectrum column which is not empty.
    1309             :         // This is useful in particular if not doing_p.correctedData_p but doing_p.modelData_p,
    1310             :         // so that modelData can be properly divided by sigmaSpectrumOut in finalizeCubeData
    1311             :         // We store the accumulated weight in sigmaSpectrumOut pending of
    1312             :         // - normalization
    1313             :         // - SIGMA = 1/sqrt(WEIGHT) in-place transformation
    1314   335197513 :         accumulateElementForCube (&weightObserved,
    1315             :                                   One, zeroAccumulation,
    1316             :                                   accumulationParameters.sigmaSpectrumOut ());
    1317             : 
    1318             :         }
    1319             : 
    1320             :         // For model data is less clear what to do, what in order to convert to
    1321             :         // split we use WEIGHT if averaging CORRECTED_DATA and SIGMA if avg. DATA.
    1322             :         // Finally we use WEIGHT by default when averaging MODEL_DATA only
    1323   776740639 :         if (doing_p.modelData_p)
    1324             :         {
    1325   234413636 :                 if (doing_p.correctedData_p)
    1326             :                 {
    1327   155726993 :                         accumulateElementForCube (      accumulationParameters.modelIn (),
    1328             :                                                                                 weightCorrected, zeroAccumulation,
    1329             :                                                                                 accumulationParameters.modelOut ());
    1330             :                 }
    1331    78686643 :                 else if (doing_p.observedData_p)
    1332             :                 {
    1333           0 :                         accumulateElementForCube (      accumulationParameters.modelIn (),
    1334             :                                                                                 weightObserved, zeroAccumulation,
    1335             :                                                                                 accumulationParameters.modelOut ());
    1336             :                 }
    1337             :                 else
    1338             :                 {
    1339    78686643 :                         accumulateElementForCube (      accumulationParameters.modelIn (),
    1340             :                                                                                 One, zeroAccumulation,
    1341             :                                                                                 accumulationParameters.modelOut ());
    1342             : 
    1343             :                         // When doing MODEL_DATA only the accumulated weight spectrum should just represent counts
    1344    78686643 :                         accumulateElementForCube (      & One,
    1345             :                                                                                 1.0f, zeroAccumulation,
    1346             :                                                                                 accumulationParameters.weightSpectrumOut ());
    1347             :                 }
    1348             :         }
    1349             : 
    1350   776740639 :         if (doing_p.floatData_p)
    1351             :         {
    1352             : 
    1353             :                 // The weight corresponding to FLOAT_DATA is that derived from the rms stored in SIGMA
    1354   192072192 :                 weightObserved = AveragingTvi2::sigmaToWeight(* accumulationParameters.sigmaSpectrumIn ());
    1355             : 
    1356             :                 // Accumulate weighted average contribution (normalization will come at the end)
    1357   192072192 :                 accumulateElementForCube (      accumulationParameters.floatDataIn (),
    1358             :                                                                         weightObserved, zeroAccumulation,
    1359             :                                                                         accumulationParameters.floatDataOut ());
    1360             : 
    1361             :                 // The weight resulting from weighted average is the sum of the weights
    1362   192072192 :                 accumulateElementForCube (      & weightObserved,
    1363             :                                                                         1.0f, zeroAccumulation,
    1364             :                                                                         accumulationParameters.weightSpectrumOut ());
    1365             :         }
    1366             : 
    1367  1553481278 :         return;
    1368             : }
    1369             : 
    1370             : 
    1371             : 
    1372             : template <typename T>
    1373             : T
    1374    43704824 : VbAvg::accumulateRowDatum (const T & averagedValue, const T & inputValue, Bool resetAverage)
    1375             : {
    1376    43704824 :     if (resetAverage){
    1377     1956956 :         return inputValue;
    1378             :     }
    1379             :     else{
    1380    41747868 :         return inputValue + averagedValue;
    1381             :     }
    1382             : }
    1383             : 
    1384             : void
    1385    10926206 : VbAvg::accumulateRowData (MsRow * rowInput, MsRowAvg * rowAveraged,
    1386             :                           Double adjustedWeight, Bool rowFlagged)
    1387             : {
    1388             : 
    1389             :     // Grab working copies of the values to be accumulated.
    1390             : 
    1391    10926206 :     Bool accumulatorRowFlagged = rowAveraged->isRowFlagged();
    1392    21392474 :     Bool flagChange = accumulatorRowFlagged != rowFlagged || // actual change
    1393    10466268 :                       rowAveraged->countsBaseline() == 0; // first time
    1394             : 
    1395    10926206 :     if (! accumulatorRowFlagged && rowFlagged){
    1396             :         // good accumulation, bad data --> skip it
    1397             :     }
    1398             :     else{
    1399             : 
    1400             :         // Update the row's accumulations; if the flagChanged then zero out the
    1401             :         // previous (flagged) accumulation first.
    1402             : 
    1403    10926206 :         rowAveraged->setCountsBaseline (accumulateRowDatum (rowAveraged->countsBaseline(),
    1404    10926206 :                                                             1,
    1405             :                                                             flagChange));
    1406             : 
    1407             :         // The WEIGHT column is handled under accumulateCubeData because of the
    1408             :         // interrelationship between weight and weightSpectrum.  The SIGMA column is
    1409             :         // handled in finalizeBaseline for similar reasons.
    1410             : 
    1411    10926206 :         accumulatorRowFlagged = accumulatorRowFlagged && rowFlagged;
    1412    10926206 :         rowAveraged->setRowFlag (accumulatorRowFlagged);
    1413             : 
    1414    10926206 :         rowAveraged->setExposure (accumulateRowDatum (rowAveraged->exposure(),
    1415    10926206 :                                                       rowInput->exposure (),
    1416    10926206 :                                                       flagChange));
    1417             : 
    1418             :         // While accumulating flagged values, the weights will be zero, so accumulate
    1419             :         // an arithmetic average until the accumulator becomes unflagged.
    1420             : 
    1421             :         Double weightToUse;
    1422             : 
    1423    10926206 :         if (accumulatorRowFlagged){
    1424      661742 :             weightToUse = 1;
    1425             :         }
    1426             :         else{
    1427    10264464 :             weightToUse = adjustedWeight;
    1428             :         }
    1429             : 
    1430    10926206 :         if (flagChange){
    1431      489239 :             rowAveraged->setNormalizationFactor(0.0);
    1432             :         }
    1433             : 
    1434    10926206 :         rowAveraged->accumulateNormalizationFactor(weightToUse);
    1435             : 
    1436    10926206 :         Double weightedTC = (rowInput->timeCentroid() - rowAveraged->timeFirst()) * weightToUse;
    1437    10926206 :         rowAveraged->setTimeCentroid (accumulateRowDatum (rowAveraged->timeCentroid(),
    1438             :                                                           weightedTC,
    1439    10926206 :                                                           flagChange));
    1440             : 
    1441    32778618 :         Vector<Double> weightedUvw = rowInput->uvw() * weightToUse;
    1442             : 
    1443    10926206 :         rowAveraged->setUvw (accumulateRowDatum (rowAveraged->uvw (),
    1444             :                                                  weightedUvw,
    1445    10926206 :                                                  flagChange));
    1446             : 
    1447             :         // Capture a couple pieces of data
    1448             : 
    1449    10926206 :         rowAveraged->setTimeLast (rowInput->time());
    1450             : 
    1451    10926206 :         rowAveraged->setIntervalLast (rowInput->interval());
    1452             :     }
    1453    10926206 : }
    1454             : 
    1455             : //Vector<Float>
    1456             : //VbAvg::adjustWeightForFlags (MsRow * rowInput)
    1457             : //{
    1458             : //    Matrix<Bool> flags = rowInput->flags();
    1459             : //    Vector<Float> adjustedWeight = rowInput->weight();
    1460             : //
    1461             : //    for (Int correlation = 0; correlation < nCorrelations(); correlation++){
    1462             : //
    1463             : //        // Sum up the number of good channels in this correlation
    1464             : //
    1465             : //        Int sum = 0;
    1466             : //
    1467             : //        for (Int channel = 0; channel < nChannels(); channel ++){
    1468             : //
    1469             : //            if (! flags (correlation, channel)){
    1470             : //
    1471             : //                sum ++;
    1472             : //            }
    1473             : //        }
    1474             : //
    1475             : //        // Adjust the weight by multiplying by the fraction of good channels.
    1476             : //
    1477             : //        Float factor = ((float) sum) / nChannels();
    1478             : //        adjustedWeight [correlation] *= factor;
    1479             : //    }
    1480             : //
    1481             : //    return adjustedWeight;
    1482             : //}
    1483             : 
    1484             : const Cube<Int> &
    1485    10929663 : VbAvg::counts () const
    1486             : {
    1487    10929663 :     return counts_p;
    1488             : }
    1489             : 
    1490             : 
    1491             : void
    1492      489139 : VbAvg::copyIdValues (MsRow * rowInput, MsRowAvg * rowAveraged)
    1493             : {
    1494      489139 :     rowAveraged->setAntenna1 (rowInput->antenna1());
    1495      489139 :     rowAveraged->setAntenna2 (rowInput->antenna2());
    1496      489139 :     rowAveraged->setArrayId (rowInput->arrayId());
    1497      489139 :     rowAveraged->setDataDescriptionId (rowInput->dataDescriptionId());
    1498      489139 :     rowAveraged->setFeed1 (rowInput->feed1());
    1499      489139 :     rowAveraged->setFeed2 (rowInput->feed2());
    1500      489139 :     rowAveraged->setFieldId (rowInput->fieldId());
    1501      489139 :     rowAveraged->setProcessorId (rowInput->processorId());
    1502      489139 :     rowAveraged->setScanNumber (rowInput->scanNumber());
    1503      489139 :     rowAveraged->setSpectralWindow (rowInput->spectralWindow());
    1504      489139 :     rowAveraged->setObservationId (rowInput->observationId());
    1505      489139 :     rowAveraged->setStateId (rowInput->stateId());
    1506      489139 : }
    1507             : 
    1508             : void
    1509           0 : VbAvg::copyIdValue (Int inputId, Int & averagedId)
    1510             : {
    1511           0 :     if (averagedId < 0){
    1512           0 :         averagedId = inputId;
    1513             :     }
    1514           0 : }
    1515             : 
    1516             : Bool
    1517           0 : VbAvg::empty () const
    1518             : {
    1519           0 :     return empty_p;
    1520             : }
    1521             : 
    1522             : Int
    1523    10926206 : VbAvg::getBaselineIndex (const MsRow * msRow) const
    1524             : {
    1525             :     // Lookup the baseline index using the prebuilt lookup table.
    1526             :     //
    1527             :     // The baseline index is the index in the sequence
    1528             :     // {(0,0),(1,0),(1,1),(2,0),(2,1),(2,2), ...} (i.e., the index in a
    1529             :     // 1-d representation of the lower right half of the square matrix of size
    1530             :     // nAntennas).
    1531             :     //
    1532             :     // This handles the case where the baseline ordering in the input VB might
    1533             :     // shift from VB to VB.
    1534             : 
    1535    10926206 :     const Int antenna1 = msRow->antenna1 ();
    1536    10926206 :     const Int antenna2 = msRow->antenna2 ();
    1537    10926206 :     const Int spw = msRow->spectralWindow ();
    1538             : 
    1539    10926206 :     const Int index = baselineIndex_p (antenna1, antenna2, spw);
    1540             : 
    1541    10926206 :     return index;
    1542             : }
    1543             : 
    1544             : Int
    1545           0 : VbAvg::getBaselineIndex (Int antenna1, Int antenna2, Int spw) const
    1546             : {
    1547           0 :     const Int index = baselineIndex_p (antenna1, antenna2, spw);
    1548             : 
    1549           0 :     return index;
    1550             : }
    1551             : 
    1552             : void
    1553       27376 : VbAvg::finalizeAverages ()
    1554             : {
    1555       27376 :     if (empty_p){
    1556       12709 :         return; // nothing to finalize
    1557             :     }
    1558             : 
    1559       14667 :     MsRowAvg * msRowAvg = getRowMutable (0);
    1560             : 
    1561      369849 :     for (Int baseline = 0; baseline < nBaselines(); baseline ++){
    1562             : 
    1563      355182 :         msRowAvg->changeRow (baseline);
    1564             : 
    1565      355182 :         if (msRowAvg->baselinePresent()){
    1566      277570 :             finalizeBaseline (msRowAvg);
    1567             :         }
    1568             : 
    1569             :     }
    1570             : 
    1571       14667 :     delete msRowAvg;
    1572             : 
    1573       14667 :     empty_p = true;
    1574             : }
    1575             : 
    1576             : void
    1577      489139 : VbAvg::finalizeBaseline (MsRowAvg * msRowAvg)
    1578             : {
    1579             :     // Software is no longer supposed to rely on the row flag.
    1580             :     // Setting it to false insures that legacy software will
    1581             :     // have to look at the flag cubes.
    1582             : 
    1583      489139 :     msRowAvg->setRowFlag(false);
    1584             : 
    1585      489139 :     finalizeCubeData (msRowAvg);
    1586             : 
    1587      489139 :     finalizeRowData (msRowAvg);
    1588             : 
    1589      489139 :     transferBaseline (msRowAvg);
    1590      489139 : }
    1591             : 
    1592             : // Functor to divide variables of possibly different types.
    1593             : // This is unlike std::divides which requires equal types.
    1594             : template <typename L, typename R=L, typename RES=L>
    1595             : struct DividesNonZero : public std::binary_function<L,R,RES>
    1596             : {
    1597   170645424 :   RES operator() (const L& x, const R& y) const
    1598             :   {
    1599   170645424 :     { return y > 0? RES(x)/y : RES(x); }
    1600             :   }
    1601             : };
    1602             : 
    1603             : 
    1604             : void
    1605      489139 : VbAvg::finalizeCubeData (MsRowAvg * msRowAvg)
    1606             : {
    1607             :     // Divide each of the data cubes in use by the sum of the appropriate weights.
    1608             : 
    1609             :     typedef DividesNonZero <Complex, Float, Complex> DivideOp;
    1610             :     DivideOp op;
    1611             : 
    1612      489139 :     if (doing_p.correctedData_p)
    1613             :     {
    1614      499934 :         Matrix<Complex> corrected = msRowAvg->correctedMutable();
    1615      249967 :         arrayTransformInPlace<Complex, Float, DivideOp > (corrected,msRowAvg->weightSpectrum (), op);
    1616             :     }
    1617             : 
    1618      489139 :     if (doing_p.observedData_p)
    1619             :     {
    1620      475532 :         Matrix<Complex> observed = msRowAvg->observedMutable();
    1621      237766 :         if (not doing_p.correctedData_p)
    1622      209686 :             arrayTransformInPlace<Complex, Float, DivideOp > (observed,msRowAvg->weightSpectrum (), op);
    1623             :         else
    1624       28080 :             arrayTransformInPlace<Complex, Float, DivideOp > (observed,msRowAvg->sigmaSpectrum (), op);
    1625             :     }
    1626             : 
    1627      489139 :     if (doing_p.modelData_p)
    1628             :     {
    1629      495946 :         Matrix<Complex> model = msRowAvg->modelMutable();
    1630             : 
    1631      247973 :         if (doing_p.correctedData_p)
    1632      219168 :             arrayTransformInPlace<Complex, Float, DivideOp > (model,msRowAvg->weightSpectrum (), op);
    1633       28805 :         else if (doing_p.observedData_p)
    1634           0 :             arrayTransformInPlace<Complex, Float, DivideOp > (model,msRowAvg->sigmaSpectrum (), op);
    1635             :         else
    1636       28805 :             arrayTransformInPlace<Complex, Int, DivideOp > (model,msRowAvg->counts (), op);
    1637             :     }
    1638             : 
    1639      489139 :     if (doing_p.floatData_p)
    1640             :     {
    1641             :         typedef Divides <Float, Float, Float> DivideOpFloat;
    1642             :         DivideOpFloat opFloat;
    1643             : 
    1644        1362 :         Matrix<Float> visCubeFloat = msRowAvg->singleDishDataMutable();
    1645         681 :         arrayTransformInPlace<Float, Float, DivideOpFloat > (visCubeFloat,msRowAvg->weightSpectrum (), opFloat);
    1646             :     }
    1647             : 
    1648             : 
    1649      978278 :     return;
    1650             : }
    1651             : 
    1652             : void
    1653      489139 : VbAvg::finalizeRowData (MsRowAvg * msRow)
    1654             : {
    1655      489139 :     Int n = msRow->countsBaseline ();
    1656             : 
    1657             :     // Obtain row-level WEIGHT by calculating the mean of WEIGHT_SPECTRUM
    1658             :     // msRow->setWeight(partialMedians(msRow->weightSpectrum(),IPosition(1,1),true));
    1659      489139 :     msRow->setWeight(AveragingTvi2::average(msRow->weightSpectrum(),msRow->flags()));
    1660             : 
    1661             :     // If doing both DATA and CORRECTED_DATA then SIGMA_SPECTRUM contains the weight
    1662             :     // (not sigma) accumulation for DATA, and we have to derive SIGMA from it
    1663      489139 :     if (doing_p.correctedData_p and doing_p.observedData_p)
    1664             :     {
    1665             :         // jagonzal: SIGMA is not derived from the mean of SIGMA_SPECTRUM but from the mean
    1666             :         // of the WEIGHT format of SIGMA_SPECTRUM turned into SIGMA by using 1/pow(weight,2)
    1667             :         // Vector<Float> weight = partialMedians(msRow->sigmaSpectrum(),IPosition(1,1),true);
    1668       56160 :         Vector<Float> weight = AveragingTvi2::average(msRow->sigmaSpectrum(),msRow->flags());
    1669       28080 :         arrayTransformInPlace (weight, AveragingTvi2::weightToSigma);
    1670       28080 :         msRow->setSigma (weight);
    1671             : 
    1672             :         // Now convert the DATA weight accumulation stored in sigmaSpectrum into the real SIGMA_SPECTRUM
    1673             :         // TODO: This should happen only if we are writing out SIGMA_SPECTRUM but
    1674             :         //       multiple column operation is rare and might be forbidden in the future
    1675       56160 :         Matrix<Float> sigmaSpectrun = msRow->sigmaSpectrum(); // Reference copy
    1676       56160 :         arrayTransformInPlace (sigmaSpectrun, AveragingTvi2::weightToSigma);
    1677             :     }
    1678             :     // Otherwise (doing only DATA/FLOAT_DATA or CORRECTED_DATA) we can derive SIGMA from WEIGHT directly
    1679      461059 :     else if ( not doing_p.onlymetadata_p)
    1680             :     {
    1681             :         // jagonzal: SIGMA is not derived from the mean of SIGMA_SPECTRUM
    1682             :         // but from WEIGHT turned into SIGMA by using 1/pow(weight,2)
    1683      922118 :         Vector<Float> sigma = msRow->sigma(); // Reference copy
    1684      461059 :         sigma = msRow->weight(); // Normal copy (transfer Weight values to Sigma)
    1685      461059 :         arrayTransformInPlace (sigma, AveragingTvi2::weightToSigma);
    1686             : 
    1687             :         // Derive SIGMA_SPECTRUM from computed WEIGHT_SPECTRUM
    1688      922118 :         Matrix<Float> sigmaSpectrun = msRow->sigmaSpectrum(); // Reference copy
    1689      461059 :         sigmaSpectrun = msRow->weightSpectrum(); // Normal copy (transfer WeightSpectrum values to SigmaSpectrum)
    1690      461059 :         arrayTransformInPlace (sigmaSpectrun, AveragingTvi2::weightToSigma);
    1691             :     }
    1692             : 
    1693             :     // Get the normalization factor for this baseline, containing
    1694             :     // the accumulation of row-level) weight contributions
    1695      489139 :     Double weight = msRow->getNormalizationFactor();
    1696             : 
    1697      489139 :     if (n != 0){
    1698             : 
    1699      489139 :         if (weight == 0){
    1700             : 
    1701             :             // The weights are all zero so compute an arithmetic average
    1702             :             // so that a somewhat value can go into these columns (i.e. rather than NaN).
    1703             : 
    1704           0 :             weight = msRow->countsBaseline();
    1705             :         }
    1706             : 
    1707      489139 :         msRow->setTimeCentroid (msRow->timeCentroid() / weight + msRow->timeFirst());
    1708             : 
    1709      489139 :         msRow->setUvw (msRow->uvw() / weight);
    1710             : 
    1711             :         // Exposure is a simple sum, not an average so it is already
    1712             :         // done at this point.
    1713             :     }
    1714             : 
    1715             :     // Fill in the time and the interval
    1716             :     //
    1717             :     // The time of a sample is centered over the integration time period.
    1718             :     // Thus find the center of the averaged interval it is necessary to
    1719             :     // slide it back by 1/2 an interval.
    1720             : 
    1721      489139 :     Double dT = msRow->timeLast () - msRow->timeFirst();
    1722             : 
    1723      489139 :     Double centerOfInterval = msRow->timeFirst () + dT / 2;
    1724             : 
    1725      489139 :     msRow->setTime (centerOfInterval);
    1726             : 
    1727      489139 :     if (dT != 0){
    1728             : 
    1729             :         // The interval is the center-to-center time + half of the intervals of
    1730             :         // the first and the last sample (if dT == 0 then the interval is
    1731             :         // already the interval of the first sample and is correct)
    1732             : 
    1733      439630 :         Double interval = dT + msRow->interval() / 2 + msRow->intervalLast() / 2;
    1734      439630 :         msRow->setInterval (interval);
    1735             :     }
    1736      489139 : }
    1737             : 
    1738             : void
    1739    10926206 : VbAvg::finalizeBaselineIfNeeded (MsRow * rowInput, MsRowAvg * rowAveraged, const Subchunk & /*subchunk*/)
    1740             : {
    1741    10926206 :     if (! rowAveraged->baselinePresent()){
    1742      277570 :         return;
    1743             :     }
    1744             : 
    1745             :     // Finalization is needed if either the uvw distance or the time distance between the input
    1746             :     // baseline and the averaged baseline is above the maximum
    1747             : 
    1748    10648636 :     Bool needed = usingUvwDistance_p;
    1749             : 
    1750    10648636 :     if (needed) {
    1751       16992 :         Double deltaUvw = distanceSquared (rowInput->uvw(), rowAveraged->uvwFirst ());
    1752       16992 :         needed = deltaUvw > maxUvwDistanceSquared_p;
    1753             :     }
    1754             : 
    1755    10648636 :     needed = needed || (rowInput->time() - rowAveraged->timeFirst()) > maxTimeDistance_p;
    1756             : 
    1757    10648636 :     if (needed){
    1758             : 
    1759             :         // Finalize the data so that the final averaging products and then move them to
    1760             :         // output buffer.
    1761             : 
    1762      211569 :         finalizeBaseline (rowAveraged);
    1763             :     }
    1764             : }
    1765             : 
    1766             : MsRowAvg *
    1767           0 : VbAvg::getRow (Int row) const
    1768             : {
    1769           0 :     return new MsRowAvg (row, this);
    1770             : }
    1771             : 
    1772             : MsRowAvg *
    1773      606549 : VbAvg::getRowMutable (Int row)
    1774             : {
    1775      606549 :     return new MsRowAvg (row, this);
    1776             : }
    1777             : 
    1778             : void
    1779      489139 : VbAvg::initializeBaseline (MsRow * rowInput, MsRowAvg * rowAveraged,
    1780             :                            const Subchunk & /*subchunk*/)
    1781             : {
    1782      489139 :     copyIdValues (rowInput, rowAveraged);
    1783             : 
    1784             :     // Size and zero out the counters
    1785             : 
    1786      489139 :     rowAveraged->setInterval (rowInput->interval()); // capture first one
    1787      489139 :     rowAveraged->setTimeFirst (rowInput->time());
    1788      489139 :     rowAveraged->setTimeLast (rowInput->time());
    1789      489139 :     rowAveraged->uvwFirst () = rowInput->uvw ();
    1790             : 
    1791      489139 :     rowAveraged->setCountsBaseline (0);
    1792             : 
    1793      978278 :     IPosition shape = rowInput->flags().shape();
    1794      489139 :     Int nCorrelations = shape (0);
    1795      489139 :     Int nChannels = shape (1);
    1796             : 
    1797      489139 :     rowAveraged->setCounts (zeroInt_p.getMatrix (nCorrelations, nChannels, 0));
    1798      489139 :     rowAveraged->setWeight (Vector<Float> (nCorrelations, 0));
    1799      489139 :     rowAveraged->setTimeCentroid (0.0);
    1800             : 
    1801      489139 :     if (doing_p.weightSpectrumOut_p){
    1802      489139 :         rowAveraged->setWeightSpectrum (zeroFloat_p.getMatrix (nCorrelations, nChannels, 0));
    1803             :     }
    1804             : 
    1805      489139 :     if (doing_p.sigmaSpectrumOut_p){
    1806      489139 :         rowAveraged->setSigmaSpectrum (zeroFloat_p.getMatrix (nCorrelations, nChannels, 0));
    1807             :     }
    1808             : 
    1809             : //    VisBufferComponents2 exclusions =
    1810             : //        VisBufferComponents2::these(VisibilityObserved, VisibilityCorrected,
    1811             : //                                    VisibilityModel, CorrType, JonesC, Unknown);
    1812             : //
    1813             : //    cacheResizeAndZero(exclusions);
    1814             : 
    1815             :     // Flag everything to start with
    1816             : 
    1817      489139 :     rowAveraged->setRowFlag (true); // only for use during row-value accumulation
    1818      489139 :     rowAveraged->setFlags(trueBool_p.getMatrix (nCorrelations, nChannels, true));
    1819      489139 :     rowAveraged->correlationFlagsMutable() = Vector<Bool> (nCorrelations, true);
    1820             : 
    1821      489139 :     rowAveraged->setBaselinePresent(true);
    1822             : 
    1823      489139 :     rowAveraged->setNormalizationFactor(0.0);
    1824      489139 : }
    1825             : 
    1826             : 
    1827             : Bool
    1828           0 : VbAvg::isComplete () const
    1829             : {
    1830           0 :     return complete_p;
    1831             : }
    1832             : 
    1833             : Bool
    1834      591805 : VbAvg::isUsingUvwDistance () const
    1835             : {
    1836      591805 :     return usingUvwDistance_p;
    1837             : }
    1838             : 
    1839             : 
    1840             : //void
    1841             : //VbAvg::markEmpty ()
    1842             : //{
    1843             : //    empty_p = true;
    1844             : //    complete_p = false;
    1845             : //}
    1846             : 
    1847             : Int
    1848      898486 : VbAvg::nBaselines () const
    1849             : {
    1850      898486 :     return countsBaseline_p.nelements();
    1851             : }
    1852             : 
    1853             : Int
    1854      591805 : VbAvg::nSpectralWindowsInBuffer () const
    1855             : {
    1856      591805 :     const Vector<Int> & windows = spectralWindows();
    1857      591805 :     set <Int> s;
    1858             : 
    1859    15803345 :     for (uInt i = 0; i < windows.nelements(); i ++){
    1860    15211540 :         s.insert (windows(i));
    1861             :     }
    1862             : 
    1863     1183610 :     return (Int) s.size();
    1864             : 
    1865             : }
    1866             : 
    1867             : 
    1868             : void
    1869       39498 : VbAvg::captureIterationInfo (VisBufferImpl2 * dstVb, const VisBuffer2 * srcVb,
    1870             :                              const Subchunk & subchunk)
    1871             : {
    1872       39498 :     dstVb->setIterationInfo (srcVb->msId(),
    1873       39498 :                              srcVb->msName(),
    1874       39498 :                              srcVb->isNewMs(),
    1875       39498 :                              srcVb->isNewArrayId(),
    1876       39498 :                              srcVb->isNewFieldId(),
    1877       39498 :                              srcVb->isNewSpectralWindow(),
    1878             :                              subchunk,
    1879       78996 :                              srcVb->getCorrelationTypes (),
    1880       78996 :                              srcVb->getCorrelationTypesDefined(),
    1881       78996 :                              srcVb->getCorrelationTypesSelected(),
    1882       78996 :                              CountedPtr <WeightScaling> ( ));
    1883             : 
    1884             :     // Request info from the VB which will cause it to be filled
    1885             :     // into cache from the input VII at its current position.
    1886             : 
    1887       39498 :     dstVb->setRekeyable(true);
    1888       39498 :     dstVb->setShape(srcVb->nCorrelations(), srcVb->nChannels(), nBaselines(), false);
    1889             :         // Do not clear the cache since we're resuing the storage
    1890             : 
    1891       39498 :     dstVb->phaseCenter();
    1892       39498 :     dstVb->nAntennas();
    1893       39498 :     dstVb->correlationTypes();
    1894       39498 :     dstVb->polarizationFrame();
    1895       39498 :     dstVb->polarizationId();
    1896       39498 : }
    1897             : 
    1898             : //void
    1899             : //VbAvg::prepareForFirstData (const VisBuffer2 * vb, const Subchunk & subchunk)
    1900             : //{
    1901             : //    startTime_p = vb->time() (0);
    1902             : //    sampleInterval_p = vb->timeInterval() (0);
    1903             : //
    1904             : //    Int nAntennas = vb->nAntennas();
    1905             : //    Int nSpw = vb->getVi()->nSpectralWindows();
    1906             : //    Int nBaselines = ((nAntennas * (nAntennas + 1)) / 2) * nSpw;
    1907             : //
    1908             : //    // Size and zero out the counters
    1909             : //
    1910             : //    timeFirst_p = Vector<Double> (nBaselines, vb->time() (0));
    1911             : //    timeLast_p = Vector<Double> (nBaselines, vb->time() (0));
    1912             : //    uvwFirst_p = Vector<Double> (nBaselines, vb->uvw().column(0));
    1913             : //
    1914             : //    countsBaseline_p = Vector<Int> (nBaselines, 0);
    1915             : //    counts_p = Cube<Int> (vb->nCorrelations(), vb->nChannels(), nBaselines, 0);
    1916             : //    weightSum_p = Cube<Float> (vb->nCorrelations(), vb->nChannels(), nBaselines, 0);
    1917             : //    if (doing_p.sigmaSpectrum_p){
    1918             : //        weightCorrectedSum_p = Cube<Float> (vb->nCorrelations(), vb->nChannels(), nBaselines, 0);
    1919             : //    }
    1920             : //
    1921             : //    baselineIndex_p.configure (nAntennas, nSpw, vb);
    1922             : //
    1923             : //    // Reshape the inherited members from VisBuffer2
    1924             : //
    1925             : //    captureIterationInfo (vb, subchunk);
    1926             : //
    1927             : //    setShape (vb->nCorrelations(), vb->nChannels(), nBaselines, false);
    1928             : //
    1929             : //    VisBufferComponents2 exclusions =
    1930             : //        VisBufferComponents2::these(VisibilityObserved, VisibilityCorrected,
    1931             : //                                    VisibilityModel, CorrType, JonesC, Unknown);
    1932             : //    cacheResizeAndZero(exclusions);
    1933             : //
    1934             : //    prepareIds (vb);
    1935             : //
    1936             : //    // Flag everything to start with
    1937             : //
    1938             : //    setFlagCube (Cube<Bool> (vb->nCorrelations(), vb->nChannels(), nBaselines, true));
    1939             : //    setFlagRow (Vector<Bool> (nBaselines, true));
    1940             : //
    1941             : //    complete_p = false;
    1942             : //}
    1943             : 
    1944             : void
    1945           0 : VbAvg::prepareIds (const VisBuffer2 * vb)
    1946             : {
    1947             :     // Set these row ID values to indicate they are unknown
    1948             : 
    1949           0 :     Vector<Int> minusOne (nBaselines(), -1);
    1950             : 
    1951           0 :     setAntenna1 (minusOne);
    1952           0 :     setAntenna2 (minusOne);
    1953           0 :     setDataDescriptionIds (minusOne);
    1954           0 :     setFeed1 (minusOne);
    1955           0 :     setFeed2 (minusOne);
    1956           0 :     setProcessorId (minusOne);
    1957           0 :     setScan (minusOne);
    1958           0 :     setObservationId (minusOne);
    1959           0 :     setSpectralWindows (minusOne);
    1960           0 :     setStateId (minusOne);
    1961             : 
    1962             :     // Copy the value from the input VB
    1963             : 
    1964           0 :     Vector<Int> tmp (nBaselines(), vb->arrayId()(0));
    1965             : 
    1966           0 :     setArrayId (tmp);
    1967             : 
    1968           0 :     tmp = vb->dataDescriptionIds()(0);
    1969           0 :     setDataDescriptionIds (tmp);
    1970             : 
    1971           0 :     tmp = vb->fieldId()(0);
    1972           0 :     setFieldId (tmp);
    1973           0 : }
    1974             : 
    1975             : //void
    1976             : //VbAvg::removeMissingBaselines ()
    1977             : //{
    1978             : //    // Some baselines may not be present in the portion of the input data
    1979             : //    // that made up this average.  However, this is not known until after
    1980             : //    // all of the data is seen.  Thus at finalization time these bogus
    1981             : //    // baselines should be removed from the average so as not to pass
    1982             : //    // flagged but zero-exposure baselines into the output.
    1983             : //
    1984             : //
    1985             : //    Vector<Int> rowsToDelete (nBaselines());
    1986             : //
    1987             : //    Int nBaselinesDeleted = 0;
    1988             : //
    1989             : //    for (Int baseline = 0; baseline < nBaselines(); baseline ++){
    1990             : //
    1991             : //        if (countsBaseline_p (baseline) == 0){
    1992             : //            rowsToDelete (nBaselinesDeleted) = baseline;
    1993             : //            nBaselinesDeleted ++;
    1994             : //        }
    1995             : //    }
    1996             : //
    1997             : //    rowsToDelete.resize (nBaselinesDeleted, true);
    1998             : //
    1999             : //    deleteRows (rowsToDelete);
    2000             : //}
    2001             : 
    2002             : void
    2003       52303 : VbAvg::setBufferToFill(VisBufferImpl2 * vb)
    2004             : {
    2005       52303 :     bufferToFill_p = vb;
    2006             : 
    2007             :     // Set flag so that iteration information will be captured into
    2008             :     // this VB from the first input VB.
    2009             : 
    2010       52303 :     needIterationInfo_p = true;
    2011       52303 : }
    2012             : 
    2013             : void
    2014       14667 : VbAvg::setupVbAvg (const VisBuffer2 * vb)
    2015             : {
    2016             :     // Configure the index
    2017             : 
    2018       14667 :     Int nAntennas = vb->nAntennas();
    2019             : 
    2020             :     // This is a kluge to allow multiple spectral windows (of the same shape)
    2021             :     // to be combined into a single VB.  This really shouldn't be allowed!!!
    2022             : 
    2023       14667 :     set<uInt> spwInVb;
    2024             : 
    2025      312511 :     for (rownr_t i = 0; i < vb->nRows(); i++){
    2026      297844 :         spwInVb.insert (vb->dataDescriptionIds()(i));
    2027             :     }
    2028             : 
    2029       14667 :     uInt nSpwInVb = spwInVb.size();
    2030             : 
    2031       14667 :     Int nSpw = averagingVii_p->nSpectralWindows();
    2032             : 
    2033       14667 :     baselineIndex_p.configure (nAntennas, nSpw, vb);
    2034             : 
    2035       14667 :     Int nBaselines = ((nAntennas * (nAntennas + 1)) / 2)* nSpwInVb;
    2036             : 
    2037       14667 :     setShape (vb->nCorrelations(), vb->nChannels(), nBaselines);
    2038             : 
    2039       14667 :     setupArrays (vb->nCorrelations(), vb->nChannels(), nBaselines);
    2040             : 
    2041       14667 :     baselinePresent_p.resize(nBaselines);
    2042       14667 :     baselinePresent_p = False;
    2043             : 
    2044       14667 :     normalizationFactor_p.resize(nBaselines);
    2045       14667 :     normalizationFactor_p = 0.0;
    2046             : 
    2047       14667 :     empty_p = false;
    2048       14667 : }
    2049             : 
    2050             : void
    2051       14667 : VbAvg::setupArrays (Int nCorrelations, Int nChannels, Int nBaselines)
    2052             : {
    2053             : 
    2054       14667 :     setShape (nCorrelations, nChannels, nBaselines);
    2055             : 
    2056             :     // Start out with all of the array-valued components except the
    2057             :     // optional ones.
    2058             : 
    2059             :     VisBufferComponents2 including =
    2060             :         VisBufferComponents2::these ({VisBufferComponent2::Antenna1,
    2061             :                     VisBufferComponent2::Antenna2,
    2062             :                     VisBufferComponent2::ArrayId,
    2063             :                     VisBufferComponent2::CorrType,
    2064             :                     VisBufferComponent2::DataDescriptionIds,
    2065             :                     VisBufferComponent2::Exposure,
    2066             :                     VisBufferComponent2::Feed1,
    2067             :                     VisBufferComponent2::Feed2,
    2068             :                     VisBufferComponent2::FieldId,
    2069             :                     VisBufferComponent2::FlagCategory,
    2070             :                     VisBufferComponent2::FlagCube,
    2071             :                     VisBufferComponent2::FlagRow,
    2072             :                     VisBufferComponent2::ObservationId,
    2073             :                     VisBufferComponent2::ProcessorId,
    2074             :                     VisBufferComponent2::RowIds,
    2075             :                     VisBufferComponent2::Scan,
    2076             :                     VisBufferComponent2::Sigma,
    2077             :                     VisBufferComponent2::SpectralWindows,
    2078             :                     VisBufferComponent2::StateId,
    2079             :                     VisBufferComponent2::Time,
    2080             :                     VisBufferComponent2::TimeCentroid,
    2081             :                     VisBufferComponent2::TimeInterval,
    2082             :                     VisBufferComponent2::Weight,
    2083       14667 :                     VisBufferComponent2::Uvw});
    2084             : 
    2085       14667 :     if (doing_p.modelData_p){
    2086        4283 :         including += VisBufferComponent2::VisibilityCubeModel;
    2087             :     }
    2088             : 
    2089       14667 :     if (doing_p.correctedData_p){
    2090        4322 :         including += VisBufferComponent2::VisibilityCubeCorrected;
    2091             :     }
    2092             : 
    2093       14667 :     if (doing_p.observedData_p){
    2094        9788 :         including += VisBufferComponent2::VisibilityCubeObserved;
    2095             :     }
    2096             : 
    2097       14667 :     if (doing_p.floatData_p){
    2098         498 :         including += VisBufferComponent2::VisibilityCubeFloat;
    2099             :     }
    2100             : 
    2101       14667 :     if (doing_p.weightSpectrumOut_p){
    2102       14667 :         including += VisBufferComponent2::WeightSpectrum;
    2103             :     }
    2104             : 
    2105       14667 :     if (doing_p.sigmaSpectrumOut_p){
    2106       14667 :         including += VisBufferComponent2::SigmaSpectrum;
    2107             :     }
    2108             : 
    2109       14667 :     cacheResizeAndZero (including);
    2110             : 
    2111       14667 :     correlationFlags_p.reference (Matrix<Bool> (IPosition (2, nCorrelations, nBaselines), true));
    2112       14667 :     counts_p.reference (Cube<Int> (IPosition (3, nCorrelations, nChannels, nBaselines), 0));
    2113       14667 :     countsBaseline_p.reference (Vector<Int> (nBaselines, 0)); // number of items summed together for each baseline.
    2114       14667 :     intervalLast_p.reference (Vector<Double> (nBaselines, 0));
    2115       14667 :     timeFirst_p.reference (Vector<Double> (nBaselines, 0));
    2116       14667 :     timeLast_p.reference (Vector<Double> (nBaselines, 0));
    2117       14667 :     uvwFirst_p.reference (Matrix<Double> (IPosition (2, 3, nBaselines), 0.0));
    2118       14667 : }
    2119             : 
    2120             : void
    2121       12480 : VbAvg::startChunk (ViImplementation2 * vi)
    2122             : {
    2123       12480 :     empty_p = true;
    2124             : 
    2125       12480 :     rowIdGenerator_p = 0;
    2126       12480 :     row2AvgRow_p.resize(0);
    2127             :     
    2128             :     // See if the new MS has corrected and/or model data columns
    2129             : 
    2130       12480 :     doing_p.observedData_p = averagingOptions_p.contains (AveragingOptions::AverageObserved);
    2131       21913 :     doing_p.correctedData_p = vi->existsColumn (VisBufferComponent2::VisibilityCubeCorrected) &&
    2132        9433 :                               averagingOptions_p.contains (AveragingOptions::AverageCorrected);
    2133       24960 :     doing_p.modelData_p = vi->existsColumn (VisBufferComponent2::VisibilityCubeModel) &&
    2134       12480 :                           averagingOptions_p.contains (AveragingOptions::AverageModel);
    2135       13016 :     doing_p.floatData_p = vi->existsColumn (VisBufferComponent2::VisibilityCubeFloat) &&
    2136         536 :                           averagingOptions_p.contains (AveragingOptions::AverageFloat);
    2137             : 
    2138       12480 :     doing_p.weightSpectrumIn_p = doing_p.correctedData_p;
    2139       12480 :     doing_p.sigmaSpectrumIn_p = doing_p.observedData_p || doing_p.floatData_p;
    2140       12480 :     doing_p.weightSpectrumOut_p = true; // We always use the output WeightSpectrum
    2141       12480 :     doing_p.sigmaSpectrumOut_p = true; // We always use the output SigmaSpectrum
    2142             : 
    2143       12480 :     if (doing_p.observedData_p or doing_p.correctedData_p or doing_p.modelData_p or doing_p.floatData_p)
    2144             :     {
    2145       12480 :         doing_p.onlymetadata_p = false;
    2146             :     }
    2147             : 
    2148             :     // Set up the flags for row copying
    2149             : 
    2150       12480 :     optionalComponentsToCopy_p = VisBufferComponents2::none();
    2151             : 
    2152       12480 :     if (doing_p.observedData_p){
    2153        4082 :         optionalComponentsToCopy_p += VisBufferComponent2::VisibilityCubeObserved;
    2154             :     }
    2155             : 
    2156       12480 :     if (doing_p.correctedData_p){
    2157        7801 :         optionalComponentsToCopy_p += VisBufferComponent2::VisibilityCubeCorrected;
    2158             :     }
    2159             : 
    2160       12480 :     if (doing_p.modelData_p){
    2161        7756 :         optionalComponentsToCopy_p += VisBufferComponent2::VisibilityCubeModel;
    2162             :     }
    2163             : 
    2164       12480 :     if (doing_p.floatData_p){
    2165         536 :         optionalComponentsToCopy_p += VisBufferComponent2::VisibilityCubeFloat;
    2166             :     }
    2167             : 
    2168       12480 :     if (doing_p.weightSpectrumOut_p){
    2169       12480 :         optionalComponentsToCopy_p += VisBufferComponent2::WeightSpectrum;
    2170             :     }
    2171             : 
    2172       12480 :     if (doing_p.sigmaSpectrumOut_p){
    2173       12480 :         optionalComponentsToCopy_p += VisBufferComponent2::SigmaSpectrum;
    2174             :     }
    2175       12480 : }
    2176             : 
    2177             : void
    2178      489139 : VbAvg::transferBaseline (MsRowAvg * rowAveraged)
    2179             : {
    2180      489139 :     rowAveraged->setRowId (rowIdGenerator_p ++);
    2181      489139 :     bufferToFill_p->appendRow (rowAveraged, nBaselines(), optionalComponentsToCopy_p);
    2182             : 
    2183      489139 :     rowAveraged->setBaselinePresent(false);
    2184      489139 : }
    2185             : 
    2186             : 
    2187             : //VbSet::VbSet (const AveragingParameters & averagingParameters)
    2188             : //: averagingInterval_p (averagingParameters.getAveragingInterval ()),
    2189             : //  averagingOptions_p (averagingParameters.getOptions()),
    2190             : //  averagingParameters_p (averagingParameters),
    2191             : //  doingCorrectedData_p (false),
    2192             : //  doingModelData_p (false),
    2193             : //  doingObservedData_p (false),
    2194             : //  doingWeightSpectrum_p (false),
    2195             : //  doingsigmaSpectrum_p (false),
    2196             : //  vbAveragers_p ()
    2197             : //{}
    2198             : 
    2199             : //VbSet::~VbSet ()
    2200             : //{
    2201             : //    flush (true); // allow killing nonempty buffers
    2202             : //}
    2203             : //
    2204             : //void
    2205             : //VbSet::accumulate (const VisBuffer2 * input, const Subchunk & subchunk)
    2206             : //{
    2207             : //    Int ddId = input->dataDescriptionIds()(0);
    2208             : //
    2209             : //    if (! utilj::containsKey (ddId, vbAveragers_p)){ // Need a new averager
    2210             : //        add (ddId);
    2211             : //    }
    2212             : //
    2213             : //    VbAvg * vba = vbAveragers_p [ddId];
    2214             : //
    2215             : //    vba->accumulate (input, subchunk);
    2216             : //}
    2217             : //
    2218             : //VbAvg *
    2219             : //VbSet::add (Int ddId)
    2220             : //{
    2221             : //    VbAvg::Doing doing;
    2222             : //
    2223             : //    doing.correctedData_p = doingCorrectedData_p;
    2224             : //    doing.modelData_p = doingModelData_p;
    2225             : //    doing.observedData_p = doingObservedData_p;
    2226             : //    doing.weightSpectrum_p = doingWeightSpectrum_p;
    2227             : //    doing.sigmaSpectrum_p = doingsigmaSpectrum_p;
    2228             : //
    2229             : //    VbAvg * newAverager =  new VbAvg (doing, averagingParameters_p);
    2230             : //
    2231             : //    vbAveragers_p [ddId] = newAverager;
    2232             : //
    2233             : //    return newAverager;
    2234             : //}
    2235             : //
    2236             : //Bool
    2237             : //VbSet::anyAveragesReady(Int ddid) const
    2238             : //{
    2239             : //    Bool any = false;
    2240             : //
    2241             : //    for (Averagers::const_iterator a = vbAveragers_p.begin();
    2242             : //         a != vbAveragers_p.end();
    2243             : //         a++){
    2244             : //
    2245             : //        if (a->second->isComplete() &&
    2246             : //            (ddid < 0 || ddid == a->second->dataDescriptionIds()(0))){
    2247             : //
    2248             : //            any = true;
    2249             : //            break;
    2250             : //        }
    2251             : //    }
    2252             : //
    2253             : //    return any;
    2254             : //}
    2255             : //
    2256             : //Bool
    2257             : //VbSet::contains (Int ddId) const
    2258             : //{
    2259             : //    return vbAveragers_p.find (ddId) != vbAveragers_p.end();
    2260             : //}
    2261             : //
    2262             : ////void
    2263             : ////VbSet::finalizeAverage (Int ddId)
    2264             : ////{
    2265             : ////    vbAveragers_p [ddId]->finalizeAverage();
    2266             : ////}
    2267             : //
    2268             : //void
    2269             : //VbSet::finalizeAverages ()
    2270             : //{
    2271             : ////    for (Averagers::iterator a = vbAveragers_p.begin();
    2272             : ////         a != vbAveragers_p.end();
    2273             : ////         a ++){
    2274             : ////
    2275             : ////        finalizeAverage (a->first);
    2276             : ////    }
    2277             : //}
    2278             : //
    2279             : //void
    2280             : //VbSet::flush (Bool okIfNonempty, ViImplementation2 * vi)
    2281             : //{
    2282             : //    // Get rid of all of the averagers.  This is done at
    2283             : //    // destruction time and when a sweeping into a new MS.
    2284             : //
    2285             : //    for (Averagers::const_iterator a = vbAveragers_p.begin();
    2286             : //         a != vbAveragers_p.end();
    2287             : //         a ++){
    2288             : //
    2289             : //        Assert (okIfNonempty || (a->second)->empty());
    2290             : //            // should have been emptied before calling this
    2291             : //
    2292             : //        delete a->second;
    2293             : //    }
    2294             : //
    2295             : //    vbAveragers_p.clear();
    2296             : //
    2297             : //    seeIfCubeColumnsExist (vi);
    2298             : //}
    2299             : //
    2300             : //void
    2301             : //VbSet::seeIfCubeColumnsExist (ViImplementation2 * vi)
    2302             : //{
    2303             : //    if (vi != 0){
    2304             : //
    2305             : //        // See if the new MS has corrected and/or model data columns
    2306             : //
    2307             : //        doingObservedData_p = averagingOptions_p.contains (AveragingOptions::AverageObserved);
    2308             : //        doingCorrectedData_p = vi->existsColumn (VisibilityCubeCorrected) &&
    2309             : //                               averagingOptions_p.contains (AveragingOptions::AverageCorrected);
    2310             : //        doingModelData_p = vi->existsColumn (VisibilityCubeModel) &&
    2311             : //                               averagingOptions_p.contains (AveragingOptions::AverageModel);
    2312             : //        doingWeightSpectrum_p = vi->existsColumn (WeightSpectrum);
    2313             : //
    2314             : //        // If the use of corrected weights were specified for one of the averages, it's an
    2315             : //        // error if the column does not exist.  Also set the doing flag for corrected weights
    2316             : //        // if it's being used in some way.
    2317             : //
    2318             : //        Bool needCorrectedWeights =
    2319             : //            averagingOptions_p.contains (AveragingOptions::ModelUseCorrectedWeights) ||
    2320             : //            averagingOptions_p.contains (AveragingOptions::CorrectedUseCorrectedWeights);
    2321             : //
    2322             : //        Bool correctedWeightsMissing = needCorrectedWeights &&
    2323             : //                                       ! vi->existsColumn (sigmaSpectrum);
    2324             : //
    2325             : //        ThrowIf (correctedWeightsMissing,
    2326             : //                 "Corrected_weight_spectrum not present but required by provided averaging options");
    2327             : //
    2328             : //        doingsigmaSpectrum_p = needCorrectedWeights;
    2329             : //    }
    2330             : //}
    2331             : //
    2332             : //Int
    2333             : //VbSet::getFirstReadyDdid () const
    2334             : //{
    2335             : //    for (Averagers::const_iterator a = vbAveragers_p.begin();
    2336             : //         a != vbAveragers_p.end();
    2337             : //         a ++){
    2338             : //
    2339             : //        if (a->second->isComplete()){
    2340             : //            return a->first;
    2341             : //        }
    2342             : //    }
    2343             : //
    2344             : //    Assert (false); // ought to have been one that's ready
    2345             : //
    2346             : //    return -1; // shouldn't be called
    2347             : //}
    2348             : //
    2349             : ////void
    2350             : ////VbSet::transferAverage (Int ddId, VisBuffer2 * vb)
    2351             : ////{
    2352             : ////    Assert (utilj::containsKey (ddId, vbAveragers_p));
    2353             : ////
    2354             : ////    VbAvg * vba = vbAveragers_p [ddId];
    2355             : ////
    2356             : ////    Assert (vba != 0 && ! vba->empty ());
    2357             : ////
    2358             : ////    // Copy< the completed average into the provided VisBuffer, but
    2359             : ////    // first reshape the VB if it's shape is different.
    2360             : ////
    2361             : ////    vba->transferAverage (vb);
    2362             : ////
    2363             : ////}
    2364             : //
    2365             : //void
    2366             : //VbSet::zero ()
    2367             : //{
    2368             : //    for (Averagers::const_iterator a = vbAveragers_p.begin();
    2369             : //         a != vbAveragers_p.end();
    2370             : //         a ++){
    2371             : //
    2372             : //        a->second->markEmpty();
    2373             : //    }
    2374             : //}
    2375             : 
    2376             :     ///////////////////////
    2377             :     //                   //
    2378             :     // End Namespace avg //
    2379             :     //                   //
    2380             :     ///////////////////////
    2381             : 
    2382             : } // end avg
    2383             : 
    2384             : using namespace avg;
    2385             : 
    2386         362 : AveragingTvi2::AveragingTvi2 (ViImplementation2 * inputVi,
    2387         362 :                               const AveragingParameters & averagingParameters)
    2388             : : TransformingVi2 (inputVi),
    2389         724 :   averagingInterval_p (averagingParameters.getAveragingInterval()),
    2390         724 :   averagingOptions_p (averagingParameters.getOptions()),
    2391             :   averagingParameters_p (averagingParameters),
    2392             :   ddidLastUsed_p (-1),
    2393             :   inputViiAdvanced_p (false),
    2394         362 :   vbAvg_p (new VbAvg (averagingParameters, this))
    2395             : {
    2396         362 :     validateInputVi (inputVi);
    2397             : 
    2398             :     // Position input Vi to the first subchunk
    2399             : 
    2400         362 :     getVii()->originChunks();
    2401         362 :     getVii()->origin ();
    2402             : 
    2403         362 :     setVisBuffer (createAttachedVisBuffer (VbNoOptions));
    2404         362 : }
    2405             : 
    2406         724 : AveragingTvi2::~AveragingTvi2 ()
    2407             : {
    2408         362 :     delete vbAvg_p;
    2409         724 : }
    2410             : 
    2411             : //void
    2412             : //AveragingTvi2::advanceInputVii ()
    2413             : //{
    2414             : //    Assert (false);
    2415             : //
    2416             : //    // Attempt to advance to the next subchunk
    2417             : //
    2418             : //    getVii()->next ();
    2419             : //
    2420             : //    if (! getVii()->more()){
    2421             : //
    2422             : //        // No more subchunks so advance to the next chunk
    2423             : //
    2424             : //        getVii()->nextChunk();
    2425             : //
    2426             : //        if (! getVii()->moreChunks()){
    2427             : //            return; // no more chunks
    2428             : //        }
    2429             : //
    2430             : //        // Position to the first subchunk
    2431             : //
    2432             : //        getVii()->origin();
    2433             : //    }
    2434             : //}
    2435             : 
    2436             : //Int
    2437             : //AveragingTvi2::determineDdidToUse() const
    2438             : //{
    2439             : //    if (ddidLastUsed_p >= 0 && vbSet_p->anyAveragesReady (ddidLastUsed_p)){
    2440             : //        return ddidLastUsed_p;
    2441             : //    }
    2442             : //
    2443             : //    return vbSet_p->getFirstReadyDdid();
    2444             : //}
    2445             : 
    2446             : Bool
    2447       56160 : AveragingTvi2::more () const
    2448             : {
    2449       56160 :     return more_p;
    2450             : }
    2451             : 
    2452             : Bool
    2453       25212 : AveragingTvi2::moreChunks () const
    2454             : {
    2455       25212 :     return getVii()->moreChunks();
    2456             : }
    2457             : 
    2458             : void
    2459       37636 : AveragingTvi2::next ()
    2460             : {
    2461       37636 :     subchunkExists_p = false;
    2462             : 
    2463       37636 :     startBuffer_p = endBuffer_p + 1;
    2464       37636 :     endBuffer_p = startBuffer_p - 1;
    2465             : 
    2466       37636 :     if (getVii()->more()){
    2467       24927 :         getVii()->next();
    2468       24927 :         endBuffer_p++;
    2469             :     }
    2470             : 
    2471       37636 :     produceSubchunk ();
    2472             : 
    2473       37636 :     subchunk_p.incrementSubChunk();
    2474       37636 : }
    2475             : 
    2476             : void
    2477       11975 : AveragingTvi2::nextChunk ()
    2478             : {
    2479             :     // New chunk, so toss all of the accumulators
    2480             : 
    2481       11975 :     vbAvg_p->startChunk (getVii());
    2482             : 
    2483             :     // Advance the input to the next chunk as well.
    2484             : 
    2485       11975 :     getVii()->nextChunk ();
    2486             : 
    2487       11975 :     subchunk_p.incrementChunk();
    2488             : 
    2489       11975 :     more_p = false;
    2490       11975 : }
    2491             : 
    2492             : void
    2493       14667 : AveragingTvi2::origin ()
    2494             : {
    2495             :     // Position input VI to the start of the chunk
    2496             : 
    2497       14667 :     subchunk_p.resetSubChunk();
    2498             : 
    2499       14667 :     getVii()->origin();
    2500             : 
    2501       14667 :     startBuffer_p = 0;
    2502       14667 :     endBuffer_p = -1;
    2503             : 
    2504             :     // Get the first subchunk ready.
    2505             : 
    2506       14667 :     produceSubchunk ();
    2507       14667 : }
    2508             : 
    2509             : void
    2510         505 : AveragingTvi2::originChunks (Bool forceRewind)
    2511             : {
    2512             :     // Ensure that the underlying VI is in a state where some metadata
    2513             :     // can be retrieved
    2514         505 :     getVii()->originChunks(forceRewind);
    2515             : 
    2516             :     // Initialize the chunk
    2517         505 :     vbAvg_p->startChunk (getVii());
    2518             : 
    2519         505 :     more_p = false;
    2520             : 
    2521         505 :     subchunk_p.resetToOrigin();
    2522         505 : }
    2523             : 
    2524             : /**
    2525             :  * Configure a VisBuffer with given averagingOptions related to phase shifting
    2526             :  *
    2527             :  * @param vb a VisBuffer to set up in terms of phase shifting
    2528             :  * @param averagingOptions averaging options enabled
    2529             :  * @param avgPars AveragingParmeters object to set into the buffer
    2530             :  */
    2531             : void
    2532      591882 : setPhaseShiftingOptions(VisBuffer2 * vb, const AveragingOptions &averagingOptions,
    2533             :                         const AveragingParameters &avgPars)
    2534             : {
    2535      591882 :     if (averagingOptions.contains (AveragingOptions::phaseShifting))
    2536             :     {
    2537           0 :         if (averagingOptions.contains (AveragingOptions::AverageObserved))
    2538             :         {
    2539           0 :             vb->visCube();
    2540             :         }
    2541             : 
    2542           0 :         if (averagingOptions.contains (AveragingOptions::AverageCorrected))
    2543             :         {
    2544           0 :             vb->visCubeCorrected();
    2545             :         }
    2546             : 
    2547           0 :         if (averagingOptions.contains (AveragingOptions::AverageModel))
    2548             :         {
    2549           0 :             vb->visCubeModel();
    2550             :         }
    2551             : 
    2552           0 :         vb->phaseCenterShift(avgPars.getXpcOffset(),
    2553           0 :                              avgPars.getYpcOffset());
    2554             :     }
    2555      591882 : }
    2556             : 
    2557             : /**
    2558             :  * The iteration of this method is different depending on whether "row blocking" is used or
    2559             :  * not. The reason is that the while loop already had enough complexity embedded when fixes
    2560             :  * were done to get flagdata+time-average+row-blocking working (CAS-11910). Hopefully in the
    2561             :  * near future we can get rid of the hacky "row blocking" feature. For the time being, it is
    2562             :  * not clear how it could possibly work together with the "uvwdistance" feature. So better
    2563             :  * to keep those features separate.
    2564             :  *
    2565             :  * So the "if (block > 0)" separates iteration when using row blocking. That implies that
    2566             :  * row blocking takes precedence over (and disables) other features like
    2567             :  * "isUsingUvwDistance()".
    2568             :  * An alternative would be to add comparisons between block and vbToFill->appendSize() in
    2569             :  * the ifs below.  Something like:
    2570             :  *         if (! vbAvg_p->isUsingUvwDistance()
    2571             :  *            && (block == 0 && vbToFill->appendSize() > 0
    2572             :  *                || (block > 0 && vbToFill->appendSize() >= block)
    2573             :  *                )
    2574             :  *            ){
    2575             :  *          ...
    2576             :  *         else if ((block > 0 && vbToFill->appendSize() < block) ||
    2577             :  *                 vbToFill->appendSize() < nBaselines * nWindows){
    2578             :  *         ...
    2579             :  *         } else {
    2580             :  *
    2581             :  * But I prefer not adding more complexity to those ifs. The potential combinations would
    2582             :  * be too many to handle in a handful of if branches, and they are not well understood let
    2583             :  * alone well tested.
    2584             :  */
    2585             : void
    2586       52303 : AveragingTvi2::produceSubchunk ()
    2587             : {
    2588       52303 :     VisBufferImpl2 * vbToFill = dynamic_cast<VisBufferImpl2 *> (getVisBuffer());
    2589       52303 :     assert (vbToFill != 0);
    2590             : 
    2591       52303 :     vbToFill->setFillable (true); // New subchunk, so it's fillable
    2592             : 
    2593       52303 :     vbAvg_p->setBufferToFill (vbToFill);
    2594             : 
    2595       52303 :     Int nBaselines = nAntennas() * (nAntennas() -1) / 2;
    2596             :         // This is just a heuristic to keep output VBs from being too small
    2597             : 
    2598             :     // jagonzal: Handle nBaselines for SD case
    2599       52303 :     if (nBaselines == 0) nBaselines = 1;
    2600             : 
    2601       52303 :     auto block = getVii()->getRowBlocking();
    2602      619258 :     while (getVii()->more()){
    2603             : 
    2604      591882 :         VisBuffer2 * vb = getVii()->getVisBuffer();
    2605             : 
    2606      591882 :         setPhaseShiftingOptions(vb, averagingOptions_p, averagingParameters_p);
    2607             : 
    2608      591882 :         bool rowBlocking = block > 0;
    2609      591882 :         vbAvg_p->accumulate (vb, subchunk_p);
    2610             : 
    2611      591882 :         if (rowBlocking) {
    2612          77 :             auto app = vbToFill->appendSize();
    2613          77 :             if (app <= block) {
    2614          77 :                 getVii()->next();
    2615          77 :                 endBuffer_p++;
    2616             :             } else {
    2617           0 :                 break;
    2618             :             }
    2619             :         } else {
    2620      591805 :             Int nWindows = vbAvg_p->nSpectralWindowsInBuffer ();
    2621      591805 :             if (! vbAvg_p->isUsingUvwDistance() && vbToFill->appendSize() > 0){
    2622             :                 // Doing straight average and some data has been produced so
    2623             :                 // output it to the user
    2624       24791 :                 break;
    2625             :             }
    2626      567014 :             else if (vbToFill->appendSize() < nBaselines * nWindows) {
    2627      566878 :                 getVii()->next();
    2628      566878 :                 endBuffer_p++;
    2629             :             }
    2630             :             else {
    2631         136 :                 break;
    2632             :             }
    2633             :         }
    2634             :     };
    2635             : 
    2636       52303 :     if (! getVii()->more()){
    2637       27376 :         vbAvg_p->finalizeAverages ();
    2638             :     }
    2639             : 
    2640       52303 :     vbAvg_p->finalizeBufferFilling ();
    2641             : 
    2642       79679 :     more_p = getVii()->more() || // more to read
    2643       27376 :              vbToFill->nRows() > 0; // some to process
    2644       52303 : }
    2645             : 
    2646             : // Bool
    2647             : // AveragingTvi2::reachedAveragingBoundary()
    2648             : // {
    2649             : //     // An average can be terminated for a variety of reasons:
    2650             : //     // o the time interval has elapsed
    2651             : //     // o the current MS is completed
    2652             : //     // o no more input data
    2653             : //     // o other (e.g, change of scan, etc.)
    2654             : 
    2655             : //     Bool reachedIt = false;
    2656             : //     VisBuffer2 * vb = getVii()->getVisBuffer();
    2657             : 
    2658             : //     if (! getVii()->more()  && ! getVii ()->moreChunks()){
    2659             : 
    2660             : //         reachedIt = true; // no more input data
    2661             : //     }
    2662             : //     else if (vb->isNewMs()){
    2663             : //         reachedIt = true; // new MS
    2664             : //     }
    2665             : 
    2666             : //     return reachedIt;
    2667             : // }
    2668             : 
    2669             : //Bool
    2670             : //AveragingTvi2::subchunksReady() const
    2671             : //{
    2672             : //    Bool ready = vbSet_p->anyAveragesReady();
    2673             : //
    2674             : //    return ready;
    2675             : //}
    2676             : 
    2677             : void
    2678         362 : AveragingTvi2::validateInputVi (ViImplementation2 *)
    2679             : {
    2680             :     // Validate that the input VI is compatible with this VI.
    2681             : 
    2682             :     // No implmented right now
    2683         362 : }
    2684             : 
    2685   402239872 : Float AveragingTvi2::weightToSigma (Float weight)
    2686             : {
    2687   402239872 :     return weight > FLT_MIN ? 1.0 / std::sqrt (weight) : -1.0; // bogosity indicator
    2688             : }
    2689             : 
    2690             : Vector<Float>
    2691     5332843 : AveragingTvi2::average (const Matrix<Float> &data, const Matrix<Bool> &flags)
    2692             : {
    2693    10665686 :     IPosition shape = data.shape();
    2694     5332843 :     Vector<Float> result(shape(0),0);
    2695    10665686 :     Vector<uInt> samples(shape(0),0);
    2696     5332843 :     uInt nCorrelations = shape (0);
    2697     5332843 :     uInt nChannels = shape (1);
    2698             : 
    2699    20675499 :     for (uInt correlation = 0; correlation < nCorrelations; correlation++)
    2700             :     {
    2701    15342656 :         int nSamples = 0;
    2702    15342656 :         float sum = 0;
    2703    15342656 :         bool accumulatorFlag = true;
    2704             : 
    2705   654309382 :         for (uInt channel=0; channel< nChannels; channel++)
    2706             :         {
    2707   638966726 :             Bool inputFlag = flags(correlation,channel);
    2708             :             // true/true or false/false
    2709   638966726 :             if (accumulatorFlag == inputFlag)
    2710             :             {
    2711   611577896 :                 nSamples ++;
    2712   611577896 :                 sum += data (correlation, channel);
    2713             :             }
    2714             :             // true/false: Reset accumulation when accumulator switches from flagged to unflagged
    2715    27388830 :             else if ( accumulatorFlag and ! inputFlag )
    2716             :             {
    2717    14121570 :                 accumulatorFlag = false;
    2718    14121570 :                 nSamples = 1;
    2719    14121570 :                 sum = data (correlation, channel);
    2720             :             }
    2721             :             // else ignore case where accumulator is valid and data is not
    2722             : 
    2723             :         }
    2724             : 
    2725    15342656 :         result (correlation) = sum / (nSamples != 0 ? nSamples : 1);
    2726             :     }
    2727             : 
    2728    10665686 :     return result;
    2729             : }
    2730             : 
    2731             : Matrix<Float>
    2732      300114 : AveragingTvi2::average (const Cube<Float> &data, const Cube<Bool> &flags)
    2733             : {
    2734      600228 :         IPosition shape = data.shape();
    2735      300114 :         uInt nRows = shape(2);
    2736      300114 :         uInt nCorrelations = shape (0);
    2737             : 
    2738      300114 :         Matrix<Float> result(nCorrelations, nRows, 0);
    2739             : 
    2740     5115738 :         for (uInt row=0; row < nRows; row++)
    2741             :         {
    2742     4815624 :                 result.column(row) = AveragingTvi2::average (data.xyPlane(row), flags.xyPlane(row));
    2743             :         }
    2744             : 
    2745      600228 :     return result;
    2746             : }
    2747             : 
    2748             : /**
    2749             :  * Strategy to support different ways of propagating flags from the 'transformed' cube to
    2750             :  * the original ('propagated') cube. Iterates through rows, channels, correlations.
    2751             :  *
    2752             :  * This is meant to be used from propagateChanAvgFlags with at least two alternative
    2753             :  * functors. One to propagate flags as required by flagdata (preserve pre-existing flags
    2754             :  * in the original data cube), and a second one to propagate flags as required by plotms.
    2755             :  * CAS-12737, CAS-9985, CAS-12205.
    2756             :  *
    2757             :  * @param flagrow per row FLAG_ROW value
    2758             :  * @param flagMapped propagated FLAG_ROW
    2759             :  * @param flagCubeMapped Cube of flags in which flags are to be propagated
    2760             :  * @param row2AvgRow map of input_buffer_row_index->output_buffer_row_index (this is pre-
    2761             :  *        calculated by the "VbAvg" when averaging rows and is needed here).
    2762             :  */
    2763             : template <typename Functor>
    2764         529 : void cubePropagateFlags(const Vector<Bool> &flagRow,
    2765             :                         Vector<Bool> &flagMapped,
    2766             :                         Cube<Bool> &flagCubeMapped,
    2767             :                         std::vector<size_t> row2AvgRow,
    2768             :                         Functor propagate)
    2769             : {
    2770         529 :     Int nRowsMapped = flagCubeMapped.shape()[2];
    2771       17169 :     for(Int rowMapped=0; rowMapped < nRowsMapped; ++rowMapped) {
    2772       16640 :         size_t index = row2AvgRow[rowMapped];
    2773       16640 :         flagMapped(rowMapped) = flagRow(index);
    2774             : 
    2775     1081600 :         for (Int chan_i=0; chan_i < flagCubeMapped.shape()[1]; ++chan_i) {
    2776     5324800 :             for (Int corr_i=0; corr_i<flagCubeMapped.shape()[0]; ++corr_i) {
    2777     4259840 :                 propagate(rowMapped, chan_i, corr_i, index);
    2778             :             }
    2779             :         }
    2780             :     }
    2781         529 : }
    2782             : 
    2783             : // -----------------------------------------------------------------------
    2784             : //
    2785             : // -----------------------------------------------------------------------
    2786         208 : void AveragingTvi2::writeFlag (const Cube<Bool> & flag)
    2787             : {
    2788             :     // Calculate FLAG_ROW from flag
    2789         416 :     Vector<Bool> flagRow;
    2790         208 :     TransformingVi2::calculateFlagRowFromFlagCube(flag, flagRow);
    2791             : 
    2792             :     const auto flagdataFlagPropagation =
    2793         208 :         averagingOptions_p.contains(AveragingOptions::flagdataFlagPropagation);
    2794             : 
    2795             :     // Propagate transformed flags
    2796         208 :     getVii()->origin();
    2797         208 :     Int currentBuffer = 0;
    2798        7285 :     while (getVii()->more())
    2799             :     {
    2800        7285 :         if ((currentBuffer >= startBuffer_p) and (currentBuffer <= endBuffer_p))
    2801             :         {
    2802             :             // Allocated propagated flag vector/cube
    2803         529 :             uInt nOriginalRows = getVii()->getVisBuffer()->nRows();
    2804        1058 :             Vector<Bool> flagMapped(nOriginalRows,false);
    2805        1058 :             Cube<Bool> flagCubeMapped;
    2806         529 :             flagCubeMapped = getVii()->getVisBuffer()->flagCube();
    2807             : 
    2808             :             // Keeping two separate blocks for 'flagdataFlagPropagation' (CAS-12737,
    2809             :             // CAS-12205, CAS-9985) until this issue is better settled.
    2810             :             // Fill propagated flag vector/cube
    2811         529 :             if (flagdataFlagPropagation)
    2812             :             {
    2813         529 :                 cubePropagateFlags(flagRow, flagMapped, flagCubeMapped, vbAvg_p->row2AvgRow(),
    2814             :                                    [&flag, &flagCubeMapped]
    2815     4902708 :                                    (uInt rowMapped, uInt chan_i, uInt corr_i, uInt index) {
    2816     4259840 :                                        if (flag(corr_i,chan_i,index))
    2817      642868 :                                            flagCubeMapped(corr_i,chan_i,rowMapped) = true;
    2818     4259840 :                                    });
    2819             :             }
    2820             :             else
    2821             :             {
    2822           0 :                 cubePropagateFlags(flagRow, flagMapped, flagCubeMapped, vbAvg_p->row2AvgRow(),
    2823             :                                    [&flag, &flagCubeMapped]
    2824           0 :                                    (uInt rowMapped, uInt chan_i, uInt corr_i, uInt index) {
    2825           0 :                                        flagCubeMapped(corr_i, chan_i, rowMapped) =
    2826           0 :                                            flag(corr_i, chan_i, index);
    2827           0 :                                    });
    2828             :             }
    2829             : 
    2830             :             // Write propagated flag vector/cube
    2831         529 :             getVii()->writeFlag(flagCubeMapped);
    2832         529 :             getVii()->writeFlagRow(flagMapped);
    2833             :         }
    2834             : 
    2835        7285 :         currentBuffer++;
    2836        7285 :         getVii()->next();
    2837        7285 :         if (currentBuffer > endBuffer_p) break;
    2838             :     }
    2839         208 : }
    2840             : 
    2841             : // -----------------------------------------------------------------------
    2842             : //
    2843             : // -----------------------------------------------------------------------
    2844          12 : void AveragingTvi2::writeFlagRow (const Vector<Bool> & flagRow)
    2845             : {
    2846             :         // Create index map for averaged data
    2847          12 :         VisBuffer2 *avgVB = getVisBuffer();
    2848          24 :         Vector<Int> avgAnt1 = avgVB->antenna1();
    2849          24 :         Vector<Int> avgAnt2 = avgVB->antenna2();
    2850          24 :         Vector<Int> avgSPW = avgVB->spectralWindows();
    2851             : 
    2852          24 :         std::map< Int, std::map <Int, std::map< Int, uInt> >  > spwAnt1Ant2IndexMap;
    2853         574 :         for (uInt avgRow=0;avgRow<avgAnt1.size();avgRow++)
    2854             :         {
    2855         562 :                 spwAnt1Ant2IndexMap[avgSPW(avgRow)][avgAnt1(avgRow)][avgAnt2(avgRow)] = avgRow;
    2856             :         }
    2857             : 
    2858             :         // Propagate transformed flags
    2859          12 :         getVii()->origin();
    2860          12 :         Int currentBuffer = 0;
    2861         106 :         while (getVii()->more())
    2862             :         {
    2863         106 :                 if ((currentBuffer >= startBuffer_p) and (currentBuffer <= endBuffer_p))
    2864             :                 {
    2865             :                         // Allocated propagated flag vector/cube
    2866         106 :                         uInt nOriginalRows = getVii()->getVisBuffer()->nRows();
    2867         212 :                         Vector<Bool> flagMapped(nOriginalRows,false);
    2868             : 
    2869             :                         // Get original ant1/ant2/spw cols. to determine the mapped index
    2870         212 :                         Vector<Int> orgAnt1 = getVii()->getVisBuffer()->antenna1();
    2871         212 :                         Vector<Int> orgAnt2 = getVii()->getVisBuffer()->antenna2();
    2872         212 :                         Vector<Int> orgSPW = getVii()->getVisBuffer()->spectralWindows();
    2873             : 
    2874             :                         // Fill propagated flag vector/cube
    2875        1466 :                         for (uInt row=0;row<nOriginalRows;row++)
    2876             :                         {
    2877        1360 :                                 uInt index = spwAnt1Ant2IndexMap[orgSPW(row)][orgAnt1(row)][orgAnt2(row)];
    2878        1360 :                                 flagMapped(row) = flagRow(index);
    2879             :                         }
    2880             : 
    2881             :                         // Write propagated flag vector/cube
    2882         106 :                         getVii()->writeFlagRow(flagMapped);
    2883             : 
    2884             :                 }
    2885             : 
    2886         106 :                 currentBuffer += 1;
    2887         106 :                 getVii()->next();
    2888         106 :                 if (currentBuffer > endBuffer_p) break;
    2889             :         }
    2890             : 
    2891          24 :         return;
    2892             : }
    2893             : 
    2894           0 : void AveragingTvi2::visibilityObserved(casacore::Cube<casacore::Complex>& vis) const
    2895             : {
    2896           0 :   if(!averagingOptions_p.contains(AveragingOptions::AverageObserved))
    2897           0 :       throw AipsError("Requesting visibilityCorrected but column has not been averaged");
    2898           0 :     VisBuffer2* vb = getVisBuffer();
    2899           0 :     vis = vb->visCube();
    2900           0 :     return;
    2901             : }
    2902             : 
    2903           0 : void AveragingTvi2::visibilityCorrected(casacore::Cube<casacore::Complex>& vis) const
    2904             : {
    2905           0 :     if(!getVii()->getVisBuffer()->existsColumn (VisBufferComponent2::VisibilityCubeCorrected) ||
    2906           0 :         !averagingOptions_p.contains(AveragingOptions::AverageCorrected))
    2907             :         throw AipsError("Requesting visibilityCorrected but column not "
    2908           0 :             "provided by underlying VI or column has not been averaged");
    2909           0 :     VisBuffer2* vb = getVisBuffer();
    2910           0 :     vis = vb->visCubeCorrected();
    2911           0 :     return;
    2912             : }
    2913             : 
    2914           0 : void AveragingTvi2::visibilityModel(casacore::Cube<casacore::Complex>& vis) const
    2915             : {
    2916           0 :     if(!getVii()->getVisBuffer()->existsColumn (VisBufferComponent2::VisibilityCubeModel) ||
    2917           0 :         !averagingOptions_p.contains(AveragingOptions::AverageModel))
    2918             :         throw AipsError("Requesting visibilityModel but column not "
    2919           0 :             "provided by underlying VI or column has not been averaged");
    2920           0 :     VisBuffer2* vb = getVisBuffer();
    2921           0 :     vis = vb->visCubeModel();
    2922           0 :     return;
    2923             : }
    2924             : 
    2925           0 : void AveragingTvi2::floatData(casacore::Cube<casacore::Float>& fcube) const
    2926             : {
    2927           0 :     if(!getVii()->getVisBuffer()->existsColumn (VisBufferComponent2::VisibilityCubeFloat) ||
    2928           0 :         !averagingOptions_p.contains(AveragingOptions::AverageFloat))
    2929             :         throw AipsError("Requesting floatData but column not "
    2930           0 :             "provided by underlying VI or column has not been averaged");
    2931           0 :     VisBuffer2* vb = getVisBuffer();
    2932           0 :     fcube = vb->visCubeFloat();
    2933           0 :     return;
    2934             : }
    2935             : 
    2936           0 : void AveragingTvi2::flag(casacore::Cube<casacore::Bool>& flags) const
    2937             : {
    2938           0 :     VisBuffer2* vb = getVisBuffer();
    2939           0 :     flags = vb->flagCube();
    2940           0 :     return;
    2941             : }
    2942             : 
    2943           0 : void AveragingTvi2::flagRow(casacore::Vector<casacore::Bool>& rowflags) const
    2944             : {
    2945           0 :     VisBuffer2* vb = getVisBuffer();
    2946           0 :     rowflags = vb->flagRow();
    2947           0 :     return;
    2948             : }
    2949             : 
    2950           0 : void AveragingTvi2::sigma(casacore::Matrix<casacore::Float> & sigmat) const
    2951             : {
    2952           0 :     VisBuffer2* vb = getVisBuffer();
    2953           0 :     sigmat = vb->sigma();
    2954           0 :     return;
    2955             : }
    2956             : 
    2957           0 : void AveragingTvi2::weight (casacore::Matrix<casacore::Float> & wtmat) const
    2958             : {
    2959           0 :     VisBuffer2* vb = getVisBuffer();
    2960           0 :     wtmat = vb->weight();
    2961           0 :     return;
    2962             : }
    2963             : 
    2964           0 : void AveragingTvi2::weightSpectrum (casacore::Cube<casacore::Float> & wtsp) const
    2965             : {
    2966           0 :     VisBuffer2* vb = getVisBuffer();
    2967           0 :     wtsp = vb->weightSpectrum();
    2968           0 :     return;
    2969             : }
    2970             : 
    2971           0 : void AveragingTvi2::sigmaSpectrum (casacore::Cube<casacore::Float> & sigsp) const
    2972             : {
    2973           0 :     VisBuffer2* vb = getVisBuffer();
    2974           0 :     sigsp = vb->sigmaSpectrum();
    2975           0 :     return;
    2976             : }
    2977             : 
    2978           0 : void AveragingTvi2::exposure (casacore::Vector<double> & expo) const
    2979             : {
    2980           0 :     VisBuffer2* vb = getVisBuffer();
    2981           0 :     expo = vb->exposure();
    2982           0 :     return;
    2983             : }
    2984             : 
    2985           0 : void AveragingTvi2::getRowIds (Vector<rownr_t> & rowids) const
    2986             : {
    2987           0 :     VisBuffer2* vb = getVisBuffer();
    2988           0 :     rowids = vb->rowIds();
    2989           0 :     return;
    2990             : }
    2991             : 
    2992          33 : void AveragingTvi2::time (casacore::Vector<double> & t) const
    2993             : {
    2994          33 :     VisBuffer2* vb = getVisBuffer();
    2995          33 :     t = vb->time();
    2996          33 :     return;
    2997             : }
    2998             : 
    2999           0 : void AveragingTvi2::timeInterval (casacore::Vector<double> & ti) const
    3000             : {
    3001           0 :     VisBuffer2* vb = getVisBuffer();
    3002           0 :     ti = vb->timeInterval();
    3003           0 :     return;
    3004             : }
    3005             : 
    3006           0 : void AveragingTvi2::timeCentroid (casacore::Vector<double> & t) const
    3007             : {
    3008           0 :     VisBuffer2* vb = getVisBuffer();
    3009           0 :     t = vb->timeCentroid();
    3010           0 :     return;
    3011             : }
    3012             : 
    3013           0 : void AveragingTvi2::uvw (casacore::Matrix<double> & uvwmat) const
    3014             : {
    3015           0 :     VisBuffer2* vb = getVisBuffer();
    3016           0 :     uvwmat = vb->uvw();
    3017           0 :     return;
    3018             : }
    3019             : 
    3020          34 : void AveragingTvi2::antenna1 (casacore::Vector<casacore::Int> & ant1) const
    3021             : {
    3022          34 :     VisBuffer2* vb = getVisBuffer();
    3023          34 :     ant1 = vb->antenna1();
    3024          34 :     return;
    3025             : }
    3026             : 
    3027          34 : void AveragingTvi2::antenna2 (casacore::Vector<casacore::Int> & ant2) const
    3028             : {
    3029          34 :     VisBuffer2* vb = getVisBuffer();
    3030          34 :     ant2 = vb->antenna2();
    3031          34 :     return;
    3032             : }
    3033             : 
    3034           0 : casacore::Bool AveragingTvi2::weightSpectrumExists () const
    3035             : {
    3036             :   //According to VbAvg::startChunk code comments,
    3037             :   //there is always an output weightSpectrum. See also CAS-11559.
    3038           0 :   return true;
    3039             : }
    3040             : 
    3041           0 : casacore::Bool AveragingTvi2::sigmaSpectrumExists () const
    3042             : {
    3043             :   //According to VbAvg::startChunk code comments,
    3044             :   //there is always an output sigmaSpectrum. See also CAS-11559.
    3045           0 :   return true;
    3046             : }
    3047             : 
    3048             : } // end namespace vi
    3049             : 
    3050             : using namespace casacore;
    3051             : } // end namespace casa

Generated by: LCOV version 1.16