LCOV - code coverage report
Current view: top level - mstransform/MSTransform - MSTransformManager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 3384 4162 81.3 %
Date: 2024-12-11 20:54:31 Functions: 169 206 82.0 %

          Line data    Source code
       1             : //# MSTransformManager.cc: This file contains the implementation of the MSTransformManager class.
       2             : //#
       3             : //#  CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
       4             : //#  Copyright (C) Associated Universities, Inc. Washington DC, USA 2011, All rights reserved.
       5             : //#  Copyright (C) European Southern Observatory, 2011, All rights reserved.
       6             : //#
       7             : //#  This library is free software; you can redistribute it and/or
       8             : //#  modify it under the terms of the GNU Lesser General Public
       9             : //#  License as published by the Free software Foundation; either
      10             : //#  version 2.1 of the License, or (at your option) any later version.
      11             : //#
      12             : //#  This library is distributed in the hope that it will be useful,
      13             : //#  but WITHOUT ANY WARRANTY, without even the implied warranty of
      14             : //#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             : //#  Lesser General Public License for more details.
      16             : //#
      17             : //#  You should have received a copy of the GNU Lesser General Public
      18             : //#  License along with this library; if not, write to the Free Software
      19             : //#  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      20             : //#  MA 02111-1307  USA
      21             : //# $Id: $
      22             : 
      23             : #include <mstransform/MSTransform/MSTransformManager.h>
      24             : 
      25             : #include <casacore/tables/Tables/TableUtil.h>
      26             : 
      27             : #include <mstransform/TVI/PolAverageTVI.h>
      28             : #include <mstransform/TVI/PointingInterpolationTVI.h>
      29             : #include <mstransform/TVI/SDAtmosphereCorrectionTVI.h>
      30             : 
      31             : #include <limits>
      32             : 
      33             : using namespace casacore;
      34             : namespace casa { //# NAMESPACE CASA - BEGIN
      35             : 
      36             : /////////////////////////////////////////////
      37             : ////// MS Transform Framework utilities /////
      38             : /////////////////////////////////////////////
      39             : namespace MSTransformations
      40             : {
      41           0 :         Double wtToSigma(Double weight)
      42             :         {
      43           0 :                 return weight > FLT_MIN ? 1.0 / std::sqrt (weight) : -1.0;
      44             :         }
      45             : 
      46           0 :         Double sigmaToWeight(Double sigma)
      47             :         {
      48           0 :                 return sigma > FLT_MIN ? 1.0 / std::pow (sigma,2) : 0.0;
      49             :         }
      50             : 
      51             :         Unit Hz(String("Hz"));
      52             : }
      53             : 
      54             : /////////////////////////////////////////////
      55             : /// MSTransformManager implementation ///
      56             : /////////////////////////////////////////////
      57             : 
      58             : // -----------------------------------------------------------------------
      59             : // Default constructor
      60             : // -----------------------------------------------------------------------
      61        1890 : MSTransformManager::MSTransformManager()
      62             : {
      63        1890 :         initialize();
      64        1890 :         return;
      65           0 : }
      66             : 
      67             : 
      68             : // -----------------------------------------------------------------------
      69             : // Configuration constructor
      70             : // -----------------------------------------------------------------------
      71           0 : MSTransformManager::MSTransformManager(Record configuration)
      72             : {
      73           0 :         initialize();
      74           0 :         configure(configuration);
      75           0 :         return;
      76           0 : }
      77             : 
      78             : 
      79             : // -----------------------------------------------------------------------
      80             : // Default destructor
      81             : // -----------------------------------------------------------------------
      82        3029 : MSTransformManager::~MSTransformManager()
      83             : {
      84             :         // Close the output MS in case the application layer does not do it
      85        1890 :         close();
      86             : 
      87        1890 :         if (channelSelector_p) delete channelSelector_p;
      88        1890 :         if (visibilityIterator_p and !factory_p) delete visibilityIterator_p;
      89        1890 :         if (dataHandler_p) delete dataHandler_p;
      90        1890 :         if (phaseCenterPar_p) delete phaseCenterPar_p;
      91             : 
      92             :         // Delete the output Ms if we are in buffer mode
      93             :         // This has to be done after deleting the outputMS data handler
      94        1890 :         if (userBufferMode_p)
      95             :         {
      96           0 :                 TableUtil::deleteTable(outMsName_p,true);
      97             :         }
      98             : 
      99        1890 :         return;
     100        3029 : }
     101             : 
     102             : // -----------------------------------------------------------------------
     103             : // Method to initialize members to default values
     104             : // -----------------------------------------------------------------------
     105        1890 : void MSTransformManager::initialize()
     106             : {
     107             :         // MS specification parameters
     108        1890 :         inpMsName_p = String("");
     109        1890 :         outMsName_p = String("");
     110        1890 :         datacolumn_p = String("CORRECTED");
     111        1890 :         makeVirtualModelColReal_p = false; // MODEL_DATA should always be made real via the datacol param.
     112        1890 :         makeVirtualCorrectedColReal_p = true; // TODO: CORRECTED_DATA should be made real on request
     113        1890 :         tileShape_p.resize(1,false);
     114             :         //TileShape of size 1 can have 2 values [0], and [1] ...these are used in to
     115             :         //determine the tileshape by using MSTileLayout. Otherwise it has to be a
     116             :         //vector size 3 e.g [4, 15, 351] => a tile shape of 4 stokes, 15 channels 351
     117             :         //rows.
     118        1890 :         tileShape_p(0) = 0;
     119             : 
     120             :         // Data selection parameters
     121        1890 :         arraySelection_p = String("");
     122        1890 :         fieldSelection_p = String("");
     123        1890 :         scanSelection_p = String("");
     124        1890 :         timeSelection_p = String("");
     125        1890 :         spwSelection_p = String("");
     126        1890 :         baselineSelection_p = String("");
     127        1890 :         uvwSelection_p = String("");
     128        1890 :         polarizationSelection_p = String("");
     129        1890 :         scanIntentSelection_p = String("");
     130        1890 :         observationSelection_p = String("");
     131        1890 :         taqlSelection_p = String("");
     132        1890 :         feedSelection_p = String("");
     133             : 
     134             :         // Input-Output index maps
     135        1890 :         inputOutputObservationIndexMap_p.clear();
     136        1890 :         inputOutputArrayIndexMap_p.clear();
     137        1890 :         inputOutputScanIndexMap_p.clear();
     138        1890 :         inputOutputScanIntentIndexMap_p.clear();
     139        1890 :         inputOutputFieldIndexMap_p.clear();
     140        1890 :         inputOutputSPWIndexMap_p.clear();
     141        1890 :         inputOutputDDIndexMap_p.clear();
     142        1890 :         inputOutputAntennaIndexMap_p.clear();
     143        1890 :         outputInputSPWIndexMap_p.clear();
     144        1890 :         inputOutputChanIndexMap_p.clear();
     145             : 
     146             :         // Frequency transformation parameters
     147        1890 :         smoothCoeff_p.resize(3,false);
     148        1890 :         smoothCoeff_p(0) = 0.25;
     149        1890 :         smoothCoeff_p(1) = 0.5;
     150        1890 :         smoothCoeff_p(2) = 0.25;
     151             : 
     152             :         // Frequency specification parameters
     153        1890 :         mode_p = String("channel");                                   // Options are: channel, frequency, velocity
     154        1890 :         start_p = String("0");
     155        1890 :         width_p = String("1");
     156        1890 :         nChan_p = -1;                                                                   // -1 means use all the input channels
     157        1890 :         velocityType_p = String("radio");                             // When mode is velocity options are: optical, radio
     158             : 
     159             :         // Phase shifting parameters
     160             :         // CAS-12706 To run phase shift via a TVI which has
     161             :         // support for shifting across large offset/angles
     162        1890 :         dx_p = 0;
     163        1890 :         dy_p = 0;
     164        1890 :         tviphaseshift_p = False;
     165        1890 :         tviphaseshiftConfig_p = Record();
     166             : 
     167             :         // Time transformation parameters
     168        1890 :         scalarAverage_p = false;
     169        1890 :         timeAverage_p = false;
     170        1890 :         timeBin_p = 0.0;
     171        1890 :         timespan_p = String("");
     172        1890 :         timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
     173        1890 :         maxuvwdistance_p = 0;
     174             :         // minbaselines_p = 0;
     175             : 
     176             :         // Cal parameters
     177        1890 :         calibrate_p = false;
     178        1890 :         callib_p = "";
     179        1890 :         callibRec_p = Record();
     180             : 
     181             :         // UVContSub parameters
     182        1890 :         uvcontsub_p = False;
     183        1890 :         uvcontsubRec_p = Record();
     184             : 
     185             :         // Spw averaging
     186        1890 :         spwAverage_p = false;
     187             : 
     188             :         // Polarization transformation
     189        1890 :         polAverage_p = false;
     190        1890 :         polAverageConfig_p = Record();
     191             : 
     192             :         // Pointings interpolation
     193        1890 :         pointingsInterpolation_p = false;
     194        1890 :         pointingsInterpolationConfig_p = Record();
     195             : 
     196             :         // Weight Spectrum parameters
     197        1890 :         usewtspectrum_p = false;
     198        1890 :         spectrumTransformation_p = false;
     199        1890 :         propagateWeights_p = false;
     200        1890 :         flushWeightSpectrum_p = false;
     201             : 
     202             :         // MS-related members
     203        1890 :         dataHandler_p = NULL;
     204        1890 :         inputMs_p = NULL;
     205        1890 :         selectedInputMs_p = NULL;
     206        1890 :         outputMs_p = NULL;
     207        1890 :         selectedInputMsCols_p = NULL;
     208        1890 :         outputMsCols_p = NULL;
     209             : 
     210             :         // VI/VB related members
     211        1890 :         sortColumns_p = Block<Int>(7);
     212        1890 :         sortColumns_p[0] = MS::OBSERVATION_ID;
     213        1890 :         sortColumns_p[1] = MS::ARRAY_ID;
     214        1890 :         sortColumns_p[2] = MS::SCAN_NUMBER;
     215        1890 :         sortColumns_p[3] = MS::STATE_ID;
     216        1890 :         sortColumns_p[4] = MS::FIELD_ID;
     217        1890 :         sortColumns_p[5] = MS::DATA_DESC_ID;
     218        1890 :         sortColumns_p[6] = MS::TIME;
     219        1890 :         visibilityIterator_p = NULL;
     220        1890 :         channelSelector_p = NULL;
     221             : 
     222             :         // Output MS structure related members
     223        1890 :         inputFlagCategoryAvailable_p = false;
     224        1890 :         inputWeightSpectrumAvailable_p = false;
     225        1890 :         weightSpectrumFromSigmaFilled_p = false;
     226        1890 :         correctedToData_p = false;
     227        1890 :         bothDataColumnsAreOutput_p = false;
     228        1890 :         doingData_p = false;
     229        1890 :         doingCorrected_p = false;
     230        1890 :         doingModel_p = false;
     231        1890 :         dataColMap_p.clear();
     232        1890 :         mainColumn_p = MS::CORRECTED_DATA;
     233        1890 :         nRowsToAdd_p = 0;
     234             : 
     235             :         // Frequency transformation members
     236        1890 :         chansPerOutputSpw_p = 0;
     237        1890 :         tailOfChansforLastSpw_p = 0;
     238        1890 :         interpolationMethod_p = MSTransformations::linear;
     239        1890 :         baselineMap_p.clear();
     240        1890 :         rowIndex_p.clear();
     241        1890 :         spwChannelMap_p.clear();
     242        1890 :         inputOutputSpwMap_p.clear();
     243        1890 :         inputOutputChanFactorMap_p.clear();
     244        1890 :         freqbinMap_p.clear();
     245        1890 :         numOfInpChanMap_p.clear();
     246        1890 :         numOfSelChanMap_p.clear();
     247        1890 :         numOfOutChanMap_p.clear();
     248        1890 :         numOfCombInputChanMap_p.clear();
     249        1890 :         numOfCombInterChanMap_p.clear();
     250        1890 :         weightFactorMap_p.clear();
     251        1890 :         sigmaFactorMap_p.clear();
     252        1890 :         newWeightFactorMap_p.clear();
     253        1890 :         newSigmaFactorMap_p.clear();
     254             : 
     255             :         // Reference frame transformation members
     256        1890 :         fftShiftEnabled_p = false;
     257        1890 :         fftShift_p = 0;
     258             : 
     259             :         // Weight Spectrum members
     260        1890 :         inputWeightSpectrumAvailable_p = false;
     261        1890 :         combinationOfSPWsWithDifferentExposure_p = false;
     262             : 
     263             :         // Transformations - related function pointers
     264        1890 :         transformCubeOfDataComplex_p = NULL;
     265        1890 :         transformCubeOfDataFloat_p = NULL;
     266        1890 :         fillWeightsPlane_p = NULL;
     267        1890 :         setWeightsPlaneByReference_p = NULL;
     268        1890 :         setWeightStripeByReference_p = NULL;
     269        1890 :         transformStripeOfDataComplex_p = NULL;
     270        1890 :         transformStripeOfDataFloat_p = NULL;
     271        1890 :         averageKernelComplex_p = NULL;
     272        1890 :         averageKernelFloat_p = NULL;
     273        1890 :         smoothKernelComplex_p = NULL;
     274        1890 :         smoothKernelFloat_p = NULL;
     275             : 
     276             :         // I/O related function pointers
     277        1890 :         writeOutputPlanesComplex_p = NULL;
     278        1890 :         writeOutputPlanesFloat_p = NULL;
     279        1890 :         writeOutputFlagsPlane_p = NULL;
     280        1890 :         writeOutputFlagsPlaneSlices_p = NULL;
     281        1890 :         writeOutputFlagsPlaneReshapedSlices_p = NULL;
     282             : 
     283             :         // Buffer handling members
     284        1890 :         bufferMode_p = false;
     285        1890 :         userBufferMode_p = false;
     286        1890 :         reindex_p = true;
     287        1890 :         factory_p = False;
     288        1890 :         interactive_p = false;
     289        1890 :         spectrumReshape_p = false;
     290        1890 :         cubeTransformation_p = false;
     291        1890 :         dataColumnAvailable_p = false;
     292        1890 :         correctedDataColumnAvailable_p = false;
     293        1890 :         modelDataColumnAvailable_p = false;
     294        1890 :         floatDataColumnAvailable_p = false;
     295        1890 :         flagCube_p = NULL;
     296        1890 :         visCube_p = NULL;
     297        1890 :         visCubeCorrected_p = NULL;
     298        1890 :         visCubeModel_p = NULL;
     299        1890 :         visCubeFloat_p = NULL;
     300        1890 :         weightSpectrum_p = NULL;
     301        1890 :         sigmaSpectrum_p = NULL;
     302        1890 :         weight_p = NULL;
     303        1890 :         sigma_p = NULL;
     304        1890 :         relativeRow_p = 0;
     305             : 
     306             :         // single dish specific
     307        1890 :         smoothFourier_p = false;
     308             : 
     309        1890 :         return;
     310             : }
     311             : 
     312             : // -----------------------------------------------------------------------
     313             : // Method to parse the configuration parameters
     314             : // -----------------------------------------------------------------------
     315        1890 : void MSTransformManager::configure(Record &configuration)
     316             : {
     317        1890 :         parseMsSpecParams(configuration);
     318        1890 :         parseDataSelParams(configuration);
     319        1890 :         parseFreqTransParams(configuration);
     320        1890 :         parseChanAvgParams(configuration);
     321        1890 :         parseRefFrameTransParams(configuration);
     322        1890 :         parseTimeAvgParams(configuration);
     323        1890 :         parseCalParams(configuration);
     324        1890 :         parseUVContSubParams(configuration);
     325        1890 :         setSpwAvg(configuration);
     326        1890 :         parsePolAvgParams(configuration);
     327        1890 :         parsePointingsInterpolationParams(configuration);
     328        1890 :         parsePhaseShiftParams(configuration);
     329        1890 :         parseAtmCorrectionParams(configuration);
     330             : 
     331        1890 :         return;
     332             : }
     333             : 
     334             : // -----------------------------------------------------------------------
     335             : // Method to parse input/output MS specification
     336             : // -----------------------------------------------------------------------
     337        1890 : void MSTransformManager::parseMsSpecParams(Record &configuration)
     338             : {
     339        1890 :         int exists = -1;
     340             : 
     341        1890 :         exists = -1;
     342        1890 :         exists = configuration.fieldNumber ("inputms");
     343        1890 :         if (exists >= 0)
     344             :         {
     345        1890 :                 configuration.get (exists, inpMsName_p);
     346        3780 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     347        3780 :                                 << "Input file name is " << inpMsName_p << LogIO::POST;
     348             :         }
     349             : 
     350        1890 :         exists = -1;
     351        1890 :         exists = configuration.fieldNumber ("buffermode");
     352        1890 :         if (exists >= 0)
     353             :         {
     354           0 :                 configuration.get (exists, userBufferMode_p);
     355           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     356           0 :                                 << "Buffer mode is on " << LogIO::POST;
     357             : 
     358           0 :                 bufferMode_p = userBufferMode_p;
     359             :         }
     360             : 
     361             :         // In buffer mode this is needed for the time average VI/VB which needs to be informed beforehand
     362        1890 :         exists = -1;
     363        1890 :         exists = configuration.fieldNumber ("datacolumn");
     364        1890 :         if (exists >= 0)
     365             :         {
     366        1890 :                 configuration.get (exists, datacolumn_p);
     367        3780 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     368        3780 :                                 << "Data column is " << datacolumn_p << LogIO::POST;
     369             :         }
     370             : 
     371             :         // In buffer mode outputms is just a random generated filename used as a placeholder for the re-indexed subtables
     372        1890 :         exists = -1;
     373        1890 :         exists = configuration.fieldNumber ("outputms");
     374        1890 :         if (exists >= 0)
     375             :         {
     376        1890 :                 configuration.get (exists, outMsName_p);
     377             : 
     378             :                 // Inform of filename only in normal mode, as in buffer mode is random generated
     379        1890 :                 if (not bufferMode_p)
     380             :                 {
     381        3780 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     382        3780 :                                                 << "Output file name is " << outMsName_p << LogIO::POST;
     383             :                 }
     384             :         }
     385             : 
     386        1890 :         exists = -1;
     387        1890 :         exists = configuration.fieldNumber ("reindex");
     388        1890 :         if (exists >= 0)
     389             :         {
     390        1329 :                 configuration.get (exists, reindex_p);
     391             : 
     392        1329 :                 if (reindex_p)
     393             :                 {
     394        2454 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     395        2454 :                                         << "Re-index is enabled " << LogIO::POST;
     396             :                 }
     397             :                 else
     398             :                 {
     399         204 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     400         204 :                                         << "Re-index is disabled " << LogIO::POST;
     401             :                 }
     402             :         }
     403             : 
     404        1890 :         exists = -1;
     405        1890 :         exists = configuration.fieldNumber ("factory");
     406        1890 :         if (exists >= 0)
     407             :         {
     408           0 :                 configuration.get (exists, factory_p);
     409             : 
     410           0 :                 if (factory_p)
     411             :                 {
     412           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     413           0 :                                         << "Factory mode enabled " << LogIO::POST;
     414             :                 }
     415             :         }
     416             : 
     417        1890 :         if (userBufferMode_p)
     418             :         {
     419           0 :                 interactive_p = true;
     420             : 
     421           0 :                 exists = -1;
     422           0 :                 exists = configuration.fieldNumber ("interactive");
     423           0 :                 if (exists >= 0)
     424             :                 {
     425           0 :                         configuration.get (exists, interactive_p);
     426             : 
     427           0 :                         if (interactive_p)
     428             :                         {
     429           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     430           0 :                                                 << "Interactive mode is enabled - flagging will be applied on input MS " << LogIO::POST;
     431             :                         }
     432             :                         else
     433             :                         {
     434           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     435           0 :                                                 << "Interactive mode is disabled - flagging will not be applied on input MS " << LogIO::POST;
     436             :                         }
     437             :                 }
     438             :         }
     439             :         else
     440             :         {
     441        1890 :                 interactive_p = false;
     442             : 
     443        1890 :                 exists = -1;
     444        1890 :                 exists = configuration.fieldNumber ("realmodelcol");
     445        1890 :                 if (exists >= 0)
     446             :                 {
     447          84 :                         configuration.get (exists, makeVirtualModelColReal_p);
     448          84 :                         if (makeVirtualModelColReal_p)
     449             :                         {
     450           2 :                                 if (datacolumn_p.contains("ALL") or datacolumn_p.contains("MODEL"))
     451             :                                 {
     452           4 :                                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     453             :                                                         << "MODEL column will be made real in the output MS "
     454           4 :                                                         << LogIO::POST;
     455             :                                 }
     456             :                                 else
     457             :                                 {
     458           0 :                                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
     459             :                                                          << "Requested to make virtual MODEL_DATA column real but "
     460             :                                                          << "MODEL_DATA column not selected in datacolumn parameter "
     461             :                                                          << "Options that include MODEL_DATA are 'MODEL' and 'ALL'"
     462           0 :                                                          << LogIO::POST;
     463           0 :                                         makeVirtualModelColReal_p = false;
     464             :                                 }
     465             :                         }
     466             :                 }
     467             : 
     468        1890 :                 exists = -1;
     469        1890 :                 exists = configuration.fieldNumber ("usewtspectrum");
     470        1890 :                 if (exists >= 0)
     471             :                 {
     472         521 :                         configuration.get (exists, usewtspectrum_p);
     473         521 :                         if (usewtspectrum_p)
     474             :                         {
     475         234 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     476         234 :                                                 << "WEIGHT_SPECTRUM will be written in output MS " << LogIO::POST;
     477             :                         }
     478             :                 }
     479             : 
     480        1890 :                 exists = -1;
     481        1890 :                 exists = configuration.fieldNumber ("tileshape");
     482        1890 :                 if (exists >= 0)
     483             :                 {
     484         521 :                         if ( configuration.type(exists) == casacore::TpInt )
     485             :                         {
     486             :                                 Int mode;
     487           0 :                                 configuration.get (exists, mode);
     488           0 :                                 tileShape_p = Vector<Int>(1,mode);
     489             :                         }
     490         521 :                         else if ( configuration.type(exists) == casacore::TpArrayInt)
     491             :                         {
     492         521 :                                 configuration.get (exists, tileShape_p);
     493             :                         }
     494             : 
     495        1042 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     496        1042 :                                         << "Tile shape is " << tileShape_p << LogIO::POST;
     497             :                 }
     498             :         }
     499             : 
     500        1890 :         return;
     501             : }
     502             : 
     503             : // -----------------------------------------------------------------------
     504             : // Method to parse the data selection parameters
     505             : // -----------------------------------------------------------------------
     506        1890 : void MSTransformManager::parseDataSelParams(Record &configuration)
     507             : {
     508        1890 :         int exists = -1;
     509             : 
     510        1890 :         exists = -1;
     511        1890 :         exists = configuration.fieldNumber ("array");
     512        1890 :         if (exists >= 0)
     513             :         {
     514          59 :                 configuration.get (exists, arraySelection_p);
     515         118 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     516         118 :                                 << "array selection is " << arraySelection_p << LogIO::POST;
     517             :         }
     518             : 
     519        1890 :         exists = -1;
     520        1890 :         exists = configuration.fieldNumber ("field");
     521        1890 :         if (exists >= 0)
     522             :         {
     523         126 :                 configuration.get (exists, fieldSelection_p);
     524         252 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     525         252 :                                 << "field selection is " << fieldSelection_p << LogIO::POST;
     526             :         }
     527             : 
     528        1890 :         exists = -1;
     529        1890 :         exists = configuration.fieldNumber ("scan");
     530        1890 :         if (exists >= 0)
     531             :         {
     532         184 :                 configuration.get (exists, scanSelection_p);
     533         368 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     534         368 :                                 << "scan selection is " << scanSelection_p << LogIO::POST;
     535             :         }
     536             : 
     537        1890 :         exists = -1;
     538        1890 :         exists = configuration.fieldNumber ("timerange");
     539        1890 :         if (exists >= 0)
     540             :         {
     541          39 :                 configuration.get (exists, timeSelection_p);
     542          78 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     543          78 :                                 << "timerange selection is " << timeSelection_p << LogIO::POST;
     544             :         }
     545             : 
     546        1890 :         exists = -1;
     547        1890 :         exists = configuration.fieldNumber ("spw");
     548        1890 :         if (exists >= 0)
     549             :         {
     550        1186 :                 configuration.get (exists, spwSelection_p);
     551        2372 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     552        2372 :                                 << "spw selection is " << spwSelection_p << LogIO::POST;
     553             :         }
     554             : 
     555        1890 :         exists = -1;
     556        1890 :         exists = configuration.fieldNumber ("antenna");
     557        1890 :         if (exists >= 0)
     558             :         {
     559         787 :                 configuration.get (exists, baselineSelection_p);
     560        1574 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     561        1574 :                                 << "antenna selection is " << baselineSelection_p << LogIO::POST;
     562             :         }
     563             : 
     564        1890 :         exists = -1;
     565        1890 :         exists = configuration.fieldNumber ("uvrange");
     566        1890 :         if (exists >= 0)
     567             :         {
     568           0 :                 configuration.get (exists, uvwSelection_p);
     569           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     570           0 :                                 << "uvrange selection is " << uvwSelection_p << LogIO::POST;
     571             :         }
     572             : 
     573        1890 :         exists = -1;
     574        1890 :         exists = configuration.fieldNumber ("correlation");
     575        1890 :         if (exists >= 0)
     576             :         {
     577          77 :                 configuration.get (exists, polarizationSelection_p);
     578         154 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     579         154 :                                 << "correlation selection is " << polarizationSelection_p << LogIO::POST;
     580             :         }
     581             : 
     582        1890 :         exists = -1;
     583        1890 :         exists = configuration.fieldNumber ("observation");
     584        1890 :         if (exists >= 0)
     585             :         {
     586          67 :                 configuration.get (exists, observationSelection_p);
     587         134 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     588         134 :                                 <<"observation selection is " << observationSelection_p << LogIO::POST;
     589             :         }
     590             : 
     591        1890 :         exists = -1;
     592        1890 :         exists = configuration.fieldNumber ("intent");
     593        1890 :         if (exists >= 0)
     594             :         {
     595         165 :                 configuration.get (exists, scanIntentSelection_p);
     596         330 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     597         330 :                                 << "scan intent selection is " << scanIntentSelection_p << LogIO::POST;
     598             :         }
     599             : 
     600        1890 :         exists = -1;
     601        1890 :         exists = configuration.fieldNumber ("taql");
     602        1890 :         if (exists >= 0)
     603             :         {
     604         353 :                 configuration.get (exists, taqlSelection_p);
     605         706 :                 logger_p << LogIO::NORMAL2 << LogOrigin("MSTransformManager", __FUNCTION__)
     606         706 :                                 << "TaQL selection is " << taqlSelection_p << LogIO::POST;
     607             :         }
     608             : 
     609        1890 :         exists = -1;
     610        1890 :         exists = configuration.fieldNumber ("feed");
     611        1890 :         if (exists >= 0)
     612             :         {
     613           0 :                 configuration.get (exists, feedSelection_p);
     614           0 :                 logger_p << LogIO::NORMAL2 << LogOrigin("MSTransformManager", __FUNCTION__)
     615           0 :                                 << "feed selection is " << feedSelection_p << LogIO::POST;
     616             :         }
     617             : 
     618        1890 :         return;
     619             : }
     620             : 
     621             : // -----------------------------------------------------------------------
     622             : // Method to parse the channel average parameters
     623             : // -----------------------------------------------------------------------
     624        1890 : void MSTransformManager::parseChanAvgParams(Record &configuration)
     625             : {
     626        1890 :     int exists = -1;
     627             : 
     628        1890 :     exists = -1;
     629        1890 :     exists = configuration.fieldNumber ("chanaverage");
     630        1890 :     if (exists >= 0)
     631             :     {
     632         140 :         configuration.get (exists, channelAverage_p);
     633         140 :         if (channelAverage_p)
     634             :         {
     635         280 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     636         280 :                                                 << "Channel average is activated" << LogIO::POST;
     637             :         }
     638             :         else
     639             :         {
     640           0 :             return;
     641             :         }
     642             :     }
     643             :     else
     644             :     {
     645        1750 :         return;
     646             :     }
     647             : 
     648         140 :     exists = -1;
     649         140 :     exists = configuration.fieldNumber ("chanbin");
     650         140 :     if (exists >= 0)
     651             :     {
     652         140 :         if ( configuration.type(exists) == casacore::TpInt )
     653             :         {
     654             :             Int freqbin;
     655         126 :             configuration.get (exists, freqbin);
     656             : 
     657         126 :             if (freqbin < 2)
     658             :             {
     659           0 :                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
     660           0 :                                                         << "Channel bin is " << freqbin << " disabling channel average" << LogIO::POST;
     661           0 :                 channelAverage_p = False;
     662             :             }
     663             :             else
     664             :             {
     665         126 :                 freqbin_p = Vector<Int>(1,freqbin);
     666             : 
     667             :             }
     668             :         }
     669          14 :         else if ( configuration.type(exists) == casacore::TpArrayInt)
     670             :         {
     671          14 :             if(combinespws_p)
     672           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
     673             :                 << "If SPW combination is active, "
     674           0 :                 "chabin cannot be an array" << LogIO::EXCEPTION;
     675             : 
     676          14 :             configuration.get (exists, freqbin_p);
     677             :         }
     678             :         else
     679             :         {
     680           0 :             logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
     681           0 :                                                 << "Wrong format for chanbin parameter (only Int and arrayInt are supported) " << LogIO::POST;
     682             :         }
     683             : 
     684         280 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     685         280 :                                         << "Channel bin is " << freqbin_p << LogIO::POST;
     686             :     }
     687             :     else
     688             :     {
     689           0 :         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
     690           0 :                                         << "Channel average is activated but no chanbin parameter provided " << LogIO::POST;
     691           0 :         channelAverage_p = false;
     692           0 :         return;
     693             :     }
     694             : 
     695             :     // jagonzal: This is now determined by usewtspectrum param and the presence of input WeightSpectrum
     696             :     /*
     697             :         exists = configuration.fieldNumber ("useweights");
     698             :         if (exists >= 0)
     699             :         {
     700             :                 configuration.get (exists, useweights_p);
     701             : 
     702             :                 useweights_p.downcase();
     703             : 
     704             :                 if (useweights_p == "flags")
     705             :                 {
     706             :                         weightmode_p = MSTransformations::flags;
     707             :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     708             :                                         << "Using FLAGS as weights for channel average" << LogIO::POST;
     709             :                 }
     710             :                 else if (useweights_p == "spectrum")
     711             :                 {
     712             :                         weightmode_p = MSTransformations::spectrum;
     713             :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     714             :                                         << "Using WEIGHT_SPECTRUM as weights for channel average" << LogIO::POST;
     715             :                 }
     716             :                 else
     717             :                 {
     718             :                         weightmode_p = MSTransformations::flags;
     719             :                         useweights_p = String("flags");
     720             :                 }
     721             :         }
     722             :      */
     723             : 
     724         140 :     return;
     725             : }
     726             : 
     727             : // -----------------------------------------------------------------------
     728             : // Method to parse the frequency transformation parameters
     729             : // -----------------------------------------------------------------------
     730        1890 : void MSTransformManager::parseFreqTransParams(Record &configuration)
     731             : {
     732        1890 :         int exists = -1;
     733             : 
     734        1890 :         exists = -1;
     735        1890 :         exists = configuration.fieldNumber ("combinespws");
     736        1890 :         if (exists >= 0)
     737             :         {
     738         119 :                 configuration.get (exists, combinespws_p);
     739             : 
     740         119 :                 if (combinespws_p)
     741             :                 {
     742         238 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     743         238 :                                         << "Combine Spectral Windows is activated" << LogIO::POST;
     744             :                 }
     745             :         }
     746             : 
     747        1890 :         exists = -1;
     748        1890 :         exists = configuration.fieldNumber ("ddistart");
     749        1890 :         if (exists >= 0)
     750             :         {
     751         834 :                 configuration.get (exists, ddiStart_p);
     752         834 :                 if (ddiStart_p > 0)
     753             :                 {
     754         144 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     755         144 :                                         << "DDI start is " << ddiStart_p << LogIO::POST;
     756             :                 }
     757             :                 else
     758             :                 {
     759         762 :                         ddiStart_p = 0;
     760             :                 }
     761             : 
     762             :         }
     763             : 
     764        1890 :         exists = -1;
     765        1890 :         exists = configuration.fieldNumber ("hanning");
     766        1890 :         if (exists >= 0)
     767             :         {
     768          83 :                 configuration.get (exists, hanningSmooth_p);
     769             : 
     770          83 :                 if (hanningSmooth_p)
     771             :                 {
     772          23 :                         smoothBin_p = 3;
     773          23 :                         smoothCoeff_p.resize(3,false);
     774          23 :                         smoothCoeff_p(0) = 0.25;
     775          23 :                         smoothCoeff_p(1) = 0.5;
     776          23 :                         smoothCoeff_p(2) = 0.25;
     777          23 :                         weightmode_p = MSTransformations::plainSmooth;
     778          46 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     779          46 :                                         << "Hanning Smooth is activated" << LogIO::POST;
     780             :                 }
     781             :         }
     782             : 
     783        1890 :         exists = -1;
     784        1890 :         exists = configuration.fieldNumber("smoothFourier");
     785        1890 :         if (exists >= 0)
     786             :         {
     787         751 :             configuration.get(exists, smoothFourier_p);
     788         751 :             if (smoothFourier_p) {
     789         320 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     790         320 :                         << "Fourier smoothing (single dish specific) is activated" << LogIO::POST;
     791             :             }
     792             :         }
     793             : 
     794        1890 :         return;
     795             : }
     796             : 
     797             : // -----------------------------------------------------------------------
     798             : // Method to parse the reference frame transformation parameters
     799             : // -----------------------------------------------------------------------
     800        1890 : void MSTransformManager::parseRefFrameTransParams(Record &configuration)
     801             : {
     802        1890 :         int exists = -1;
     803             : 
     804        1890 :         exists = -1;
     805        1890 :         exists = configuration.fieldNumber ("regridms");
     806        1890 :         if (exists >= 0)
     807             :         {
     808         112 :                 configuration.get (exists, regridding_p);
     809             : 
     810         112 :                 if (regridding_p)
     811             :                 {
     812         224 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     813         224 :                                         << "Regrid MS is activated"<< LogIO::POST;
     814             :                 }
     815             :                 else
     816             :                 {
     817           0 :                         return;
     818             :                 }
     819             :         }
     820             : 
     821        1890 :         exists = -1;
     822        1890 :         exists = configuration.fieldNumber ("phasecenter");
     823        1890 :         if (exists >= 0)
     824             :         {
     825             :                 //If phase center is a simple numeric value then it is taken
     826             :                 // as a FIELD_ID otherwise it is converted to a MDirection
     827          29 :         if( configuration.type(exists) == TpInt )
     828             :         {
     829           4 :                 int fieldIdForPhaseCenter = -1;
     830           4 :                 configuration.get (exists, fieldIdForPhaseCenter);
     831           8 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     832           8 :                                 << "Field Id for phase center is " << fieldIdForPhaseCenter << LogIO::POST;
     833           4 :                 if (phaseCenterPar_p) delete phaseCenterPar_p;
     834           4 :                 phaseCenterPar_p = new casac::variant((long)fieldIdForPhaseCenter);
     835             :         }
     836             :         else
     837             :         {
     838          25 :                 String phaseCenter("");
     839          25 :                 configuration.get (exists, phaseCenter);
     840          50 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     841          50 :                                 << "Phase center is " << phaseCenter << LogIO::POST;
     842          25 :                 if (phaseCenterPar_p) delete phaseCenterPar_p;
     843          25 :                 phaseCenterPar_p = new casac::variant(phaseCenter);
     844          25 :         }
     845             :         }
     846             : 
     847        1890 :         exists = -1;
     848        1890 :         exists = configuration.fieldNumber ("restfreq");
     849        1890 :         if (exists >= 0)
     850             :         {
     851          21 :                 configuration.get (exists, restFrequency_p);
     852          21 :                 if (!restFrequency_p.empty())
     853             :                 {
     854          42 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     855          42 :                                         << "Rest frequency is " << restFrequency_p << LogIO::POST;
     856             :                 }
     857             :         }
     858             : 
     859        1890 :         exists = -1;
     860        1890 :         exists = configuration.fieldNumber ("outframe");
     861        1890 :         if (exists >= 0)
     862             :         {
     863          43 :                 configuration.get (exists, outputReferenceFramePar_p);
     864          86 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     865          86 :                                 << "Output reference frame is " << outputReferenceFramePar_p << LogIO::POST;
     866             :         }
     867             : 
     868        1890 :         exists = -1;
     869        1890 :         exists = configuration.fieldNumber ("interpolation");
     870        1890 :         if (exists >= 0)
     871             :         {
     872         112 :                 configuration.get (exists, interpolationMethodPar_p);
     873             : 
     874         112 :                 if (interpolationMethodPar_p.contains("nearest"))
     875             :                 {
     876           1 :                         interpolationMethod_p = MSTransformations::nearestNeighbour;
     877             :                 }
     878         111 :                 else if (interpolationMethodPar_p.contains("linear"))
     879             :                 {
     880          98 :                         interpolationMethod_p = MSTransformations::linear;
     881             :                 }
     882          13 :                 else if (interpolationMethodPar_p.contains("cubic"))
     883             :                 {
     884           1 :                         interpolationMethod_p = MSTransformations::cubic;
     885             :                 }
     886          12 :                 else if (interpolationMethodPar_p.contains("spline"))
     887             :                 {
     888           1 :                         interpolationMethod_p = MSTransformations::spline;
     889             :                 }
     890          11 :                 else if (interpolationMethodPar_p.contains("fftshift"))
     891             :                 {
     892          11 :                         fftShiftEnabled_p = true;
     893          11 :                         interpolationMethod_p = MSTransformations::linear;
     894             :                 }
     895             :                 else
     896             :                 {
     897           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
     898           0 :                                         << "Interpolation method " << interpolationMethodPar_p  << " not available " << LogIO::POST;
     899             :                 }
     900             : 
     901         224 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     902         224 :                                 << "Interpolation method is " << interpolationMethodPar_p  << LogIO::POST;
     903             :         }
     904             :         else
     905             :         {
     906        1778 :                 interpolationMethod_p = MSTransformations::linear;
     907             :         }
     908             : 
     909        1890 :         exists = -1;
     910        1890 :         exists = configuration.fieldNumber ("nspw");
     911        1890 :         if (exists >= 0)
     912             :         {
     913         112 :                 configuration.get (exists, nspws_p);
     914             : 
     915         112 :                 if (nspws_p > 1)
     916             :                 {
     917          26 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     918          26 :                                         << "Number of output SPWs is " << nspws_p << LogIO::POST;
     919          13 :                         combinespws_p = true;
     920             :                 }
     921             :                 else
     922             :                 {
     923          99 :                         nspws_p = 1;
     924             :                 }
     925             :         }
     926             : 
     927        1890 :         parseFreqSpecParams(configuration);
     928             : 
     929        1890 :         exists = configuration.fieldNumber ("preaverage");
     930        1890 :         if (exists >= 0) {
     931          50 :           configuration.get (exists, enableChanPreAverage_p);
     932             : 
     933          50 :           if (combinespws_p) {
     934          42 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     935          42 :                      << "Enabling channel pre-averaging" << LogIO::POST;
     936             :           }
     937             :         }
     938             : 
     939        1890 :         return;
     940             : }
     941             : 
     942             : // -----------------------------------------------------------------------
     943             : // Method to parse the frequency selection specification
     944             : // -----------------------------------------------------------------------
     945        1890 : void MSTransformManager::parseFreqSpecParams(Record &configuration)
     946             : {
     947        1890 :         int exists = -1;
     948             : 
     949        1890 :         exists = -1;
     950        1890 :         exists = configuration.fieldNumber ("mode");
     951        1890 :         if (exists >= 0)
     952             :         {
     953         112 :                 configuration.get (exists, mode_p);
     954         224 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     955         224 :                                 << "Mode is " << mode_p<< LogIO::POST;
     956             : 
     957         112 :                 if ((mode_p == "frequency") or (mode_p == "velocity"))
     958             :                 {
     959          48 :                         start_p = String("");
     960          48 :                         width_p = String("");
     961             :                 }
     962             :         }
     963             : 
     964        1890 :         exists = -1;
     965        1890 :         exists = configuration.fieldNumber ("nchan");
     966        1890 :         if (exists >= 0)
     967             :         {
     968         112 :                 configuration.get (exists, nChan_p);
     969         112 :                 if (nspws_p > 1)
     970             :                 {
     971          26 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     972          26 :                                         << "Number of output channels per output spw is " << nChan_p << LogIO::POST;
     973          13 :                         nChan_p *=  nspws_p;
     974             :                 }
     975             :                 else
     976             :                 {
     977         198 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     978         198 :                                         << "Number of output channels is " << nChan_p<< LogIO::POST;
     979             :                 }
     980             :         }
     981             : 
     982        1890 :         exists = -1;
     983        1890 :         exists = configuration.fieldNumber ("start");
     984        1890 :         if (exists >= 0)
     985             :         {
     986         100 :                 configuration.get (exists, start_p);
     987         200 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     988         200 :                                 << "Start is " << start_p << LogIO::POST;
     989             :         }
     990             : 
     991        1890 :         exists = -1;
     992        1890 :         exists = configuration.fieldNumber ("width");
     993        1890 :         if (exists >= 0)
     994             :         {
     995         106 :                 configuration.get (exists, width_p);
     996         212 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     997         212 :                                 << "Width is " << width_p << LogIO::POST;
     998             :         }
     999             : 
    1000        1890 :         exists = -1;
    1001        1890 :         exists = configuration.fieldNumber ("veltype");
    1002        1890 :         if ((exists >= 0) and (mode_p == "velocity"))
    1003             :         {
    1004          21 :                 configuration.get (exists, velocityType_p);
    1005          42 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1006          42 :                                 << "Velocity type is " << velocityType_p << LogIO::POST;
    1007             :         }
    1008             : 
    1009        1890 :         return;
    1010             : }
    1011             : 
    1012             : // -----------------------------------------------------------------------
    1013             : // Method to parse the phase shifting specification
    1014             : // -----------------------------------------------------------------------
    1015             : // CAS-12706 To run phase shift via a TVI which has
    1016             : // support for shifting across large offset/angles
    1017             : // -----------------------------------------------------------------------
    1018        1890 : void MSTransformManager::parsePhaseShiftParams(Record &configuration)
    1019             : {
    1020        1890 :         int exists = -1;
    1021             : 
    1022        1890 :         exists = -1;
    1023        1890 :         exists = configuration.fieldNumber("tviphaseshift");
    1024        1890 :         if (exists >= 0)
    1025             :         {
    1026          82 :                 configuration.get (exists, tviphaseshift_p);
    1027             : 
    1028          82 :                 if (tviphaseshift_p)
    1029             :                 {
    1030             :                         // Extract the callib Record
    1031          82 :                         exists = -1;
    1032          82 :                         exists = configuration.fieldNumber("tviphaseshiftlib");
    1033          82 :                         if (configuration.type(exists) == TpRecord)
    1034             :                         {
    1035          82 :                                 tviphaseshiftConfig_p = configuration.subRecord(exists);
    1036             :                         }
    1037             : 
    1038         164 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    1039             :                                                 << "Phase shifting via TVI with support for large offset/angle "
    1040         164 :                                                 << LogIO::POST;
    1041             :                 }
    1042             :         }
    1043             : 
    1044        1890 :         return;
    1045             : }
    1046             : 
    1047             : // -----------------------------------------------------------------------
    1048             : // Method to parse the time average specification
    1049             : // -----------------------------------------------------------------------
    1050        1890 : void MSTransformManager::parseTimeAvgParams(Record &configuration)
    1051             : {
    1052        1890 :         int exists = -1;
    1053             : 
    1054        1890 :         exists = -1;
    1055        1890 :         exists = configuration.fieldNumber ("timeaverage");
    1056        1890 :         if (exists >= 0)
    1057             :         {
    1058         207 :                 configuration.get (exists, timeAverage_p);
    1059             : 
    1060         207 :                 if (timeAverage_p)
    1061             :                 {
    1062         414 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1063         414 :                                         << "Time average is activated" << LogIO::POST;
    1064             :                 }
    1065             :         }
    1066             : 
    1067        1890 :     exists = -1;
    1068        1890 :         exists = configuration.fieldNumber ("scalaraverage");
    1069        1890 :         if (exists >= 0)
    1070             :         {
    1071           0 :                 configuration.get (exists, scalarAverage_p);
    1072             : 
    1073           0 :                 if (scalarAverage_p)
    1074             :                 {
    1075           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1076           0 :                                         << "Scalar average is activated" << LogIO::POST;
    1077             :                 }
    1078             :         }
    1079             : 
    1080        1890 :         if (timeAverage_p || scalarAverage_p)
    1081             :         {
    1082         207 :                 exists = -1;
    1083         207 :                 exists = configuration.fieldNumber ("timebin");
    1084         207 :                 if (exists >= 0)
    1085             :                 {
    1086         207 :                         String timebin;
    1087         207 :                         configuration.get (exists, timebin);
    1088         207 :                         timeBin_p=casaQuantity(timebin).get("s").getValue();
    1089             : 
    1090         414 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1091         414 :                                         << "Time bin is " << timeBin_p << " seconds" << LogIO::POST;
    1092         207 :                 }
    1093             :                 else
    1094             :                 {
    1095           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1096           0 :                                         << "Time or scalar average is activated but no timebin parameter provided " << LogIO::POST;
    1097           0 :                         timeAverage_p = false;
    1098           0 :                         scalarAverage_p = false;
    1099           0 :                         return;
    1100             :                 }
    1101             : 
    1102         207 :                 exists = -1;
    1103         207 :                 exists = configuration.fieldNumber ("timespan");
    1104         207 :                 if (exists >= 0)
    1105             :                 {
    1106         205 :                         configuration.get (exists, timespan_p);
    1107             : 
    1108         205 :                         if (!timespan_p.contains("scan") and !timespan_p.contains("state") and !timespan_p.contains("field"))
    1109             :                         {
    1110         137 :                                 timespan_p = String("");
    1111             :                         }
    1112             :                         else
    1113             :                         {
    1114         136 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1115         136 :                                                 << "Time span is " << timespan_p << LogIO::POST;
    1116             :                         }
    1117             :                 }
    1118             : 
    1119             :                 // CAS-4850 (jagonzal): For ALMA each bdf is limited to 30s, so we need to combine across state (i.e. su-scan)
    1120         207 :                 if (timeAverage_p && (timeBin_p > 30.0) and !timespan_p.contains("state"))
    1121             :                 {
    1122          58 :                         MeasurementSet tmpMs(inpMsName_p,Table::Old);
    1123          58 :                         MSObservation observationTable = tmpMs.observation();
    1124          58 :                         MSObservationColumns observationCols(observationTable);
    1125          58 :                         String telescopeName = observationCols.telescopeName()(0);
    1126             : 
    1127          58 :                         if (telescopeName.contains("ALMA"))
    1128             :                         {
    1129          10 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1130             :                                                 << "Operating with ALMA data, automatically adding state to timespan "<< endl
    1131          10 :                                                 << "In order to remove sub-scan boundaries which limit time average to 30s "<< LogIO::POST;
    1132           5 :                                 timespan_p += String(",state");
    1133             :                         }
    1134          58 :                 }
    1135             : 
    1136         207 :                 exists = -1;
    1137         207 :                 exists = configuration.fieldNumber ("maxuvwdistance");
    1138         207 :                 if (exists >= 0)
    1139             :                 {
    1140         197 :                         configuration.get (exists, maxuvwdistance_p);
    1141             : 
    1142         197 :                         if (maxuvwdistance_p > 0)
    1143             :                         {
    1144           2 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1145             :                                                 << "Maximum UV distance for baseline-dependent time average is: "
    1146           2 :                                                 << maxuvwdistance_p << " meters" << LogIO::POST;
    1147             :                         }
    1148             :                 }
    1149             : 
    1150             :                 /*
    1151             :                 exists = configuration.fieldNumber ("minbaselines");
    1152             :                 if (exists >= 0)
    1153             :                 {
    1154             :                         configuration.get (exists, minbaselines_p);
    1155             : 
    1156             :                         if (minbaselines_p > 0)
    1157             :                         {
    1158             :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1159             :                                                 << "Minimum number of baselines for time average: " << minbaselines_p << LogIO::POST;
    1160             :                         }
    1161             :                 }
    1162             :                 */
    1163             :         }
    1164             : 
    1165        1890 :         return;
    1166             : }
    1167             : 
    1168             : // -----------------------------------------------------------------------
    1169             : // Parameter parser for on-the-fly (OTF) calibration
    1170             : // -----------------------------------------------------------------------
    1171        1890 : void MSTransformManager::parseCalParams(Record &configuration)
    1172             : {
    1173        1890 :         int exists = configuration.fieldNumber("callib");
    1174        1890 :         if (exists >= 0)
    1175             :         {
    1176             : 
    1177           9 :                 if (configuration.type(exists) == TpRecord)
    1178             :                 {
    1179             :                         // Extract the callib Record
    1180           9 :                         callibRec_p = configuration.subRecord(exists);
    1181           9 :                         callib_p="";
    1182             : 
    1183             :                         // If the Record is non-trivial, calibration is turned on
    1184           9 :                         calibrate_p = callibRec_p.nfields() > 0;
    1185             :                 }
    1186           0 :                 else if (configuration.type(exists) == TpString)
    1187             :                 {
    1188             :                         // Extract the callib String
    1189           0 :                         callib_p = configuration.asString(exists);
    1190           0 :                         callibRec_p = Record();
    1191             : 
    1192             :                         // If the callib_p String has non-trivial content, calibration in turned on
    1193           0 :                         calibrate_p = callib_p.length() > 0;
    1194             : 
    1195             :                 }
    1196             : 
    1197           9 :                 if (calibrate_p)
    1198             :                 {
    1199          18 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    1200          18 :                                                 << "Calibration is activated" << LogIO::POST;
    1201             :                 }
    1202             : 
    1203             :         }
    1204             : 
    1205        1890 :         return;
    1206             : }
    1207             : 
    1208             : // -----------------------------------------------------------------------
    1209             : // Parameter parser for continuum subtraction
    1210             : // -----------------------------------------------------------------------
    1211        1890 : void MSTransformManager::parseUVContSubParams(Record &configuration)
    1212             : {
    1213        1890 :     int exists = -1;
    1214             : 
    1215        1890 :     exists = -1;
    1216        1890 :     exists = configuration.fieldNumber("uvcontsub");
    1217        1890 :     if (exists >= 0)
    1218             :     {
    1219          57 :         configuration.get (exists, uvcontsub_p);
    1220             : 
    1221          57 :         if (uvcontsub_p)
    1222             :         {
    1223             :             // Extract the callib Record
    1224          57 :             exists = -1;
    1225          57 :             exists = configuration.fieldNumber("uvcontsublib");
    1226          57 :             if (configuration.type(exists) == TpRecord)
    1227             :             {
    1228          57 :                 uvcontsubRec_p = configuration.subRecord(exists);
    1229             :             }
    1230             : 
    1231         114 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",
    1232             :                                                    __FUNCTION__)
    1233             :                      << "Continuum subtraction is activated "
    1234         114 :                      << LogIO::POST;
    1235             : 
    1236             :             // not nice going into the subRec, perhaps a writemodel var
    1237             :             // could be put in the top level record
    1238          57 :             int writemodel = uvcontsubRec_p.fieldNumber("writemodel");
    1239          57 :             if (writemodel >= 0) {
    1240          57 :                 bool dowrite = false;
    1241          57 :                 uvcontsubRec_p.get(writemodel, dowrite);
    1242          57 :                 if (dowrite) {
    1243           3 :                     produceModel_p = true;
    1244             :                 }
    1245             :             }
    1246             :         }
    1247             :     }
    1248        1890 : }
    1249             : 
    1250             : // -----------------------------------------------------------------------
    1251             : // Method to set spw averaging
    1252             : // -----------------------------------------------------------------------
    1253        1890 : void MSTransformManager::setSpwAvg(Record &configuration)
    1254             : {
    1255        1890 :         int exists = -1;
    1256             : 
    1257        1890 :         exists = -1;
    1258        1890 :         exists = configuration.fieldNumber ("spwaverage");
    1259        1890 :         if (exists >= 0)
    1260             :         {
    1261           0 :                 configuration.get (exists, spwAverage_p);
    1262             : 
    1263           0 :                 if (spwAverage_p)
    1264             :                 {
    1265           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1266           0 :                                         << "Spw average is activated" << LogIO::POST;
    1267             :                 }
    1268             :         }
    1269        1890 : }
    1270             : 
    1271             : // -----------------------------------------------------------------------
    1272             : // Parameter parser for polarization transformation
    1273             : // -----------------------------------------------------------------------
    1274        1890 : void MSTransformManager::parsePolAvgParams(Record &configuration)
    1275             : {
    1276        1890 :   String key("polaverage");
    1277        1890 :   bool exists = configuration.isDefined(key);
    1278        1890 :   if (exists) {
    1279           6 :     polAverage_p = configuration.asBool(key);
    1280             :   }
    1281             : 
    1282        1890 :   key = "polaveragemode";
    1283        1890 :   if (polAverage_p) {
    1284           6 :     if (configuration.isDefined(key)) {
    1285           6 :       polAverageConfig_p.define("mode", configuration.asString(key));
    1286             :     } else {
    1287           0 :       polAverageConfig_p.define("mode", "default");
    1288             :     }
    1289             :   }
    1290        1890 : }
    1291             : 
    1292        1890 : void MSTransformManager::parsePointingsInterpolationParams(casacore::Record &configuration){
    1293        1890 :         String key("pointingsinterpolation");
    1294        1890 :         bool exists = configuration.isDefined(key);
    1295        1890 :         if (exists) {
    1296           0 :                 pointingsInterpolation_p = configuration.asBool(key);
    1297             :         }
    1298        1890 : }
    1299             : 
    1300        1890 : void MSTransformManager::parseAtmCorrectionParams(casacore::Record &configuration) {
    1301        1890 :     String key("atmCor");
    1302        1890 :     if (configuration.isDefined(key)) {
    1303         751 :         doAtmCor_p = configuration.asBool(key);
    1304         751 :         atmCorConfig_p = configuration;
    1305             :     } else {
    1306        1139 :         doAtmCor_p = False;
    1307             :     }
    1308        1890 : }
    1309             : 
    1310             : // -----------------------------------------------------------------------
    1311             : // Method to open the input MS, select the data and create the
    1312             : // structure of the output MS filling the auxiliary tables.
    1313             : // -----------------------------------------------------------------------
    1314        1890 : void MSTransformManager::open()
    1315             : {
    1316             :         // Initialize MSTransformDataHandler to open the MeasurementSet object
    1317        1890 :         if (interactive_p)
    1318             :         {
    1319             :                 // In buffer mode we may have to modify the flags
    1320           0 :                 dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Update);
    1321             :         }
    1322             :         else
    1323             :         {
    1324        1890 :                 dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Old);
    1325             :         }
    1326             : 
    1327             : 
    1328             :         // WARNING: Input MS is re-set at the end of a successful MSTransformDataHandler::makeMSBasicStructure,
    1329             :         // call therefore we have to use the selected MS always
    1330        1890 :         inputMs_p = dataHandler_p->getInputMS();
    1331             :         // Note: We always get the input number of channels because we don't know if pre-averaging will be necessary
    1332        1890 :         getInputNumberOfChannels();
    1333             : 
    1334             :         // Check available data cols to pass this information on to MSTransformDataHandler which creates the MS structure
    1335        1890 :         checkDataColumnsAvailable();
    1336        1890 :         checkDataColumnsToFill();
    1337             : 
    1338             : 
    1339             :         // Check whether the MS has correlator pre-averaging and we are smoothing or averaging
    1340        1890 :         checkCorrelatorPreaveraging();
    1341             : 
    1342             :         // Set virtual column operation
    1343        1890 :         dataHandler_p->setVirtualModelCol(makeVirtualModelColReal_p);
    1344        1890 :         dataHandler_p->setVirtualCorrectedCol(makeVirtualCorrectedColReal_p);
    1345             : 
    1346             :         // Once the input MS is opened we can get the selection indexes,
    1347             :         // in this way we also validate the selection parameters
    1348        1890 :         dataHandler_p->setReindex(reindex_p);
    1349        1890 :         initDataSelectionParams();
    1350             : 
    1351             :         // Once the selection parameters have been processed, check consistency in
    1352             :         // number of channels, if needed.
    1353        1886 :         checkSPWChannelsKnownLimitation();
    1354             : 
    1355             :         // Determine channel specification for output MS
    1356        1882 :         Vector<Int> chanSpec;
    1357        1882 :         bool spectralRegridding = combinespws_p or regridding_p;
    1358        1882 :         if (channelAverage_p and !spectralRegridding)
    1359             :         {
    1360         138 :                 chanSpec =  freqbin_p;
    1361             :         }
    1362             :         else
    1363             :         {
    1364        1744 :                 chanSpec = Vector<Int>(1,1);
    1365             :         }
    1366             : 
    1367             :         // Set-up splitter object
    1368        1882 :         const String dummyExpr = String("");
    1369        1882 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << "Select data" << LogIO::POST;
    1370        1882 :         dataHandler_p->setmsselect((const String)spwSelection_p,
    1371        3764 :                                                         (const String)fieldSelection_p,
    1372        3764 :                                                         (const String)baselineSelection_p,
    1373        3764 :                                                         (const String)scanSelection_p,
    1374        3764 :                                                         (const String)uvwSelection_p,
    1375        3764 :                                                         (const String)taqlSelection_p,
    1376             :                                                         chanSpec,
    1377        3764 :                                                         (const String)arraySelection_p,
    1378        3764 :                                                         (const String)polarizationSelection_p,
    1379        3764 :                                                         (const String)scanIntentSelection_p,
    1380        3764 :                                                         (const String)observationSelection_p,
    1381        3764 :                                                         (const String)feedSelection_p);
    1382             : 
    1383        1882 :         dataHandler_p->selectTime(timeBin_p,timeSelection_p);
    1384             : 
    1385        1882 :         createOutputMSStructure();
    1386             : 
    1387             :         // jagonzal (CAS-5076): Reindex state column when there is scan selection
    1388             :         // jagonzal (CAS-6351): Removing this fix as only implicit selection-based re-indexing has to be applied
    1389             :         /*
    1390             :         map<Int, Int> stateRemapper = dataHandler_p->getStateRemapper();
    1391             :     std::map<Int, Int>::iterator stateRemapperIter;
    1392             :     for (       stateRemapperIter = stateRemapper.begin();
    1393             :                 stateRemapperIter != stateRemapper.end();
    1394             :                 stateRemapperIter++)
    1395             :     {
    1396             :         inputOutputScanIntentIndexMap_p[stateRemapperIter->first] = stateRemapperIter->second;
    1397             : 
    1398             :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1399             :                         << "State " << stateRemapperIter->first << " mapped to " << stateRemapperIter->second << LogIO::POST;
    1400             :     }
    1401             :     */
    1402             : 
    1403             :     // jagonzal (CAS-5349): Reindex antenna columns when there is antenna selection
    1404        1864 :     if (!baselineSelection_p.empty() and reindex_p)
    1405             :     {
    1406         744 :         Vector<Int> antennaRemapper = dataHandler_p->getAntennaRemapper();
    1407        1797 :         for (uInt oldIndex=0;oldIndex<antennaRemapper.size();oldIndex++)
    1408             :         {
    1409        1053 :                 inputOutputAntennaIndexMap_p[oldIndex] = antennaRemapper[oldIndex];
    1410             :         }
    1411         744 :     }
    1412             : 
    1413             : 
    1414        1864 :         selectedInputMs_p = dataHandler_p->getSelectedInputMS();
    1415        1864 :         outputMs_p = dataHandler_p->getOutputMS();
    1416        1864 :         selectedInputMsCols_p = dataHandler_p->getSelectedInputMSColumns();
    1417        1864 :         outputMsCols_p = dataHandler_p->getOutputMSColumns();
    1418             : 
    1419        3728 :         return;
    1420        1900 : }
    1421             : 
    1422             : /**
    1423             :  * Whether the WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
    1424             :  * This should be honored when creating the output MS structure (in
    1425             :  * createOutputMSStructure().
    1426             :  *
    1427             :  * The logic to say true is: if the WEIGHT/SIGMA_SPECTRUM are present in the input MS or
    1428             :  * the user has requested the creation of these columns in the output MS anyway via the
    1429             :  * parameter 'usewtspectrum'
    1430             :  * This requires that the input configuration be parsed here in MSTransformManager before
    1431             :  * calling this method, and passed as parameter.
    1432             :  *
    1433             :  * @param usewtspectrum value of the usewtspectrum input parameter of mstransform
    1434             :  *
    1435             :  * @return whether WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
    1436             :  */
    1437        1882 : bool MSTransformManager::shouldCreateOutputWtSpectrum(bool usewtspectrum)
    1438             : {
    1439        1882 :     if (nullptr == inputMs_p) {
    1440           0 :         throw AipsError("When trying to guess if WEIGHT/SIGMA_SPECTRUM should be created "
    1441           0 :                         "in the output MS: the input MS has not been initialized.");
    1442             :     }
    1443             : 
    1444        1882 :     auto wtSpec = MSColumns(*inputMs_p).weightSpectrum();
    1445        1882 :     auto inputWeightSpectrumAvailable = !wtSpec.isNull() and wtSpec.isDefined(0);
    1446        3764 :     return inputWeightSpectrumAvailable or usewtspectrum;
    1447        1882 : }
    1448             : 
    1449             : /**
    1450             :  * Helper method for open() to create the structure of the output MS
    1451             :  * and check errors.
    1452             :  *
    1453             :  * @throws AipsError in case of errors creating the output MS
    1454             :  */
    1455        1882 : void MSTransformManager::createOutputMSStructure()
    1456             : {
    1457             :         // Create output MS structure
    1458        1882 :         if (not bufferMode_p)
    1459             :         {
    1460        3764 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1461        3764 :                                 << "Create output MS structure" << LogIO::POST;
    1462             :         }
    1463             :         else
    1464             :         {
    1465           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1466           0 :                                 << "Create transformed MS Subtables to be stored in memory" << LogIO::POST;
    1467             :         }
    1468             : 
    1469             : 
    1470             :         //jagonzal (CAS-5174)
    1471        1882 :         bool outputMSStructureCreated = false;
    1472             :         try
    1473             :         {
    1474        1882 :             Table::TableOption option = Table::New;
    1475        1882 :             if (bufferMode_p) {
    1476           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1477           0 :                          << "Create output MS structure" << LogIO::POST;
    1478           0 :                 option = Table::Scratch;
    1479             :             }
    1480             : 
    1481        1882 :             auto createWeightSpectrum = shouldCreateOutputWtSpectrum(usewtspectrum_p);
    1482        3746 :             outputMSStructureCreated = dataHandler_p->makeMSBasicStructure(outMsName_p,
    1483        1882 :                                                                            datacolumn_p,
    1484        1882 :                                                                            produceModel_p,
    1485             :                                                                            createWeightSpectrum,
    1486        1882 :                                                                            tileShape_p,
    1487        1882 :                                                                            timespan_p,
    1488             :                                                                            option);
    1489             :         }
    1490          18 :         catch (AipsError ex)
    1491             :         {
    1492          18 :                 outputMSStructureCreated = false;
    1493          18 :                 logger_p        << LogIO::DEBUG1
    1494             :                                         << "Exception creating output MS structure: " << ex.getMesg() << endl
    1495          18 :                                         << LogIO::POST;
    1496             : 
    1497          18 :                 throw AipsError(ex.getMesg());
    1498          36 :         }
    1499             : 
    1500             : 
    1501             : 
    1502        1864 :         if (!outputMSStructureCreated)
    1503             :         {
    1504           0 :                 throw AipsError("Error creating output MS structure");
    1505             :         }
    1506        1864 : }
    1507             : 
    1508             : // -----------------------------------------------------------------------
    1509             : // Method to close the output MS
    1510             : // -----------------------------------------------------------------------
    1511        3736 : void MSTransformManager::close()
    1512             : {
    1513        3736 :         if (outputMs_p)
    1514             :         {
    1515             :                 // unlock MS (the MS data handler will flush it when destroying it).
    1516        1864 :                 outputMs_p->unlock();
    1517        1864 :                 Table::relinquishAutoLocks(true);
    1518             : 
    1519             :                 // Unset the output MS
    1520        1864 :                 outputMs_p = NULL;
    1521             :         }
    1522             : 
    1523        3736 :         return;
    1524             : }
    1525             : 
    1526             : // -----------------------------------------------------------------------
    1527             : // Check configuration and input MS characteristics to determine run parameters
    1528             : // -----------------------------------------------------------------------
    1529        1864 : void MSTransformManager::setup()
    1530             : {
    1531             :         // Check what columns have to filled
    1532             :         // CAS-5581 (jagonzal): Moving these methods here because we need to know if
    1533             :         // WEIGHT_SPECTRUM is available to configure the appropriate averaging kernel.
    1534             :         // - note also that the availability of WEIGHT_SPECTRUM in the input MS needs
    1535             :         // to be checked even before, as it is needed when doing
    1536             :         // dataHandler_p->makeMSBasicStructure() in createOutputMSStructure() - CAS-11269
    1537        1864 :         checkFillFlagCategory();
    1538        1864 :         checkFillWeightSpectrum();
    1539             : 
    1540             :         // Check if we really need to combine SPWs
    1541        1864 :         if (combinespws_p)
    1542             :         {
    1543         128 :                 auto nInputSpws = outputMs_p->spectralWindow().nrow();
    1544         128 :                 if (nInputSpws < 2)
    1545             :                 {
    1546          76 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1547          76 :                                         << "There is only one selected SPW, no need to combine " << LogIO::POST;
    1548          38 :                         combinespws_p = false;
    1549             :                 }
    1550             :         }
    1551             : 
    1552             :         // Regrid SPW subtable
    1553        1864 :         if (combinespws_p)
    1554             :         {
    1555          90 :                 initRefFrameTransParams();
    1556          90 :                 regridAndCombineSpwSubtable();
    1557          90 :                 reindexDDISubTable();
    1558          90 :                 reindexSourceSubTable();
    1559             :                 //reindexFeedSubTable();
    1560             :                 //reindexSysCalSubTable();
    1561          90 :                 reindexFreqOffsetSubTable();
    1562          90 :                 reindexGenericTimeDependentSubTable("FEED");
    1563          90 :                 reindexGenericTimeDependentSubTable("SYSCAL");
    1564          90 :                 reindexGenericTimeDependentSubTable("CALDEVICE");
    1565          90 :                 reindexGenericTimeDependentSubTable("SYSPOWER");
    1566             :         }
    1567        1774 :         else if (regridding_p)  // regrid as in the regridms option
    1568             :         {
    1569          61 :                 initRefFrameTransParams();
    1570          61 :                 regridSpwSubTable();
    1571             :         }
    1572             : 
    1573             :         // Subtable manipulation for polarization averaging
    1574        1863 :         if (polAverage_p) {
    1575             : //        Int nInputPolarizations = outputMs_p->polarization().nrow();
    1576           6 :           Int averagedPolId = getAveragedPolarizationId();
    1577           6 :           reindexPolarizationIdInDataDesc(averagedPolId);
    1578             :         }
    1579             : 
    1580             :         //// Determine the frequency transformation methods to use ////
    1581             : 
    1582             : 
    1583             :         // Cube level
    1584        1863 :         if (combinespws_p)
    1585             :         {
    1586          90 :                 transformCubeOfDataComplex_p = &MSTransformManager::combineCubeOfData;
    1587          90 :                 transformCubeOfDataFloat_p = &MSTransformManager::combineCubeOfData;
    1588          90 :                 spectrumTransformation_p = true;
    1589          90 :                 propagateWeights_p = true;
    1590          90 :                 spectrumReshape_p = true;
    1591          90 :                 cubeTransformation_p = true;
    1592             :         }
    1593        1773 :         else if (regridding_p)
    1594             :         {
    1595          60 :                 transformCubeOfDataComplex_p = &MSTransformManager::regridCubeOfData;
    1596          60 :                 transformCubeOfDataFloat_p = &MSTransformManager::regridCubeOfData;
    1597          60 :                 spectrumTransformation_p = true;
    1598          60 :                 propagateWeights_p = true;
    1599          60 :                 spectrumReshape_p = true;
    1600          60 :                 cubeTransformation_p = true;
    1601             :         }
    1602        1713 :         else if (channelAverage_p)
    1603             :         {
    1604         136 :                 transformCubeOfDataComplex_p = &MSTransformManager::averageCubeOfData;
    1605         136 :                 transformCubeOfDataFloat_p = &MSTransformManager::averageCubeOfData;
    1606         136 :                 spectrumTransformation_p = true;
    1607         136 :                 propagateWeights_p = true;
    1608         136 :                 spectrumReshape_p = true;
    1609         136 :                 cubeTransformation_p = true;
    1610             :         }
    1611        1577 :         else if (hanningSmooth_p || smoothFourier_p)
    1612             :         {
    1613         175 :                 transformCubeOfDataComplex_p = &MSTransformManager::smoothCubeOfData;
    1614         175 :                 transformCubeOfDataFloat_p = &MSTransformManager::smoothCubeOfData;
    1615         175 :                 spectrumTransformation_p = true;
    1616         175 :                 cubeTransformation_p = true;
    1617             :         }
    1618        1402 :         else if (nspws_p > 1)
    1619             :         {
    1620           0 :                 transformCubeOfDataComplex_p = &MSTransformManager::separateCubeOfData;
    1621           0 :                 transformCubeOfDataFloat_p = &MSTransformManager::separateCubeOfData;
    1622           0 :                 spectrumReshape_p = true;
    1623           0 :                 cubeTransformation_p = true;
    1624             :         }
    1625             :         else
    1626             :         {
    1627        1402 :                 transformCubeOfDataComplex_p = &MSTransformManager::copyCubeOfData;
    1628        1402 :                 transformCubeOfDataFloat_p = &MSTransformManager::copyCubeOfData;
    1629             :         }
    1630             : 
    1631        1863 :         bool spectralRegridding = combinespws_p or regridding_p;
    1632             : 
    1633             :         // Vector level
    1634        1863 :         if (channelAverage_p and !hanningSmooth_p and !spectralRegridding)
    1635             :         {
    1636         136 :                 transformStripeOfDataComplex_p = &MSTransformManager::average;
    1637         136 :                 transformStripeOfDataFloat_p = &MSTransformManager::average;
    1638             :         }
    1639        1727 :         else if (!channelAverage_p and hanningSmooth_p and !spectralRegridding)
    1640             :         {
    1641          18 :                 transformStripeOfDataComplex_p = &MSTransformManager::smooth;
    1642          18 :                 transformStripeOfDataFloat_p = &MSTransformManager::smooth;
    1643             :         }
    1644        1709 :         else if (!channelAverage_p and !hanningSmooth_p and spectralRegridding)
    1645             :         {
    1646         143 :                 transformStripeOfDataComplex_p = &MSTransformManager::regrid;
    1647         143 :                 transformStripeOfDataFloat_p = &MSTransformManager::regrid;
    1648             :         }
    1649        1566 :         else if (channelAverage_p and hanningSmooth_p and !spectralRegridding)
    1650             :         {
    1651           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageSmooth;
    1652           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageSmooth;
    1653             :         }
    1654        1566 :         else if (channelAverage_p and !hanningSmooth_p and spectralRegridding)
    1655             :         {
    1656           2 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageRegrid;
    1657           2 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageRegrid;
    1658             :         }
    1659        1564 :         else if (!channelAverage_p and hanningSmooth_p and spectralRegridding)
    1660             :         {
    1661           5 :                 transformStripeOfDataComplex_p = &MSTransformManager::smoothRegrid;
    1662           5 :                 transformStripeOfDataFloat_p = &MSTransformManager::smoothRegrid;
    1663             :         }
    1664        1559 :         else if (channelAverage_p and hanningSmooth_p and spectralRegridding)
    1665             :         {
    1666           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageSmoothRegrid;
    1667           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageSmoothRegrid;
    1668             :         }
    1669        1559 :         else if (smoothFourier_p) {
    1670         157 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    1671         157 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    1672             :         }
    1673             : 
    1674             :         // If there is not inputWeightSpectrumAvailable_p and no time average then
    1675             :         // weightSpectrum is constant and has no effect in frequency avg./regridding
    1676        1863 :         if ((not inputWeightSpectrumAvailable_p) and (not timeAverage_p))
    1677             :         {
    1678        1458 :                 propagateWeights_p = false;
    1679        1458 :                 weightmode_p = MSTransformations::flagsNonZero;
    1680             :         }
    1681             :         else
    1682             :         {
    1683             :                 // NOTE: It does not hurt to set the averaging kernel even if we are not going to use it
    1684         405 :                 weightmode_p = MSTransformations::flagSpectrumNonZero;
    1685             :         }
    1686             : 
    1687             :         // SPECTRUM columns have to be set when they exists in the input or the user specifies it via usewtspectrum_p
    1688        1863 :         if (inputWeightSpectrumAvailable_p or usewtspectrum_p)
    1689             :         {
    1690         324 :                 flushWeightSpectrum_p = true;
    1691             :         }
    1692             :         else
    1693             :         {
    1694        1539 :                 flushWeightSpectrum_p = false;
    1695             :         }
    1696             : 
    1697        1863 :         propagateWeights(propagateWeights_p);
    1698        1863 :         setChannelAverageKernel(weightmode_p);
    1699        1863 :         setSmoothingKernel(smoothmode_p);
    1700             : 
    1701             : 
    1702             :         // Set Regridding kernel
    1703        1863 :         if (fftShiftEnabled_p)
    1704             :         {
    1705          11 :                 regridCoreComplex_p = &MSTransformManager::interpol1Dfftshift;
    1706          11 :                 regridCoreFloat_p = &MSTransformManager::interpol1Dfftshift;
    1707             :         }
    1708             :         else
    1709             :         {
    1710        1852 :                 regridCoreComplex_p = &MSTransformManager::interpol1D;
    1711        1852 :                 regridCoreFloat_p = &MSTransformManager::interpol1D;
    1712             :         }
    1713             : 
    1714             :         //// Determine the frequency transformation methods to use ////
    1715             : 
    1716             :         // Drop channels with non-uniform width when doing only channel average
    1717        1863 :         if (channelAverage_p and !regridding_p and !combinespws_p )
    1718             :         {
    1719         136 :                 dropNonUniformWidthChannels();
    1720             :         }
    1721             : 
    1722             :         // Get number of output channels (needed by chan avg and separate SPWs when there is only 1 selected SPW)
    1723        1863 :         if (channelAverage_p or (nspws_p>1 and !combinespws_p))
    1724             :         {
    1725         144 :                 getOutputNumberOfChannels();
    1726             :         }
    1727             : 
    1728             :         // Determine weight and sigma factors when either auto or user channel average is set
    1729        1863 :         if (channelAverage_p or combinespws_p or regridding_p)
    1730             :         {
    1731         286 :                 calculateNewWeightAndSigmaFactors();
    1732             :         }
    1733             : 
    1734             : 
    1735        1863 :         if (nspws_p > 1)
    1736             :         {
    1737          13 :                 uInt totalNumberOfOutputChannels = 0;
    1738          13 :                 if (combinespws_p)
    1739             :                 {
    1740           7 :                         totalNumberOfOutputChannels = inputOutputSpwMap_p[0].second.NUM_CHAN;
    1741             :                 }
    1742             :                 // jagonzal: This is the case when there is only one input SPW and there is no need to combine
    1743             :                 else
    1744             :                 {
    1745           6 :                         uInt spwId = 0;
    1746           6 :                 if (outputInputSPWIndexMap_p.size()>0)
    1747             :                 {
    1748           3 :                         spwId = outputInputSPWIndexMap_p[0];
    1749             :                 }
    1750             :                 else
    1751             :                 {
    1752           3 :                         spwId = 0;
    1753             :                 }
    1754             : 
    1755           6 :                 totalNumberOfOutputChannels = numOfOutChanMap_p[spwId];
    1756             :                 }
    1757             : 
    1758             : 
    1759          13 :                 chansPerOutputSpw_p = totalNumberOfOutputChannels / nspws_p;
    1760          13 :                 if (totalNumberOfOutputChannels % nspws_p)
    1761             :                 {
    1762           0 :                         chansPerOutputSpw_p += 1;
    1763           0 :                         tailOfChansforLastSpw_p = totalNumberOfOutputChannels - chansPerOutputSpw_p*(nspws_p-1);
    1764             :                 }
    1765             :                 else
    1766             :                 {
    1767          13 :                         tailOfChansforLastSpw_p = chansPerOutputSpw_p;
    1768             :                 }
    1769             : 
    1770          13 :                 if (bufferMode_p)
    1771             :                 {
    1772           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1773           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1774             :                 }
    1775             :                 else
    1776             :                 {
    1777          13 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
    1778          13 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
    1779             :                 }
    1780             : 
    1781          13 :                 separateSpwSubtable();
    1782          13 :                 separateFeedSubtable();
    1783          13 :                 separateSourceSubtable();
    1784          13 :                 separateSyscalSubtable();
    1785          13 :                 separateFreqOffsetSubtable();
    1786          13 :                 separateCalDeviceSubtable();
    1787          13 :                 separateSysPowerSubtable();
    1788             : 
    1789             :                 // CAS-5404. DDI sub-table has to be re-indexed after separating SPW sub-table
    1790          13 :                 if (not combinespws_p) reindexDDISubTable();
    1791             :         }
    1792             :         else
    1793             :         {
    1794        1850 :                 if (bufferMode_p)
    1795             :                 {
    1796           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
    1797           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
    1798             :                 }
    1799             :                 else
    1800             :                 {
    1801        1850 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
    1802        1850 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
    1803             :                 }
    1804             :         }
    1805             : 
    1806             :         // Generate Iterator
    1807        1863 :         setIterationApproach();
    1808        1863 :         generateIterator();
    1809             : 
    1810        1853 :         return;
    1811             : }
    1812             : 
    1813             : 
    1814             : // -----------------------------------------------------------------------
    1815             : //
    1816             : // -----------------------------------------------------------------------
    1817     1315204 : IPosition MSTransformManager::getShape()
    1818             : {
    1819     1315204 :         return getTransformedShape(visibilityIterator_p->getVisBuffer());
    1820             : }
    1821             : 
    1822             : // -----------------------------------------------------------------------
    1823             : //
    1824             : // -----------------------------------------------------------------------
    1825     1315204 : IPosition MSTransformManager::getTransformedShape(vi::VisBuffer2 *visBuffer)
    1826             : {
    1827     1315204 :         IPosition outputCubeShape(3);
    1828             : 
    1829             :         // Correlations
    1830     1315204 :         outputCubeShape(0) = visBuffer->nCorrelations();
    1831             : 
    1832             :         // Rows
    1833     1315204 :         outputCubeShape(2) = nRowsToAdd_p;
    1834             : 
    1835             :         // Channels
    1836     1315204 :         if (nspws_p > 1)
    1837             :         {
    1838        9674 :                 outputCubeShape(1) = chansPerOutputSpw_p;
    1839             :         }
    1840     1305530 :         else if (combinespws_p)
    1841             :         {
    1842       32676 :                 outputCubeShape(1) = inputOutputSpwMap_p[0].second.NUM_CHAN;
    1843             :         }
    1844     1272854 :         else if (regridding_p)
    1845             :         {
    1846       45469 :                 Int inputSpw = visBuffer->spectralWindows()(0);
    1847       45469 :                 outputCubeShape(1) = inputOutputSpwMap_p[inputSpw].second.NUM_CHAN;
    1848             :         }
    1849     1227385 :         else if (channelAverage_p)
    1850             :         {
    1851      788522 :                 Int inputSpw = visBuffer->spectralWindows()(0);
    1852      788522 :                 outputCubeShape(1) = numOfOutChanMap_p[inputSpw];
    1853             :         }
    1854             :         else
    1855             :         {
    1856      438863 :                 outputCubeShape(1) = visBuffer->nChannels();
    1857             :         }
    1858             : 
    1859     1315204 :         return outputCubeShape;
    1860           0 : }
    1861             : 
    1862             : // -----------------------------------------------------------------------
    1863             : //
    1864             : // -----------------------------------------------------------------------
    1865      344845 : void MSTransformManager::propagateWeights(bool on)
    1866             : {
    1867             : 
    1868      344845 :         if (on)
    1869             :         {
    1870             :                 // Used by SPW combination
    1871       23564 :                 fillWeightsPlane_p = &MSTransformManager::fillWeightsPlane;
    1872       23564 :                 normalizeWeightsPlane_p = &MSTransformManager::normalizeWeightsPlane;
    1873             : 
    1874             :                 // Used by channel average
    1875       23564 :                 setWeightsPlaneByReference_p = &MSTransformManager::setWeightsPlaneByReference;
    1876       23564 :                 setWeightStripeByReference_p = &MSTransformManager::setWeightStripeByReference;
    1877             :         }
    1878             :         else
    1879             :         {
    1880             :                 // Used by SPW combination
    1881      321281 :                 fillWeightsPlane_p = &MSTransformManager::dontfillWeightsPlane;
    1882      321281 :                 normalizeWeightsPlane_p = &MSTransformManager::dontNormalizeWeightsPlane;
    1883             : 
    1884             :                 // Used by channel average
    1885      321281 :                 setWeightsPlaneByReference_p = &MSTransformManager::dontsetWeightsPlaneByReference;
    1886      321281 :                 setWeightStripeByReference_p = &MSTransformManager::dontSetWeightStripeByReference;
    1887             :         }
    1888             : 
    1889      344845 :         return;
    1890             : }
    1891             : 
    1892             : // -----------------------------------------------------------------------
    1893             : //
    1894             : // -----------------------------------------------------------------------
    1895      300198 : void MSTransformManager::setBufferMode(bool on)
    1896             : {
    1897      300198 :         bufferMode_p = on;
    1898             : 
    1899      300198 :         if (nspws_p > 1)
    1900             :         {
    1901        3942 :                 if (bufferMode_p)
    1902             :                 {
    1903        1971 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1904        1971 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1905             :                 }
    1906             :                 else
    1907             :                 {
    1908        1971 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
    1909        1971 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
    1910             :                 }
    1911             :         }
    1912             :         else
    1913             :         {
    1914      296256 :                 if (bufferMode_p)
    1915             :                 {
    1916      148128 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
    1917      148128 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
    1918             :                 }
    1919             :                 else
    1920             :                 {
    1921      148128 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
    1922      148128 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
    1923             :                 }
    1924             :         }
    1925             : 
    1926      300198 :         return;
    1927             : }
    1928             : 
    1929             : // -----------------------------------------------------------------------
    1930             : //
    1931             : // -----------------------------------------------------------------------
    1932      344845 : void MSTransformManager::setChannelAverageKernel(uInt mode)
    1933             : {
    1934      344845 :         switch (mode)
    1935             :         {
    1936           0 :                 case MSTransformations::spectrum:
    1937             :                 {
    1938           0 :                         averageKernelComplex_p = &MSTransformManager::weightAverageKernel;
    1939           0 :                         averageKernelFloat_p = &MSTransformManager::weightAverageKernel;
    1940           0 :                         break;
    1941             :                 }
    1942           0 :                 case MSTransformations::flags:
    1943             :                 {
    1944           0 :                         averageKernelComplex_p = &MSTransformManager::flagAverageKernel;
    1945           0 :                         averageKernelFloat_p = &MSTransformManager::flagAverageKernel;
    1946           0 :                         break;
    1947             :                 }
    1948           0 :                 case MSTransformations::cumSum:
    1949             :                 {
    1950           0 :                         averageKernelComplex_p = &MSTransformManager::cumSumKernel;
    1951           0 :                         averageKernelFloat_p = &MSTransformManager::cumSumKernel;
    1952           0 :                         break;
    1953             :                 }
    1954           0 :                 case MSTransformations::flagSpectrum:
    1955             :                 {
    1956           0 :                         averageKernelComplex_p = &MSTransformManager::flagWeightAverageKernel;
    1957           0 :                         averageKernelFloat_p = &MSTransformManager::flagWeightAverageKernel;
    1958           0 :                         break;
    1959             :                 }
    1960           0 :                 case MSTransformations::flagCumSum:
    1961             :                 {
    1962           0 :                         averageKernelComplex_p = &MSTransformManager::flagCumSumKernel;
    1963           0 :                         averageKernelFloat_p = &MSTransformManager::flagCumSumKernel;
    1964           0 :                         break;
    1965             :                 }
    1966      126724 :                 case MSTransformations::flagsNonZero:
    1967             :                 {
    1968      126724 :                         averageKernelComplex_p = &MSTransformManager::flagNonZeroAverageKernel;
    1969      126724 :                         averageKernelFloat_p = &MSTransformManager::flagNonZeroAverageKernel;
    1970      126724 :                         break;
    1971             :                 }
    1972       46630 :                 case MSTransformations::flagSpectrumNonZero:
    1973             :                 {
    1974       46630 :                         averageKernelComplex_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
    1975       46630 :                         averageKernelFloat_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
    1976       46630 :                         break;
    1977             :                 }
    1978      171491 :                 case MSTransformations::flagCumSumNonZero:
    1979             :                 {
    1980      171491 :                         averageKernelComplex_p = &MSTransformManager::flagCumSumNonZeroKernel;
    1981      171491 :                         averageKernelFloat_p = &MSTransformManager::flagCumSumNonZeroKernel;
    1982      171491 :                         break;
    1983             :                 }
    1984           0 :                 default:
    1985             :                 {
    1986           0 :                         averageKernelComplex_p = &MSTransformManager::simpleAverageKernel;
    1987           0 :                         averageKernelFloat_p = &MSTransformManager::simpleAverageKernel;
    1988           0 :                         break;
    1989             :                 }
    1990             :         }
    1991             : 
    1992      344845 :         return;
    1993             : }
    1994             : 
    1995             : // -----------------------------------------------------------------------
    1996             : //
    1997             : // -----------------------------------------------------------------------
    1998      344845 : void MSTransformManager::setSmoothingKernel(uInt mode)
    1999             : {
    2000      344845 :         switch (mode)
    2001             :         {
    2002      173354 :                 case MSTransformations::plainSmooth:
    2003             :                 {
    2004      173354 :                         smoothKernelComplex_p = &MSTransformManager::plainSmooth;
    2005      173354 :                         smoothKernelFloat_p = &MSTransformManager::plainSmooth;
    2006      173354 :                         break;
    2007             :                 }
    2008      171491 :                 case MSTransformations::plainSmoothSpectrum:
    2009             :                 {
    2010      171491 :                         smoothKernelComplex_p = &MSTransformManager::plainSmoothSpectrum;
    2011      171491 :                         smoothKernelFloat_p = &MSTransformManager::plainSmoothSpectrum;
    2012      171491 :                         break;
    2013             :                 }
    2014           0 :                 default:
    2015             :                 {
    2016           0 :                         smoothKernelComplex_p = &MSTransformManager::plainSmooth;
    2017           0 :                         smoothKernelFloat_p = &MSTransformManager::plainSmooth;
    2018           0 :                         break;
    2019             :                 }
    2020             :         }
    2021             : 
    2022      344845 :         return;
    2023             : }
    2024             : 
    2025             : // -----------------------------------------------------------------------
    2026             : //
    2027             : // -----------------------------------------------------------------------
    2028      342982 : void MSTransformManager::setSmoothingFourierKernel(uInt mode)
    2029             : {
    2030      342982 :   if (smoothFourier_p) {
    2031        1378 :     switch (mode)
    2032             :     {
    2033         689 :       case MSTransformations::plainSmooth:
    2034             :       {
    2035             :         //logger_p << "Set smoothing kernel to smoothFourier" << LogIO::POST;
    2036         689 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    2037         689 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    2038         689 :         break;
    2039             :       }
    2040         689 :       case MSTransformations::plainSmoothSpectrum:
    2041             :       {
    2042             :         //logger_p << "Set smoothing kernel to smooth (for weight propagation)" << LogIO::POST;
    2043         689 :         transformStripeOfDataComplex_p = &MSTransformManager::smooth;
    2044         689 :         transformStripeOfDataFloat_p = &MSTransformManager::smooth;
    2045         689 :         break;
    2046             :       }
    2047           0 :       default:
    2048             :       {
    2049           0 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    2050           0 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    2051           0 :         break;
    2052             :       }
    2053             :     }
    2054             :   }
    2055             : 
    2056      342982 :   return;
    2057             : }
    2058             : 
    2059             : // -----------------------------------------------------------------------
    2060             : //
    2061             : // -----------------------------------------------------------------------
    2062        1890 : void MSTransformManager::initDataSelectionParams()
    2063             : {
    2064        1890 :     MSSelection mssel;
    2065             : 
    2066        1890 :     if (reindex_p)
    2067             :     {
    2068        1788 :         if (!observationSelection_p.empty())
    2069             :         {
    2070          10 :             mssel.setObservationExpr(observationSelection_p);
    2071          10 :             Vector<Int> observationList = mssel.getObservationList(inputMs_p);
    2072          20 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2073          20 :                                                 << "Selected Observations Ids are " << observationList << LogIO::POST;
    2074             : 
    2075          22 :             for (uInt index=0; index < observationList.size(); index++)
    2076             :             {
    2077          12 :                 inputOutputObservationIndexMap_p[observationList(index)] = index;
    2078             :             }
    2079          10 :         }
    2080             : 
    2081        1788 :         if (!arraySelection_p.empty())
    2082             :         {
    2083           2 :             mssel.setArrayExpr(arraySelection_p);
    2084           2 :             Vector<Int> arrayList = mssel.getSubArrayList(inputMs_p);
    2085           4 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2086           4 :                                                 << "Selected Arrays Ids are " << arrayList << LogIO::POST;
    2087             : 
    2088           4 :             for (uInt index=0; index < arrayList.size(); index++)
    2089             :             {
    2090           2 :                 inputOutputArrayIndexMap_p[arrayList(index)] = index;
    2091             :             }
    2092           2 :         }
    2093             : 
    2094        1788 :         if (!scanSelection_p.empty())
    2095             :         {
    2096         126 :             mssel.setScanExpr(scanSelection_p);
    2097         126 :             Vector<Int> scanList = mssel.getScanList(inputMs_p);
    2098         252 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2099         252 :                                                 << "Selected Scans Ids are " << scanList << LogIO::POST;
    2100             : 
    2101         369 :             for (uInt index=0; index < scanList.size(); index++)
    2102             :             {
    2103         243 :                 inputOutputScanIndexMap_p[scanList(index)] = index;
    2104             :             }
    2105         126 :         }
    2106             : 
    2107        1788 :         if (!scanIntentSelection_p.empty())
    2108             :         {
    2109         102 :             mssel.setStateExpr(scanIntentSelection_p);
    2110         102 :             Vector<Int> scanIntentList = mssel.getStateObsModeList(inputMs_p);
    2111         204 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2112         204 :                                                 << "Selected Scans Intents Ids are " << scanIntentList << LogIO::POST;
    2113             : 
    2114         342 :             for (uInt index=0; index < scanIntentList.size(); index++)
    2115             :             {
    2116         240 :                 inputOutputScanIntentIndexMap_p[scanIntentList(index)] = index;
    2117             :             }
    2118         102 :         }
    2119             : 
    2120        1788 :         if (!fieldSelection_p.empty())
    2121             :         {
    2122          63 :             mssel.setFieldExpr(fieldSelection_p);
    2123          63 :             Vector<Int> fieldList = mssel.getFieldList(inputMs_p);
    2124         124 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2125         124 :                                                 << "Selected Fields Ids are " << fieldList << LogIO::POST;
    2126             : 
    2127         140 :             for (uInt index=0; index < fieldList.size(); index++)
    2128             :             {
    2129          78 :                 inputOutputFieldIndexMap_p[fieldList(index)] = index;
    2130             :             }
    2131          62 :         }
    2132             :     }
    2133             : 
    2134             : 
    2135        1889 :     if (!spwSelection_p.empty())
    2136             :     {
    2137        1134 :         mssel.setSpwExpr(spwSelection_p);
    2138        1134 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2139             : 
    2140             :         // Get the DD IDs of this spw selection
    2141        1131 :         Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
    2142             : 
    2143             :         // Take into account the polarization selections
    2144        1131 :         if (!polarizationSelection_p.empty()){
    2145          67 :             mssel.setPolnExpr(polarizationSelection_p.c_str());
    2146          67 :             Vector<Int> polddi = mssel.getDDIDList(inputMs_p);
    2147          67 :             if (polddi.size() > 0){
    2148             :                 // make an intersection
    2149          67 :                 Vector<Int> commonDDI = set_intersection(spwddi, polddi);
    2150          67 :                 uInt nddids = commonDDI.size();
    2151          67 :                 if (nddids > 0){
    2152          67 :                     spwddi.resize(nddids);
    2153         406 :                     for (uInt ii = 0; ii < nddids; ++ii){
    2154         339 :                         spwddi[ii] = commonDDI[ii];
    2155             :                     }
    2156             :                 }
    2157          67 :             }
    2158          67 :         }
    2159             : 
    2160        1131 :         uInt nddi = spwddi.size();
    2161             :         Int ddid;
    2162        2262 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2163        2262 :                                         << "Selected SPWs Ids are " << spwchan << LogIO::POST;
    2164             :         // Example of MS with repeated SPW ID in DD table:
    2165             :         // DD   POL             SPW
    2166             :         //      0       0               0 (RR)
    2167             :         //      1       1               0 (LL)
    2168             :         //      2       2               1 (RR,LL)
    2169             :         //      3       3               2 (RR,LL,RL,LR)
    2170             :         // example of selection: spw=0,1 correlation=RR, so selected DDs are
    2171             :         //      DD      POL             SPW
    2172             :         //      0       0               0
    2173             :         //      2       2               1
    2174             : 
    2175             :         // Do the mapping of DD between input and output
    2176        1131 :         if (reindex_p)
    2177             :         {
    2178        4241 :             for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
    2179             :             {
    2180             :                 // Get dd id and set the input-output dd map
    2181             :                 // This will only be used to write the DD ids in the main table
    2182        3157 :                 ddid = spwddi[selection_ii];
    2183        3157 :                 inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
    2184             :             }
    2185             :         }
    2186             : 
    2187        1131 :         IPosition shape = spwchan.shape();
    2188        1131 :         uInt nSelections = shape[0];
    2189             :         Int spw,channelStart,channelStop,channelStep,channelWidth;
    2190        1131 :         if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
    2191             : 
    2192             :         // Do the spw mapping between input and output
    2193        1131 :         uInt outputSpwIndex = 0;
    2194        5154 :         for(uInt selection_i=0;selection_i<nSelections;selection_i++)
    2195             :         {
    2196             :             // Get spw id and set the input-output spw map
    2197        4023 :             spw = spwchan(selection_i,0);
    2198             : 
    2199             :             // Set the channel selection ()
    2200        4023 :             channelStart = spwchan(selection_i,1);
    2201        4023 :             channelStop = spwchan(selection_i,2);
    2202        4023 :             channelStep = spwchan(selection_i,3);
    2203             :             // number of channels to select, starting with first selected channel:
    2204        4023 :             channelWidth = 1 + floor(float(channelStop - channelStart) / float(channelStep));
    2205        4023 :             channelSelector_p->add (spw, channelStart, channelWidth, channelStep);
    2206             : 
    2207        4023 :             if (numOfSelChanMap_p.find(spw) == numOfSelChanMap_p.end())
    2208             :             {
    2209        4016 :                 if (reindex_p)
    2210             :                 {
    2211        3146 :                     inputOutputSPWIndexMap_p[spw] = outputSpwIndex + ddiStart_p;
    2212             : 
    2213        3146 :                     outputInputSPWIndexMap_p[outputSpwIndex] = spw;
    2214             :                 }
    2215             : 
    2216        4016 :                 numOfSelChanMap_p[spw] = channelWidth;
    2217             : 
    2218        4016 :                 outputSpwIndex ++;
    2219             : 
    2220        4016 :                 inputOutputChanIndexMap_p[spw].clear(); // Accesing the vector creates it
    2221             :             }
    2222             :             else
    2223             :             {
    2224           7 :                 numOfSelChanMap_p[spw] += channelWidth;
    2225             :             }
    2226             : 
    2227    10848325 :             for (Int inpChan=channelStart;inpChan<=channelStop;inpChan += channelStep)
    2228             :             {
    2229    10844302 :                 inputOutputChanIndexMap_p[spw].push_back(inpChan);
    2230             :             }
    2231             :         }
    2232        1131 :     }
    2233             : 
    2234             :     // jagonzal: must fill numOfSelChanMap_p
    2235             :     else
    2236             :     {
    2237         755 :         spwSelection_p = "*";
    2238         755 :         mssel.setSpwExpr(spwSelection_p);
    2239         755 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2240             : 
    2241         755 :         IPosition shape = spwchan.shape();
    2242         755 :         uInt nSelections = shape[0];
    2243             :         Int spw,channelStart,channelStop,channelWidth;
    2244        9602 :         for(uInt selection_i=0;selection_i<nSelections;selection_i++)
    2245             :         {
    2246             :             // Get spw id and set the input-output spw map
    2247        8847 :             spw = spwchan(selection_i,0);
    2248             : 
    2249             :             // Set the channel selection ()
    2250        8847 :             channelStart = spwchan(selection_i,1);
    2251        8847 :             channelStop = spwchan(selection_i,2);
    2252        8847 :             channelWidth = channelStop-channelStart+1;
    2253        8847 :             numOfSelChanMap_p[spw] = channelWidth;
    2254             :         }
    2255             : 
    2256             :         // CAS-8631: Even w/o spw selection MSTransformDataHandler sets spws selection to *
    2257             :         //           in order to obtain the SPW-DDI list. It turns out that sometimes the
    2258             :         //           output DDI sub-table is resorted, for instance in case of non-monotonic
    2259             :         //           DDI-SPW relation,  therefore it is necessary to map input-output DDIS
    2260         755 :         if (reindex_p)
    2261             :         {
    2262         701 :             Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
    2263             : 
    2264             :             Int ddid;
    2265         701 :             uInt nddi = spwddi.size();
    2266        6982 :             for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
    2267             :             {
    2268             :                 // Get dd id and set the input-output dd map
    2269             :                 // This will only be used to write the DD ids in the main table
    2270        6281 :                 ddid = spwddi[selection_ii];
    2271        6281 :                 inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
    2272             :             }
    2273         701 :         }
    2274             : 
    2275         755 :         spwSelection_p = "";
    2276         755 :     }
    2277             : 
    2278             :     // If we have channel average we have to populate the freqbin map
    2279        1886 :     if (channelAverage_p)
    2280             :     {
    2281         140 :         if (!spwSelection_p.empty())
    2282             :         {
    2283          38 :             mssel.setSpwExpr(spwSelection_p);
    2284             :         }
    2285             :         else
    2286             :         {
    2287         102 :             mssel.setSpwExpr("*");
    2288             :         }
    2289             : 
    2290             :         //Vector<Int> spwList = mssel.getSpwList(inputMs_p);
    2291         140 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2292             : 
    2293             :         // jagonzal (CAS-7149): Have to remove duplicates: With multiple pols per SPW
    2294             :         // each SPWId appears various (see times test_chanavg_spw_with_diff_pol_shape)
    2295         140 :         vector<Int> noDupSpwList;
    2296        1528 :         for (size_t idx=0;idx < spwchan.nrow(); idx++)
    2297             :         {
    2298        1388 :             if (find(noDupSpwList.begin(),noDupSpwList.end(),spwchan(idx,0)) == noDupSpwList.end())
    2299             :             {
    2300        1388 :                 noDupSpwList.push_back(spwchan(idx,0));
    2301             :             }
    2302             :         }
    2303             : 
    2304             :         //spwList.resize(noDupSpwList.size());
    2305             :         //for (uInt idx=0;idx < noDupSpwList.size(); idx++) spwList(idx) = noDupSpwList[idx];
    2306         140 :         Vector<Int> spwList(noDupSpwList);
    2307             : 
    2308         140 :         if (freqbin_p.size() == 1)
    2309             :         {
    2310         130 :             if(combinespws_p)
    2311             :             {
    2312           2 :                 uInt spwAfterComb = 0;
    2313           2 :                 freqbinMap_p[spwAfterComb] = freqbin_p(spwAfterComb);
    2314             :             }
    2315             :             else
    2316             :             {
    2317             :                 // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2318         128 :                 Int freqbin = freqbin_p(0);
    2319         128 :                 freqbin_p.resize(spwList.size(),True);
    2320         128 :                 freqbin_p = freqbin;
    2321             : 
    2322        1483 :                 for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
    2323             :                 {
    2324        1355 :                     freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2325             : 
    2326             :                     // jagonzal (new WEIGHT/SIGMA convention)
    2327             :                     // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
    2328        1355 :                     if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
    2329             :                     {
    2330           8 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    2331           4 :                                                                      << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
    2332           8 :                                                                                                                             << " for SPW " << spwList(spw_i)
    2333           8 :                                                                                                                             << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
    2334           8 :                                                                                                                             << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
    2335           8 :                                                                                                                                                                           << " for SPW " << spwList(spw_i)
    2336          16 :                                                                                                                                                                           << LogIO::POST;
    2337           4 :                         freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2338           4 :                         newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2339             :                         // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2340           4 :                         freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
    2341             :                     }
    2342             :                     else
    2343             :                     {
    2344        1351 :                         newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2345             :                     }
    2346             :                 }
    2347             :             }
    2348             :         }
    2349             :         else
    2350             :         {
    2351          10 :             if (spwList.size() != freqbin_p.size())
    2352             :             {
    2353           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2354             :                                                         << "Number of frequency bins ( "
    2355             :                                                         << freqbin_p.size() << " ) different from number of selected spws ( "
    2356           0 :                                                         << spwList.size() << " )" << LogIO::POST;
    2357             :             }
    2358             :             else
    2359             :             {
    2360          39 :                 for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
    2361             :                 {
    2362          29 :                     freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2363             :                     // jagonzal (new WEIGHT/SIGMA convention)
    2364             :                     // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
    2365          29 :                     if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
    2366             :                     {
    2367           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    2368           0 :                                                                         << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
    2369           0 :                                                                                                                                << " for SPW " << spwList(spw_i)
    2370           0 :                                                                                                                                << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
    2371           0 :                                                                                                                                << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
    2372           0 :                                                                                                                                                                              << " for SPW " << spwList(spw_i)
    2373           0 :                                                                                                                                                                              << LogIO::POST;
    2374           0 :                         freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2375           0 :                         newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2376             :                         // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2377           0 :                         freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
    2378             :                     }
    2379             :                     else
    2380             :                     {
    2381          29 :                         newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2382             :                     }
    2383             :                 }
    2384             :             }
    2385             :         }
    2386         140 :     }
    2387             : 
    2388        1886 :     if (!polarizationSelection_p.empty())
    2389             :     {
    2390          77 :         mssel.setPolnExpr(polarizationSelection_p.c_str());
    2391          77 :         Vector <Vector <Slice> > correlationSlices;
    2392          77 :         mssel.getCorrSlices(correlationSlices,inputMs_p);
    2393         154 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2394         154 :                                         << "Selected correlations are " << correlationSlices << LogIO::POST;
    2395             : 
    2396          77 :         if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
    2397             : 
    2398          77 :         channelSelector_p->addCorrelationSlices(correlationSlices);
    2399             : 
    2400             :         // Get the DDs related to the polarization selection
    2401             :         // when there is no spw selection
    2402          77 :         if (spwSelection_p.empty() and reindex_p)
    2403             :         {
    2404          10 :             std::vector<Int> polddids = mssel.getDDIDList(inputMs_p).tovector();
    2405             :             // The output from MSSelection might not be sorted
    2406          10 :             std::sort(polddids.begin(), polddids.end());
    2407             : 
    2408             :             // Make the in/out DD mapping
    2409          10 :             size_t nddids = polddids.size();
    2410             :             Int dd;
    2411         102 :             for(size_t ii=0;ii<nddids;ii++)
    2412             :             {
    2413             :                 // Get dd id and set the input-output dd map
    2414          92 :                 dd = polddids[ii];
    2415          92 :                 inputOutputDDIndexMap_p[dd] = ii + ddiStart_p;
    2416             :             }
    2417             : 
    2418          10 :         }
    2419             : 
    2420          77 :     }
    2421             : 
    2422        3772 :     return;
    2423        1890 : }
    2424             : 
    2425             : // -----------------------------------------------------------------------
    2426             : // Method to initialize the reference frame transformation parameters
    2427             : // -----------------------------------------------------------------------
    2428         151 : void MSTransformManager::initRefFrameTransParams()
    2429             : {
    2430         151 :   inputReferenceFrame_p = determineInputRefFrame();
    2431             : 
    2432             :   // Parse output reference frame
    2433         151 :   refFrameTransformation_p = true;
    2434         151 :   radialVelocityCorrection_p = false;
    2435         151 :   if(outputReferenceFramePar_p.empty()) {
    2436         110 :     outputReferenceFrame_p = inputReferenceFrame_p;
    2437             :   }
    2438             :   // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2439          41 :   else if (outputReferenceFramePar_p == "SOURCE") {
    2440           5 :     outputReferenceFrame_p = MFrequency::GEO;
    2441           5 :     radialVelocityCorrection_p = true;
    2442          36 :   } else if(!MFrequency::getType(outputReferenceFrame_p, outputReferenceFramePar_p)) {
    2443           0 :     logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2444           0 :              << "Problem parsing output reference frame:" << outputReferenceFramePar_p
    2445           0 :              << LogIO::EXCEPTION;
    2446             :   }
    2447             : 
    2448         151 :   if (outputReferenceFrame_p == inputReferenceFrame_p) {
    2449         111 :     refFrameTransformation_p = false;
    2450             :   }
    2451             : 
    2452             :   // Determine observatory position from the first row in the observation sub-table of the output (selected) MS
    2453         151 :   MSObservation observationTable;
    2454         151 :   if (userBufferMode_p) {
    2455           0 :     observationTable = selectedInputMs_p->observation();
    2456             :   } else {
    2457         151 :     observationTable = outputMs_p->observation();
    2458             :   }
    2459         151 :   MSObservationColumns observationCols(observationTable);
    2460         151 :   String observatoryName = observationCols.telescopeName()(0);
    2461         151 :   MeasTable::Observatory(observatoryPosition_p,observatoryName);
    2462             : 
    2463             :   // jagonzal: This conversion is needed only for cosmetic reasons
    2464             :   // observatoryPosition_p=MPosition::Convert(observatoryPosition_p, MPosition::ITRF)();
    2465             : 
    2466             :   // Determine observation time from the first row in the selected MS
    2467         151 :   referenceTime_p = selectedInputMsCols_p->timeMeas()(0);
    2468             : 
    2469             :   // Access FIELD cols to get phase center and radial velocity
    2470         151 :   inputMSFieldCols_p = std::make_shared<MSFieldColumns>(selectedInputMs_p->field());
    2471             : 
    2472         151 :   phaseCenter_p = determinePhaseCenter();
    2473         151 : }
    2474             : 
    2475             : /**
    2476             :  * Determine input reference frame from the first row in the SPW 8
    2477             :  * sub-table of the output/selected MS.
    2478             :  * Helper for the initialization of the reference frame transformations
    2479             :  *
    2480             :  * @return Reference frame of output/selected MS.
    2481             :  */
    2482         151 : casacore::MFrequency::Types MSTransformManager::determineInputRefFrame() {
    2483         151 :   MSSpectralWindow spwTable;
    2484         151 :   if (userBufferMode_p) {
    2485           0 :     spwTable = selectedInputMs_p->spectralWindow();
    2486             :   } else {
    2487         151 :     spwTable = outputMs_p->spectralWindow();
    2488             :   }
    2489         151 :   MSSpWindowColumns spwCols(spwTable);
    2490             : 
    2491             :   casacore::MFrequency::Types result;
    2492         151 :   if (reindex_p) {
    2493         148 :     result = MFrequency::castType(spwCols.measFreqRef()(0));
    2494             :   } else {
    2495           3 :     Int firstSelectedDDI = selectedInputMsCols_p->dataDescId()(0);
    2496           3 :     MSDataDescription ddiTable = outputMs_p->dataDescription();
    2497           3 :     MSDataDescColumns ddiCols(ddiTable);
    2498           3 :     Int firstSelectedSPW = ddiCols.spectralWindowId()(firstSelectedDDI);
    2499           3 :     result = MFrequency::castType(spwCols.measFreqRef()(firstSelectedSPW));
    2500           3 :   }
    2501             : 
    2502         151 :   return result;
    2503         151 : }
    2504             : 
    2505             : /**
    2506             :  * Determine phase center from output/selected MS.
    2507             :  * Helper for the initialization of the reference frame transformations
    2508             :  *
    2509             :  * @return phase center from output/selected MS.
    2510             :  */
    2511         151 : casacore::MDirection MSTransformManager::determinePhaseCenter() {
    2512         151 :   casacore::MDirection result;
    2513             : 
    2514             :   // Determine phase center
    2515         151 :   if (phaseCenterPar_p->type() == casac::variant::INT) {
    2516           4 :     Int fieldIdForPhaseCenter = phaseCenterPar_p->toInt();
    2517             : 
    2518           4 :     if (fieldIdForPhaseCenter >= (Int)inputMSFieldCols_p->nrow() ||
    2519             :         fieldIdForPhaseCenter < 0) {
    2520           2 :       logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2521             :                << "Selected FIELD_ID to determine phase center does not exist "
    2522           2 :                << LogIO::POST;
    2523             :     } else {
    2524             :       // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2525           3 :       if (radialVelocityCorrection_p) {
    2526           0 :         radialVelocity_p = inputMSFieldCols_p->radVelMeas(fieldIdForPhaseCenter,
    2527           0 :                                                           referenceTime_p.get("s").getValue());
    2528           0 :         result = inputMSFieldCols_p->phaseDirMeas(fieldIdForPhaseCenter,
    2529           0 :                                                          referenceTime_p.get("s").getValue());
    2530             :       } else {
    2531           3 :         result = inputMSFieldCols_p->phaseDirMeasCol()(fieldIdForPhaseCenter)(IPosition(1,0));
    2532             :       }
    2533             :     }
    2534             :   } else {
    2535         147 :     String phaseCenter = phaseCenterPar_p->toString(true);
    2536             : 
    2537             :     // Determine phase center from the first row in the FIELD sub-table of the output
    2538             :     // (selected) MS
    2539         147 :     if (phaseCenter.empty()) {
    2540         122 :       std::shared_ptr<MSFieldColumns> fieldCols;
    2541         122 :       if (userBufferMode_p) {
    2542           0 :         fieldCols = inputMSFieldCols_p;
    2543             :       } else {
    2544         122 :         MSField fieldTable = outputMs_p->field();
    2545         122 :         fieldCols = std::make_shared<MSFieldColumns>(fieldTable);
    2546         122 :       }
    2547             : 
    2548             :       // CAS-8870: Mstransform with outframe=’SOURCE’ crashes because of ephemeris type
    2549         122 :       Int firstSelectedField = selectedInputMsCols_p->fieldId()(0);
    2550         122 :       if (inputOutputFieldIndexMap_p.find(firstSelectedField) !=
    2551         244 :           inputOutputFieldIndexMap_p.end()) {
    2552          22 :         firstSelectedField = inputOutputFieldIndexMap_p[firstSelectedField];
    2553             :       }
    2554             : 
    2555             :       // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2556         122 :       if (radialVelocityCorrection_p) {
    2557           5 :         radialVelocity_p = fieldCols->radVelMeas(firstSelectedField, referenceTime_p.get("s").getValue());
    2558             : 
    2559           5 :         if (radialVelocity_p.getRef().getType() != MRadialVelocity::GEO) {
    2560           0 :           logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2561             :                    << "Cannot perform radial velocity correction with ephemerides attached "
    2562             :                    << "to first selected field " << firstSelectedField << " of type "
    2563           0 :                    << MRadialVelocity::showType(radialVelocity_p.getRef().getType())
    2564             :                    << ".\nType needs to be GEO."
    2565           0 :                    << LogIO::EXCEPTION;
    2566             :         }
    2567             : 
    2568           5 :         result = fieldCols->phaseDirMeas(firstSelectedField,referenceTime_p.get("s").getValue());
    2569             :       } else {
    2570         117 :         result = fieldCols->phaseDirMeasCol()(firstSelectedField)(IPosition(1,0));
    2571             :       }
    2572         122 :     } else {
    2573             :       // Parse phase center
    2574          25 :       if(!casaMDirection(phaseCenter, result)) {
    2575           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2576           0 :                  << "Cannot interpret phase center " << phaseCenter << LogIO::POST;
    2577             :       }
    2578             :     }
    2579         147 :   }
    2580             : 
    2581         151 :   return result;
    2582           0 : }
    2583             : 
    2584             : // -----------------------------------------------------------------------
    2585             : // Method to re-grid each SPW separately in the SPW sub-table
    2586             : // It also sets the input/output frequency arrays to be used by the interpolations
    2587             : // -----------------------------------------------------------------------
    2588          61 : void MSTransformManager::regridSpwSubTable()
    2589             : {
    2590             :   // Access Spectral Window sub-table
    2591          61 :   MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2592          61 :   auto nInputSpws = spwTable.nrow();
    2593          61 :   MSSpWindowColumns spwCols(spwTable);
    2594             : 
    2595             :   // Access columns which have to be modified
    2596          61 :   ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    2597          61 :   ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    2598          61 :   ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    2599          61 :   ArrayColumn<Double> resolutionCol = spwCols.resolution();
    2600          61 :   ScalarColumn<Int> numChanCol = spwCols.numChan();
    2601          61 :   ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
    2602          61 :   ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    2603          61 :   ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
    2604             : 
    2605             :   Int spwId;
    2606         167 :   for(rownr_t spw_idx=0; spw_idx<nInputSpws; ++spw_idx) {
    2607         107 :     if (outputInputSPWIndexMap_p.size() > 0) {
    2608          36 :       spwId = outputInputSPWIndexMap_p[spw_idx];
    2609             :     } else {
    2610          71 :       spwId = spw_idx;
    2611             :     }
    2612             : 
    2613             :     // jagonzal: Skip this SPW in non-reindex mode
    2614         107 :     if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end()))
    2615           6 :       continue;
    2616             : 
    2617         202 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2618         202 :              << "Regridding SPW with Id " <<  spwId << LogIO::POST;
    2619             : 
    2620             :     // Get input frequencies and widths
    2621         101 :     Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
    2622         101 :     Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
    2623             : 
    2624             :     // Calculate output SPW
    2625         101 :     Vector<Double> regriddedCHAN_FREQ;
    2626         101 :     Vector<Double> regriddedCHAN_WIDTH;
    2627         101 :     Vector<Double> inputCHAN_FREQ;
    2628         101 :     Vector<Double> inputCHAN_WIDTH;
    2629         101 :     regridSpwAux(spwId, MFrequency::castType(spwCols.measFreqRef()(spw_idx)),
    2630             :                  originalChanFreq, originalChanWidth,
    2631             :                  inputCHAN_FREQ, inputCHAN_WIDTH,
    2632         204 :                  regriddedCHAN_FREQ, regriddedCHAN_WIDTH, string("Input"));
    2633         100 :     spwInfo inputSpw(inputCHAN_FREQ, inputCHAN_WIDTH);
    2634         100 :     spwInfo outputSpw(regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
    2635             : 
    2636             :     // Set the output SPW characteristics in the SPW sub-table
    2637         100 :     numChanCol.put(spw_idx, outputSpw.NUM_CHAN);
    2638         100 :     chanFreqCol.put(spw_idx, outputSpw.CHAN_FREQ);
    2639         100 :     chanWidthCol.put(spw_idx, outputSpw.CHAN_WIDTH);
    2640         100 :     effectiveBWCol.put(spw_idx, outputSpw.EFFECTIVE_BW);
    2641         100 :     resolutionCol.put(spw_idx, outputSpw.RESOLUTION);
    2642         100 :     refFrequencyCol.put(spw_idx, outputSpw.REF_FREQUENCY);
    2643         100 :     totalBandwidthCol.put(spw_idx, outputSpw.TOTAL_BANDWIDTH);
    2644             : 
    2645             :     // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2646         100 :     if(outputReferenceFrame_p==MFrequency::GEO) {
    2647             :       // i.e. outframe was GEO or SOURCE
    2648           3 :       measFreqRefCol.put(spw_idx, (Int)MFrequency::REST);
    2649             :     } else {
    2650          97 :       measFreqRefCol.put(spw_idx, (Int)outputReferenceFrame_p);
    2651             :     }
    2652             : 
    2653             :     // Add input-output SPW pair to map
    2654         100 :     inputOutputSpwMap_p[spwId] = std::make_pair(inputSpw,outputSpw);
    2655             : 
    2656             :     // Prepare frequency transformation engine for the reference time
    2657         100 :     if (fftShiftEnabled_p) {
    2658           4 :       MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
    2659           4 :                                     MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2660           4 :       MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
    2661           4 :                                      MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2662           4 :       refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    2663             : 
    2664         194 :       for(uInt chan_idx=0; chan_idx < inputOutputSpwMap_p[spwId].first.CHAN_FREQ.size();
    2665             :           ++chan_idx) {
    2666         190 :         inputOutputSpwMap_p[spwId].first.CHAN_FREQ_aux[chan_idx] =
    2667         190 :           refTimeFreqTransEngine_p(inputOutputSpwMap_p[spwId].first.CHAN_FREQ[chan_idx]).
    2668         380 :           get(MSTransformations::Hz).getValue();
    2669             :       }
    2670           4 :     }
    2671         106 :   }
    2672          70 : }
    2673             : 
    2674             : // -----------------------------------------------------------------------
    2675             : // Method to combine and re-grid the SPW sub-table
    2676             : // It also sets the input/output frequency arrays to be used by the interpolations
    2677             : // -----------------------------------------------------------------------
    2678          90 : void MSTransformManager::regridAndCombineSpwSubtable()
    2679             : {
    2680             :     /// Determine input SPW structure ////////////////////
    2681             : 
    2682             :     // Access Spectral Window sub-table
    2683          90 :     MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2684          90 :     auto nInputSpws = spwTable.nrow();
    2685          90 :     MSSpWindowColumns spwCols(spwTable);
    2686             : 
    2687             :     // Access columns which have to be modified
    2688          90 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    2689          90 :     ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    2690          90 :     ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    2691          90 :     ArrayColumn<Double> resolutionCol = spwCols.resolution();
    2692          90 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    2693          90 :     ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
    2694          90 :     ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    2695          90 :     ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
    2696             : 
    2697             :     // Create list of input channels
    2698          90 :     vector<channelInfo> inputChannels;
    2699         714 :     for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    2700             :     {
    2701             :         Int spwId;
    2702         624 :                 if (outputInputSPWIndexMap_p.size())
    2703             :                 {
    2704         136 :                         spwId = outputInputSPWIndexMap_p[spw_idx];
    2705             :                 }
    2706             :                 else
    2707             :                 {
    2708         488 :                         spwId = spw_idx;
    2709             :                 }
    2710             : 
    2711             :                 // jagonzal: Skip this SPW in non-reindex mode
    2712         624 :         if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
    2713             : 
    2714         624 :         Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
    2715         624 :         Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
    2716         624 :         Vector<Double> inputEffectiveBW(effectiveBWCol(spw_idx));
    2717         624 :         Vector<Double> inputResolution(resolutionCol(spw_idx));
    2718         624 :         uInt nChannels = originalChanFreq.size();
    2719             : 
    2720       72414 :         for (uInt chan_idx=0;chan_idx<nChannels;chan_idx++)
    2721             :         {
    2722       71790 :                 channelInfo channelInfo_idx;
    2723       71790 :                 channelInfo_idx.SPW_id = spwId;
    2724             : 
    2725       71790 :                 channelInfo_idx.inpChannel = chan_idx;
    2726       71790 :                 channelInfo_idx.CHAN_FREQ = originalChanFreq(chan_idx);
    2727       71790 :                 channelInfo_idx.CHAN_WIDTH = originalChanWidth(chan_idx);
    2728       71790 :                 channelInfo_idx.EFFECTIVE_BW = inputEffectiveBW(chan_idx);
    2729       71790 :                 channelInfo_idx.RESOLUTION = inputResolution(chan_idx);
    2730             : 
    2731       71790 :                 inputChannels.push_back(channelInfo_idx);
    2732       71790 :         }
    2733         624 :     }
    2734             : 
    2735             :     // Sort input channels
    2736          90 :     sort (inputChannels.begin(), inputChannels.end());
    2737             : 
    2738             :     /// Determine combined SPW structure ///////////////////
    2739             : 
    2740             :     // Determine combined SPWs
    2741         180 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2742         180 :              << "Calculate combined SPW frequencies" << LogIO::POST;
    2743             : 
    2744          90 :     Vector<Double> combinedCHAN_FREQ;
    2745          90 :     Vector<Double> combinedCHAN_WIDTH;
    2746          90 :     std::vector<std::vector<Int> > averageWhichChan;
    2747          90 :     std::vector<std::vector<Int> > averageWhichSPW;
    2748          90 :     std::vector<std::vector<Double> > averageChanFrac;
    2749          90 :     MSTransformRegridder::combineSpws(logger_p,outMsName_p,Vector<Int>(1,-1),
    2750             :                                                                   combinedCHAN_FREQ,combinedCHAN_WIDTH,
    2751             :                                                                           averageWhichChan, averageWhichSPW, averageChanFrac, true);
    2752             : 
    2753             :         // Create list of combined channels
    2754          90 :         vector<channelInfo> combinedChannels;
    2755          90 :         uInt nCombinedChannels = combinedCHAN_FREQ.size();
    2756       61187 :         for (uInt chan_idx=0;chan_idx<nCombinedChannels;chan_idx++)
    2757             :         {
    2758       61097 :                 channelInfo channelInfo_idx;
    2759       61097 :                 channelInfo_idx.SPW_id = 0;
    2760       61097 :                 channelInfo_idx.inpChannel = chan_idx;
    2761       61097 :                 channelInfo_idx.CHAN_FREQ = combinedCHAN_FREQ(chan_idx);
    2762       61097 :                 channelInfo_idx.CHAN_WIDTH = combinedCHAN_WIDTH(chan_idx);
    2763       61097 :                 channelInfo_idx.EFFECTIVE_BW = combinedCHAN_WIDTH(chan_idx);
    2764       61097 :                 channelInfo_idx.RESOLUTION = combinedCHAN_WIDTH(chan_idx);
    2765       61097 :                 channelInfo_idx.contribFrac = averageChanFrac.at(chan_idx);
    2766       61097 :                 channelInfo_idx.contribSPW_id = averageWhichSPW.at(chan_idx);
    2767       61097 :                 channelInfo_idx.contribChannel = averageWhichChan.at(chan_idx);
    2768       61097 :                 combinedChannels.push_back(channelInfo_idx);
    2769       61097 :         }
    2770             : 
    2771             :         // create list of input overlapping channels per combined channel
    2772             :         // note combineSpws has an edge case growing channels for slight overlap on edges,
    2773             :         // there the overlap is 1 even though combchannel->overlap(inputchannel) is slightly smaller than 1
    2774          90 :         inputOutputChanFactorMap_p.clear();
    2775             : 
    2776       61187 :         for (auto combChanIter = combinedChannels.begin(); combChanIter != combinedChannels.end(); combChanIter++)
    2777             :         {
    2778      143199 :                 for (auto k = 0lu; k < combChanIter->contribFrac.size(); k++)
    2779             :                 {
    2780             :                         // combineSpws sorts spw so we need to map back to input selection to get correct input spw
    2781       82102 :                         uInt spw_idx = combChanIter->contribSPW_id[k];
    2782       82102 :                         if (outputInputSPWIndexMap_p.size())
    2783             :                         {
    2784       15631 :                                 spw_idx = outputInputSPWIndexMap_p[spw_idx];
    2785             :                         }
    2786             : 
    2787             :                         // jagonzal: Skip this SPW in non-reindex mode
    2788       82102 :                 if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
    2789             : 
    2790       82102 :                         inputOutputChanFactorMap_p[combChanIter->inpChannel].
    2791       82102 :                         push_back(channelContribution(spw_idx, combChanIter->contribChannel[k], combChanIter->inpChannel, combChanIter->contribFrac[k]));
    2792             :                 }
    2793             :         }
    2794             : 
    2795             :     /// Calculate output SPW ///////////////////////////////
    2796          90 :     Vector<Double> regriddedCHAN_FREQ;
    2797          90 :     Vector<Double> regriddedCHAN_WIDTH;
    2798          90 :     Vector<Double> inputCHAN_FREQ;
    2799          90 :     Vector<Double> inputCHAN_WIDTH;
    2800          90 :     regridSpwAux(0,inputReferenceFrame_p,combinedCHAN_FREQ,combinedCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH,regriddedCHAN_FREQ,regriddedCHAN_WIDTH,string("Combined"));
    2801          90 :     spwInfo inputSpw(inputCHAN_FREQ,inputCHAN_WIDTH);
    2802          90 :     spwInfo outputSpw(regriddedCHAN_FREQ,regriddedCHAN_WIDTH);
    2803             : 
    2804             :     /// Modify SPW subtable ////////////////////////////////
    2805             : 
    2806         180 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2807         180 :                 << "Write output SPW subtable " << LogIO::POST;
    2808             : 
    2809             :     // Delete combined SPWs (reverse to preserve row number)
    2810          90 :     uInt rowsToDelete = nInputSpws-1;
    2811         624 :     for(Int spw_idx=rowsToDelete; spw_idx>0; spw_idx--)
    2812             :     {
    2813         534 :         spwTable.removeRow(spw_idx);
    2814             :     }
    2815             : 
    2816             :     // Set the output SPW characteristics in the SPW sub-table
    2817          90 :     numChanCol.put(0,outputSpw.NUM_CHAN);
    2818          90 :     chanFreqCol.put(0, outputSpw.CHAN_FREQ);
    2819          90 :     chanWidthCol.put(0,  outputSpw.CHAN_WIDTH);
    2820          90 :     effectiveBWCol.put(0, outputSpw.EFFECTIVE_BW);
    2821          90 :     resolutionCol.put(0, outputSpw.RESOLUTION);
    2822          90 :     refFrequencyCol.put(0,outputSpw.REF_FREQUENCY);
    2823          90 :     totalBandwidthCol.put(0,outputSpw.TOTAL_BANDWIDTH);
    2824          90 :     measFreqRefCol.put(0,outputReferenceFrame_p);
    2825             : 
    2826             :     /// Add input-output SPW pair to map ///////////////////
    2827          90 :     inputOutputSpwMap_p[0] = std::make_pair(inputSpw,outputSpw);
    2828             : 
    2829             :     // Prepare frequency transformation engine for the reference time
    2830          90 :     if (fftShiftEnabled_p)
    2831             :     {
    2832           8 :         MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
    2833           8 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2834           8 :         MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
    2835           8 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2836           8 :         refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    2837             : 
    2838        1040 :         for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[0].first.CHAN_FREQ.size(); chan_idx++)
    2839             :         {
    2840        1032 :                 inputOutputSpwMap_p[0].first.CHAN_FREQ_aux[chan_idx] =
    2841        1032 :                   refTimeFreqTransEngine_p(inputOutputSpwMap_p[0].first.CHAN_FREQ[chan_idx]).
    2842        2064 :                   get(MSTransformations::Hz).getValue();
    2843             :         }
    2844           8 :     }
    2845             : 
    2846         180 :     return;
    2847          90 : }
    2848             : 
    2849             : 
    2850             : // -----------------------------------------------------------------------
    2851             : // Auxiliary method common whenever re-gridding is necessary (with or without combining
    2852             : // the SPWs). It regrids one SPW.
    2853             : // -----------------------------------------------------------------------
    2854         191 : void MSTransformManager::regridSpwAux(Int spwId, MFrequency::Types spwInputRefFrame,
    2855             :                                       Vector<Double> &originalCHAN_FREQ,
    2856             :                                       Vector<Double> &originalCHAN_WIDTH,
    2857             :                                       Vector<Double> &inputCHAN_FREQ,
    2858             :                                       Vector<Double> &inputCHAN_WIDTH,
    2859             :                                       Vector<Double> &regriddedCHAN_FREQ,
    2860             :                                       Vector<Double> &regriddedCHAN_WIDTH,
    2861             :                                       string msg)
    2862             : {
    2863             : 
    2864             :   // Print characteristics of input SPW
    2865         191 :   ostringstream oss;
    2866         191 :   oss << msg;
    2867         191 :   oss << " SPW: " << std::setw(5) << originalCHAN_FREQ.size()
    2868             :       << " channels, first channel = "
    2869         191 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2870         191 :       << originalCHAN_FREQ(0) << " Hz"
    2871             :       << ", last channel = "
    2872         191 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2873         191 :       << originalCHAN_FREQ(originalCHAN_FREQ.size() -1) << " Hz"
    2874             :       << ", first width = "
    2875         191 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2876         191 :       << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
    2877             :       << ", last width = "
    2878         191 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2879         191 :       << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
    2880             :     ;
    2881             : 
    2882         191 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
    2883             : 
    2884             :   // Apply channel average if necessary
    2885         191 :   if (freqbinMap_p.find(spwId) != freqbinMap_p.end()) {
    2886           2 :     calculateIntermediateFrequencies(spwId,originalCHAN_FREQ,originalCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH);
    2887             : 
    2888           2 :     oss.str("");
    2889           2 :     oss.clear();
    2890           2 :     oss << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
    2891             :         << " channels, first channel = "
    2892           2 :         << std::setprecision(9) << std::setw(14) << std::scientific
    2893           2 :         << inputCHAN_FREQ(0) << " Hz"
    2894             :         << ", last channel = "
    2895           2 :         << std::setprecision(9) << std::setw(14) << std::scientific
    2896           2 :         << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
    2897           4 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2898           4 :              << oss.str() << LogIO::POST;
    2899             :   } else {
    2900         189 :     numOfCombInputChanMap_p[spwId] = originalCHAN_FREQ.size();
    2901         189 :     numOfCombInterChanMap_p[spwId] = originalCHAN_FREQ.size();
    2902         189 :     inputCHAN_FREQ = originalCHAN_FREQ;
    2903         189 :     inputCHAN_WIDTH = originalCHAN_WIDTH;
    2904             :   }
    2905             : 
    2906             :   // Re-grid the output SPW to be uniform and change reference frame
    2907         382 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2908         382 :            << "Calculate frequencies in output reference frame " << LogIO::POST;
    2909             : 
    2910             :   Double weightScale;
    2911         191 :   bool ret = MSTransformRegridder::calcChanFreqs(logger_p,
    2912             :                                                  regriddedCHAN_FREQ, regriddedCHAN_WIDTH,
    2913             :                                                  weightScale, inputCHAN_FREQ,
    2914         191 :                                                  inputCHAN_WIDTH, phaseCenter_p,
    2915         191 :                                                  spwInputRefFrame, referenceTime_p,
    2916         191 :                                                  observatoryPosition_p, mode_p, nChan_p,
    2917         191 :                                                  start_p, width_p, restFrequency_p,
    2918         191 :                                                  outputReferenceFramePar_p,
    2919         191 :                                                  velocityType_p,
    2920             :                                                  true, // verbose
    2921         191 :                                                  radialVelocity_p);
    2922             : 
    2923         191 :   if (!ret) {
    2924           1 :     logger_p << LogIO::SEVERE << "calcChanFreqs failed, check input start and width parameters"
    2925           1 :              << LogIO::EXCEPTION;
    2926             :   }
    2927             : 
    2928         190 :   ostringstream oss_debug;
    2929         190 :   oss_debug << "after calcChanFreqs, phaseCenter_p=" << phaseCenter_p << endl
    2930         190 :             << " inputReferenceFrame_p=" << inputReferenceFrame_p << endl
    2931         190 :             << " referenceTime_p=" << referenceTime_p << endl
    2932         190 :             << " observatoryPosition_p=" << observatoryPosition_p << endl
    2933         190 :             << " mode_p=" << mode_p << endl
    2934         190 :             << " nChan_p=" << nChan_p << endl
    2935         190 :             << " start_p=" << start_p << endl
    2936         190 :             << " width_p=" << width_p << endl
    2937         190 :             << " restFrequency_p=" << restFrequency_p << endl
    2938         190 :             << " outputReferenceFrame_p=" << outputReferenceFrame_p << endl
    2939         190 :             << " velocityType_p=" << velocityType_p << endl
    2940         190 :             << " radialVelocity_p=" << radialVelocity_p;
    2941         380 :   logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__) <<
    2942         380 :     oss_debug.str() << LogIO::POST;
    2943             : 
    2944             :   // jagonzal (new WEIGHT/SIGMA convention in CASA 4.2.2)
    2945         190 :   if (newWeightFactorMap_p.find(spwId) == newWeightFactorMap_p.end()) {
    2946         190 :     newWeightFactorMap_p[spwId] = weightScale;
    2947             :   } else {
    2948           0 :     newWeightFactorMap_p[spwId] *= weightScale;
    2949             :   }
    2950             : 
    2951         190 :   checkAndPreaverageChannelsIfNeeded(spwId, inputCHAN_FREQ, inputCHAN_WIDTH,
    2952             :                                      originalCHAN_FREQ, originalCHAN_WIDTH,
    2953             :                                      regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
    2954             : 
    2955             :   // Print characteristics of output SPW
    2956         190 :   oss.str("");
    2957         190 :   oss.clear();
    2958         190 :   oss << "Output SPW: " << std::setw(5) << regriddedCHAN_FREQ.size()
    2959             :       << " channels, first channel = "
    2960         190 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2961         190 :       << regriddedCHAN_FREQ(0) << " Hz"
    2962             :       << ", last channel = "
    2963         190 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2964         190 :       << regriddedCHAN_FREQ(regriddedCHAN_FREQ.size()-1) << " Hz"
    2965             :       <<", first width = "
    2966         190 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2967         190 :       << regriddedCHAN_WIDTH(0) << " Hz"
    2968             :       << ", last width = "
    2969         190 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2970         190 :       << regriddedCHAN_WIDTH(regriddedCHAN_WIDTH.size()-1) << " Hz";
    2971             : 
    2972         380 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2973         380 :            << oss.str() << LogIO::POST;
    2974         191 : }
    2975             : 
    2976             : // -----------------------------------------------------------------------
    2977             : //
    2978             : // -----------------------------------------------------------------------
    2979          13 : void MSTransformManager::separateSpwSubtable()
    2980             : {
    2981          13 :         if (Table::isReadable(outputMs_p->spectralWindowTableName()) and !outputMs_p->spectralWindow().isNull())
    2982             :         {
    2983             :                 // Access Spectral Window sub-table
    2984          13 :                 MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2985             : 
    2986          13 :                 if (spwTable.nrow() > 0)
    2987             :                 {
    2988          26 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2989          26 :                                 << " Multiplexing SPECTRAL_WINDOW sub-table to take into account new SPWs " << LogIO::POST;
    2990             : 
    2991          13 :                         MSSpWindowColumns spwCols(spwTable);
    2992             : 
    2993             :                         // Access columns which have to be separated
    2994          13 :                         ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    2995          13 :                         Vector<Double> chanFreq = chanFreqCol(0);
    2996          13 :                         ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    2997          13 :                         Vector<Double> chanWidth = chanWidthCol(0);
    2998          13 :                         ArrayColumn<Double> effectiveBWCol = spwCols.chanWidth();
    2999          13 :                         Vector<Double> effectiveBW = effectiveBWCol(0);
    3000          13 :                         ArrayColumn<Double> resolutionCol = spwCols.resolution();
    3001          13 :                         Vector<Double> resolution = resolutionCol(0);
    3002             : 
    3003             :                         // Resize columns to be separated
    3004             :                         // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
    3005             :                         /*
    3006             :                         if (tailOfChansforLastSpw_p)
    3007             :                         {
    3008             :                                 uInt nInChannels = chanFreq.size();
    3009             :                                 uInt nOutChannels = nspws_p*chansPerOutputSpw_p;
    3010             :                                 uInt newChannels = nOutChannels-nInChannels;
    3011             :                                 Double lastFreq = chanFreq(chanFreq.size()-1);
    3012             :                                 Double lastWidth = chanWidth(chanFreq.size()-1);
    3013             :                                 Double lastEffectiveBW = effectiveBW(chanFreq.size()-1);
    3014             :                                 Double lastResolution = resolution(chanFreq.size()-1);
    3015             : 
    3016             :                                 chanFreq.resize(nOutChannels,true);
    3017             :                                 chanWidth.resize(nOutChannels,true);
    3018             :                                 effectiveBW.resize(nOutChannels,true);
    3019             :                                 resolution.resize(nOutChannels,true);
    3020             : 
    3021             :                                 uInt outIndex;
    3022             :                                 for (uInt newChanIdx = 0; newChanIdx<newChannels; newChanIdx++)
    3023             :                                 {
    3024             :                                         outIndex = nInChannels+newChanIdx;
    3025             :                                         chanFreq(outIndex) = lastFreq + (newChanIdx+1)*lastWidth;
    3026             :                                         chanWidth(outIndex) = lastWidth;
    3027             :                                         effectiveBW(outIndex) = lastEffectiveBW;
    3028             :                                         resolution(outIndex) = lastResolution;
    3029             :                                 }
    3030             :                         }
    3031             :                         */
    3032             : 
    3033             :                         // Calculate bandwidth per output spw
    3034          13 :                         Double totalBandwidth = chanWidth(0)*chansPerOutputSpw_p;
    3035             : 
    3036          13 :                         uInt rowIndex = 0;
    3037          72 :                         for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
    3038             :                         {
    3039             :                                 // Columns that can be just copied
    3040          59 :                                 if (rowIndex > 0)
    3041             :                                 {
    3042             :                                         // Add row
    3043          46 :                                         spwTable.addRow(1,true);
    3044             : 
    3045          46 :                                         spwCols.measFreqRef().put(rowIndex,spwCols.measFreqRef()(0));
    3046          46 :                                         spwCols.flagRow().put(rowIndex,spwCols.flagRow()(0));
    3047          46 :                                         spwCols.freqGroup().put(rowIndex,spwCols.freqGroup()(0));
    3048          46 :                                         spwCols.freqGroupName().put(rowIndex,spwCols.freqGroupName()(0));
    3049          46 :                                         spwCols.ifConvChain().put(rowIndex,spwCols.ifConvChain()(0));
    3050          46 :                                         spwCols.name().put(rowIndex,spwCols.name()(0));
    3051          46 :                                         spwCols.netSideband().put(rowIndex,spwCols.netSideband()(0));
    3052             : 
    3053             :                                         // Optional columns
    3054          46 :                                         if (MSTransformDataHandler::columnOk(spwCols.bbcNo()))
    3055             :                                         {
    3056           4 :                                                 spwCols.bbcNo().put(rowIndex,spwCols.bbcNo()(0));
    3057             :                                         }
    3058             : 
    3059          46 :                                         if (MSTransformDataHandler::columnOk(spwCols.assocSpwId()))
    3060             :                                         {
    3061           0 :                                                 spwCols.assocSpwId().put(rowIndex,spwCols.assocSpwId()(0));
    3062             :                                         }
    3063             : 
    3064          46 :                                         if (MSTransformDataHandler::columnOk(spwCols.assocNature()))
    3065             :                                         {
    3066           0 :                                                 spwCols.assocNature().put(rowIndex,spwCols.assocNature()(0));
    3067             :                                         }
    3068             : 
    3069          46 :                                         if (MSTransformDataHandler::columnOk(spwCols.bbcSideband()))
    3070             :                                         {
    3071           0 :                                                 spwCols.bbcSideband().put(rowIndex,spwCols.bbcSideband()(0));
    3072             :                                         }
    3073             : 
    3074          46 :                                         if (MSTransformDataHandler::columnOk(spwCols.dopplerId()))
    3075             :                                         {
    3076           0 :                                                 spwCols.dopplerId().put(rowIndex,spwCols.dopplerId()(0));
    3077             :                                         }
    3078             : 
    3079          46 :                     if (MSTransformDataHandler::columnOk(spwCols.receiverId()))
    3080             :                     {
    3081           0 :                         spwCols.receiverId().put(rowIndex,spwCols.receiverId()(0));
    3082             :                     }
    3083             : 
    3084          92 :                     if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
    3085          46 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION"))
    3086             :                     {
    3087           0 :                         ScalarColumn<String> swfCol(spwTable, "SDM_WINDOW_FUNCTION");
    3088           0 :                         swfCol.put(rowIndex, swfCol(0));
    3089           0 :                     }
    3090             : 
    3091          92 :                     if (spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
    3092          46 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
    3093             :                     {
    3094           0 :                         ScalarColumn<Int> snbCol(spwTable, "SDM_NUM_BIN");
    3095           0 :                         snbCol.put(rowIndex, snbCol(0));
    3096           0 :                     }
    3097             : 
    3098          92 :                     if (spwTable.tableDesc().isColumn("SDM_CORR_BIT") &&
    3099          46 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_CORR_BIT"))
    3100             :                     {
    3101           0 :                         ScalarColumn<String> corrBitCol(spwTable, "SDM_CORR_BIT");
    3102           0 :                         corrBitCol.put(rowIndex, corrBitCol(0));
    3103           0 :                     }
    3104             : 
    3105             :                                 }
    3106             : 
    3107          59 :                                 if ( (spw_i < nspws_p-1) or (tailOfChansforLastSpw_p == 0) )
    3108             :                                 {
    3109          46 :                                         Slice range(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    3110             : 
    3111             :                                         // Array columns that have to be modified
    3112          46 :                                         spwCols.chanFreq().put(rowIndex,chanFreq(range));
    3113          46 :                                         spwCols.chanWidth().put(rowIndex,chanWidth(range));
    3114          46 :                                         spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
    3115          46 :                                         spwCols.resolution().put(rowIndex,resolution(range));
    3116             : 
    3117             :                                         // Scalar columns that have to be modified
    3118          46 :                                         spwCols.numChan().put(rowIndex,chansPerOutputSpw_p);
    3119          46 :                                         spwCols.totalBandwidth().put(rowIndex,totalBandwidth);
    3120          46 :                                         spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
    3121          46 :                                 }
    3122             :                                 // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
    3123             :                                 else
    3124             :                                 {
    3125          13 :                                         Slice range(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    3126             : 
    3127             :                                         // Array columns that have to be modified
    3128          13 :                                         spwCols.chanFreq().put(rowIndex,chanFreq(range));
    3129          13 :                                         spwCols.chanWidth().put(rowIndex,chanWidth(range));
    3130          13 :                                         spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
    3131          13 :                                         spwCols.resolution().put(rowIndex,resolution(range));
    3132             : 
    3133             :                                         // Scalar columns that have to be modified
    3134          13 :                                         spwCols.numChan().put(rowIndex,tailOfChansforLastSpw_p);
    3135          13 :                                         spwCols.totalBandwidth().put(rowIndex,chanWidth(0)*tailOfChansforLastSpw_p);
    3136          13 :                                         spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
    3137             :                                 }
    3138             : 
    3139          59 :                                 rowIndex += 1;
    3140             :                         }
    3141             : 
    3142             :                         // Remove first row
    3143             :                         // spwTable.removeRow(0);
    3144          13 :                 }
    3145             :         else
    3146             :         {
    3147           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3148           0 :                                 << "SPECTRAL_WINDOW sub-table found but has no valid content" << LogIO::POST;
    3149             :         }
    3150          13 :     }
    3151             :     else
    3152             :     {
    3153           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3154           0 :                         << "SPECTRAL_WINDOW sub-table not found " << LogIO::POST;
    3155             :     }
    3156             : 
    3157          13 :         return;
    3158             : }
    3159             : 
    3160             : // -----------------------------------------------------------------------
    3161             : //
    3162             : // -----------------------------------------------------------------------
    3163          13 : void MSTransformManager::separateFeedSubtable()
    3164             : {
    3165          13 :         if (Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
    3166             :         {
    3167             :                 // Access Feed sub-table
    3168          13 :                 MSFeed feedtable = outputMs_p->feed();
    3169             : 
    3170          13 :                 if (feedtable.nrow() > 0)
    3171             :                 {
    3172          26 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3173          26 :                                 << " Multiplexing FEED sub-table to take into account new SPWs " << LogIO::POST;
    3174             : 
    3175          13 :                         MSFeedColumns feedCols(feedtable);
    3176             : 
    3177             :                     // Get original content from columns
    3178          13 :                         Array<Double> position = feedCols.position().getColumn();
    3179          13 :                         Array<Double> beamOffset = feedCols.beamOffset().getColumn();
    3180          13 :                         Array<String> polarizationType = feedCols.polarizationType().getColumn();
    3181          13 :                         Array<Complex> polResponse = feedCols.polResponse().getColumn();
    3182          13 :                         Array<Double> receptorAngle = feedCols.receptorAngle().getColumn();
    3183          13 :                         Array<Int> antennaId = feedCols.antennaId().getColumn();
    3184          13 :                         Array<Int> beamId = feedCols.beamId().getColumn();
    3185          13 :                         Array<Int> feedId = feedCols.feedId().getColumn();
    3186          13 :                         Array<Double> interval = feedCols.interval().getColumn();
    3187          13 :                         Array<Int> numReceptors = feedCols.numReceptors().getColumn();
    3188          13 :                         Array<Int> spectralWindowId = feedCols.spectralWindowId().getColumn();
    3189          13 :                         Array<Double> time = feedCols.time().getColumn();
    3190             : 
    3191             :                         // Optional columns
    3192          13 :                         Array<Double> focusLength;
    3193          13 :                         if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
    3194             :                         {
    3195           0 :                                 focusLength = feedCols.focusLength().getColumn();
    3196             :                         }
    3197             : 
    3198          13 :                         Array<Int> phasedFeedId;
    3199          13 :                         if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
    3200             :                         {
    3201           0 :                                 phasedFeedId = feedCols.phasedFeedId().getColumn();
    3202             :                         }
    3203             : 
    3204          13 :                         auto nRowsPerSpw = feedCols.spectralWindowId().nrow();
    3205          13 :                     auto rowIndex = nRowsPerSpw;
    3206          59 :                     for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3207             :                     {
    3208             :                         // Add rows
    3209          46 :                         feedtable.addRow(nRowsPerSpw);
    3210             : 
    3211             :                         // Prepare row reference object
    3212          46 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3213             : 
    3214             :                         // Reindex SPW col
    3215          46 :                         spectralWindowId = spw_i;
    3216          46 :                         feedCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3217             : 
    3218             :                         // Columns that can be just copied
    3219          46 :                         feedCols.position().putColumnCells(refRow,position);
    3220          46 :                         feedCols.beamOffset().putColumnCells(refRow,beamOffset);
    3221          46 :                         feedCols.polarizationType().putColumnCells(refRow,polarizationType);
    3222          46 :                         feedCols.polResponse().putColumnCells(refRow,polResponse);
    3223          46 :                         feedCols.receptorAngle().putColumnCells(refRow,receptorAngle);
    3224          46 :                         feedCols.antennaId().putColumnCells(refRow,antennaId);
    3225          46 :                         feedCols.beamId().putColumnCells(refRow,beamId);
    3226          46 :                         feedCols.feedId().putColumnCells(refRow,feedId);
    3227          46 :                         feedCols.interval().putColumnCells(refRow,interval);
    3228          46 :                         feedCols.numReceptors().putColumnCells(refRow,numReceptors);
    3229          46 :                         feedCols.time().putColumnCells(refRow,time);
    3230             : 
    3231             :                                 // Optional columns
    3232          46 :                         if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
    3233             :                                 {
    3234           0 :                                         feedCols.focusLength().putColumnCells(refRow,focusLength);
    3235             :                                 }
    3236             : 
    3237          46 :                         if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
    3238             :                                 {
    3239           0 :                                         feedCols.phasedFeedId().putColumnCells(refRow,phasedFeedId);
    3240             :                                 }
    3241             : 
    3242             :                         // Increment row offset
    3243          46 :                         rowIndex += nRowsPerSpw;
    3244          46 :                     }
    3245             : 
    3246          13 :                 }
    3247             :         else
    3248             :         {
    3249           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3250           0 :                                 << "FEED sub-table found but has no valid content" << LogIO::POST;
    3251             :         }
    3252          13 :     }
    3253             :     else
    3254             :     {
    3255           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3256           0 :                         << "FEED sub-table not found " << LogIO::POST;
    3257             :     }
    3258             : 
    3259          13 :         return;
    3260             : }
    3261             : 
    3262             : // -----------------------------------------------------------------------
    3263             : //
    3264             : // -----------------------------------------------------------------------
    3265          13 : void MSTransformManager::separateSourceSubtable()
    3266             : {
    3267          13 :         if (Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
    3268             :         {
    3269             :                 // Access Source sub-table
    3270          13 :                 MSSource sourcetable = outputMs_p->source();
    3271             : 
    3272          13 :                 if (sourcetable.nrow() > 0)
    3273             :                 {
    3274          26 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3275          26 :                                 << " Multiplexing SOURCE sub-table to take into account new SPWs " << LogIO::POST;
    3276             : 
    3277          13 :                         MSSourceColumns sourceCols(sourcetable);
    3278             : 
    3279             :                     // Get original content from columns
    3280          13 :                         Array<Double> direction = sourceCols.direction().getColumn();
    3281          13 :                         Array<Double> properMotion = sourceCols.properMotion().getColumn();
    3282          13 :                         Array<Int> calibrationGroup = sourceCols.calibrationGroup().getColumn();
    3283          13 :                         Array<String> code = sourceCols.code().getColumn();
    3284          13 :                         Array<Double> interval = sourceCols.interval().getColumn();
    3285          13 :                         Array<String> name = sourceCols.name().getColumn();
    3286          13 :                         Array<Int> numLines = sourceCols.numLines().getColumn();
    3287          13 :                         Array<Int> sourceId = sourceCols.sourceId().getColumn();
    3288          13 :                         Array<Int> spectralWindowId = sourceCols.spectralWindowId().getColumn();
    3289          13 :                         Array<Double> time = sourceCols.time().getColumn();
    3290             : 
    3291             :                         // Optional columns
    3292          13 :                         Array<Double> position;
    3293          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.position()))
    3294             :                         {
    3295           0 :                                 position = sourceCols.position().getColumn();
    3296             :                         }
    3297             : 
    3298          13 :                         Array<String> transition;
    3299          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.transition()))
    3300             :                         {
    3301           1 :                                 transition = sourceCols.transition().getColumn();
    3302             :                         }
    3303             : 
    3304          13 :                         Array<Double> restFrequency;
    3305          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
    3306             :                         {
    3307           1 :                                 restFrequency = sourceCols.restFrequency().getColumn();
    3308             :                         }
    3309             : 
    3310          13 :                         Array<Double> sysvel;
    3311          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
    3312             :                         {
    3313           1 :                                 sysvel = sourceCols.sysvel().getColumn();
    3314             :                         }
    3315             : 
    3316          13 :                         Array<Int> pulsarId;
    3317          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
    3318             :                         {
    3319           0 :                                 pulsarId = sourceCols.pulsarId().getColumn();
    3320             :                         }
    3321             : 
    3322          13 :                         Array<TableRecord> sourceModel;
    3323          13 :                         if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
    3324             :                         {
    3325           0 :                                 sourceModel = sourceCols.sourceModel().getColumn();
    3326             :                         }
    3327             : 
    3328             : 
    3329          13 :                         auto nRowsPerSpw = sourceCols.spectralWindowId().nrow();
    3330          13 :                     auto rowIndex = nRowsPerSpw;
    3331          59 :                     for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3332             :                     {
    3333             :                         // Add rows
    3334          46 :                         sourcetable.addRow(nRowsPerSpw);
    3335             : 
    3336             :                         // Prepare row reference object
    3337          46 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3338             : 
    3339             :                         // Re-index SPW col
    3340          46 :                         spectralWindowId = spw_i;
    3341          46 :                         sourceCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3342             : 
    3343             :                         // Columns that can be just copied
    3344          46 :                         sourceCols.direction().putColumnCells(refRow,direction);
    3345          46 :                         sourceCols.properMotion().putColumnCells(refRow,properMotion);
    3346          46 :                         sourceCols.calibrationGroup().putColumnCells(refRow,calibrationGroup);
    3347          46 :                         sourceCols.code().putColumnCells(refRow,code);
    3348          46 :                         sourceCols.interval().putColumnCells(refRow,interval);
    3349          46 :                         sourceCols.name().putColumnCells(refRow,name);
    3350          46 :                         sourceCols.numLines().putColumnCells(refRow,numLines);
    3351          46 :                         sourceCols.sourceId().putColumnCells(refRow,sourceId);
    3352          46 :                         sourceCols.time().putColumnCells(refRow,time);
    3353             : 
    3354             :                         // Optional columns
    3355          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.position()))
    3356             :                         {
    3357           0 :                                 sourceCols.position().putColumnCells(refRow,position);
    3358             :                         }
    3359             : 
    3360          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.transition()))
    3361             :                         {
    3362           3 :                                 sourceCols.transition().putColumnCells(refRow,transition);
    3363             :                         }
    3364             : 
    3365          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
    3366             :                         {
    3367           3 :                                 sourceCols.restFrequency().putColumnCells(refRow,restFrequency);
    3368             :                         }
    3369             : 
    3370          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
    3371             :                         {
    3372           3 :                                 sourceCols.sysvel().putColumnCells(refRow,sysvel);
    3373             :                         }
    3374             : 
    3375          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
    3376             :                         {
    3377           0 :                                 sourceCols.pulsarId().putColumnCells(refRow,pulsarId);
    3378             :                         }
    3379             : 
    3380          46 :                         if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
    3381             :                         {
    3382           0 :                                 sourceCols.sourceModel().putColumnCells(refRow,sourceModel);
    3383             :                         }
    3384             : 
    3385             :                         // Increment row offset
    3386          46 :                         rowIndex += nRowsPerSpw;
    3387          46 :                     }
    3388             : 
    3389          13 :                 }
    3390             :         else
    3391             :         {
    3392           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3393           0 :                                 << "SOURCE sub-table found but has no valid content" << LogIO::POST;
    3394             :         }
    3395          13 :     }
    3396             :     else
    3397             :     {
    3398           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3399           0 :                         << "SOURCE sub-table not found " << LogIO::POST;
    3400             :     }
    3401             : 
    3402          13 :         return;
    3403             : }
    3404             : 
    3405             : // -----------------------------------------------------------------------
    3406             : //
    3407             : // -----------------------------------------------------------------------
    3408          13 : void MSTransformManager::separateSyscalSubtable()
    3409             : {
    3410             : 
    3411          13 :     if (Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
    3412             :     {
    3413             :         // Access SysCal sub-table
    3414           1 :         MSSysCal syscalTable = outputMs_p->sysCal();
    3415             : 
    3416           1 :         if (syscalTable.nrow() > 0)
    3417             :         {
    3418           2 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3419           2 :                                 << " Multiplexing SYSCAL sub-table to take into account new SPWs " << LogIO::POST;
    3420             : 
    3421           1 :                 MSSysCalColumns syscalCols(syscalTable);
    3422             : 
    3423             :                         // Get original content from columns
    3424           1 :                         Array<Int> antennaId = syscalCols.antennaId().getColumn();
    3425           1 :                         Array<Int> feedId = syscalCols.feedId().getColumn();
    3426           1 :                         Array<Double> interval = syscalCols.interval().getColumn();
    3427           1 :                         Array<Int> spectralWindowId = syscalCols.spectralWindowId().getColumn();
    3428           1 :                         Array<Double> time = syscalCols.time().getColumn();
    3429             : 
    3430             :                         // Optional columns
    3431           1 :                         Array<Float> phaseDiff;
    3432           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
    3433             :                         {
    3434           0 :                                 phaseDiff = syscalCols.phaseDiff().getColumn();
    3435             :                         }
    3436             : 
    3437           1 :                         Array<bool> phaseDiffFlag;
    3438           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
    3439             :                         {
    3440           0 :                                 phaseDiffFlag = syscalCols.phaseDiffFlag().getColumn();
    3441             :                         }
    3442             : 
    3443           1 :                         Array<Float> tant;
    3444           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tant()))
    3445             :                         {
    3446           0 :                                 tant = syscalCols.tant().getColumn();
    3447             :                         }
    3448             : 
    3449           1 :                         Array<bool> tantFlag;
    3450           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
    3451             :                         {
    3452           1 :                                 tantFlag = syscalCols.tantFlag().getColumn();
    3453             :                         }
    3454             : 
    3455           1 :                         Array<Float> tantSpectrum;
    3456           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
    3457             :                         {
    3458           0 :                                 tantSpectrum = syscalCols.tantSpectrum().getColumn();
    3459             :                         }
    3460             : 
    3461           1 :                         Array<Float> tantTsys;
    3462           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
    3463             :                         {
    3464           0 :                                 tantTsys = syscalCols.tantTsys().getColumn();
    3465             :                         }
    3466             : 
    3467           1 :                         Array<bool> tantTsysFlag;
    3468           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
    3469             :                         {
    3470           1 :                                 tantTsysFlag = syscalCols.tantTsysFlag().getColumn();
    3471             :                         }
    3472             : 
    3473           1 :                         Array<Float> tantTsysSpectrum;
    3474           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
    3475             :                         {
    3476           0 :                                 tantTsysSpectrum = syscalCols.tantTsysSpectrum().getColumn();
    3477             :                         }
    3478             : 
    3479           1 :                         Array<Float> tcal;
    3480           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
    3481             :                         {
    3482           0 :                                 tcal = syscalCols.tcal().getColumn();
    3483             :                         }
    3484             : 
    3485           1 :                         Array<bool> tcalFlag;
    3486           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
    3487             :                         {
    3488           1 :                                 tcalFlag = syscalCols.tcalFlag().getColumn();
    3489             :                         }
    3490             : 
    3491           1 :                         Array<Float> tcalSpectrum;
    3492           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
    3493             :                         {
    3494           1 :                                 tcalSpectrum = syscalCols.tcalSpectrum().getColumn();
    3495             :                         }
    3496             : 
    3497           1 :                         Array<Float> trx;
    3498           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.trx()))
    3499             :                         {
    3500           0 :                                 trx = syscalCols.trx().getColumn();
    3501             :                         }
    3502             : 
    3503           1 :                         Array<bool> trxFlag;
    3504           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
    3505             :                         {
    3506           1 :                                 trxFlag = syscalCols.trxFlag().getColumn();
    3507             :                         }
    3508             : 
    3509           1 :                         Array<Float> trxSpectrum;
    3510           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
    3511             :                         {
    3512           1 :                                 trxSpectrum = syscalCols.trxSpectrum().getColumn();
    3513             :                         }
    3514             : 
    3515           1 :                         Array<Float> tsky;
    3516           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
    3517             :                         {
    3518           0 :                                 tsky = syscalCols.tsky().getColumn();
    3519             :                         }
    3520             : 
    3521           1 :                         Array<bool> tskyFlag;
    3522           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
    3523             :                         {
    3524           1 :                                 tskyFlag = syscalCols.tskyFlag().getColumn();
    3525             :                         }
    3526             : 
    3527           1 :                         Array<Float> tskySpectrum;
    3528           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
    3529             :                         {
    3530           1 :                                 tskySpectrum = syscalCols.tskySpectrum().getColumn();
    3531             :                         }
    3532             : 
    3533           1 :                         Array<Float> tsys;
    3534           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
    3535             :                         {
    3536           0 :                                 tsys = syscalCols.tsys().getColumn();
    3537             :                         }
    3538             : 
    3539           1 :                         Array<bool> tsysFlag;
    3540           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
    3541             :                         {
    3542           1 :                                 tsysFlag = syscalCols.tsysFlag().getColumn();
    3543             :                         }
    3544             : 
    3545           1 :                         Array<Float> tsysSpectrum;
    3546           1 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
    3547             :                         {
    3548           1 :                                 tsysSpectrum = syscalCols.tsysSpectrum().getColumn();
    3549             :                         }
    3550             : 
    3551             : 
    3552           1 :                         auto nRowsPerSpw = syscalCols.spectralWindowId().nrow();
    3553           1 :                         auto rowIndex = nRowsPerSpw;
    3554           4 :                         for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3555             :                         {
    3556             :                                 // Add rows
    3557           3 :                                 syscalTable.addRow(nRowsPerSpw);
    3558             : 
    3559             :                                 // Prepare row reference object
    3560           3 :                                 RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3561             : 
    3562             :                                 // Re-index SPW col
    3563           3 :                                 spectralWindowId = spw_i;
    3564           3 :                                 syscalCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3565             : 
    3566             :                                 // Columns that can be just copied
    3567           3 :                                 syscalCols.antennaId().putColumnCells(refRow,antennaId);
    3568           3 :                                 syscalCols.feedId().putColumnCells(refRow,feedId);
    3569           3 :                                 syscalCols.interval().putColumnCells(refRow,interval);
    3570           3 :                                 syscalCols.time().putColumnCells(refRow,time);
    3571             : 
    3572             :                                 // Optional columns
    3573           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
    3574             :                                 {
    3575           0 :                                         syscalCols.phaseDiff().putColumnCells(refRow,phaseDiff);
    3576             :                                 }
    3577             : 
    3578           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
    3579             :                                 {
    3580           0 :                                         syscalCols.phaseDiffFlag().putColumnCells(refRow,phaseDiffFlag);
    3581             :                                 }
    3582             : 
    3583           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tant()))
    3584             :                                 {
    3585           0 :                                         syscalCols.tant().putColumnCells(refRow,tant);
    3586             :                                 }
    3587             : 
    3588           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
    3589             :                                 {
    3590           3 :                                         syscalCols.tantFlag().putColumnCells(refRow,tantFlag);
    3591             :                                 }
    3592             : 
    3593           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
    3594             :                                 {
    3595           0 :                                         syscalCols.tantSpectrum().putColumnCells(refRow,tantSpectrum);
    3596             :                                 }
    3597             : 
    3598           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
    3599             :                                 {
    3600           0 :                                         syscalCols.tantTsys().putColumnCells(refRow,tantTsys);
    3601             :                                 }
    3602             : 
    3603           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
    3604             :                                 {
    3605           3 :                                         syscalCols.tantTsysFlag().putColumnCells(refRow,tantTsysFlag);
    3606             :                                 }
    3607             : 
    3608           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
    3609             :                                 {
    3610           0 :                                         syscalCols.tantTsysSpectrum().putColumnCells(refRow,tantTsysSpectrum);
    3611             :                                 }
    3612             : 
    3613           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
    3614             :                                 {
    3615           0 :                                         syscalCols.tcal().putColumnCells(refRow,tcal);
    3616             :                                 }
    3617             : 
    3618           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
    3619             :                                 {
    3620           3 :                                         syscalCols.tcalFlag().putColumnCells(refRow,tcalFlag);
    3621             :                                 }
    3622             : 
    3623           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
    3624             :                                 {
    3625           3 :                                         syscalCols.tcalSpectrum().putColumnCells(refRow,tcalSpectrum);
    3626             :                                 }
    3627             : 
    3628           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trx()))
    3629             :                                 {
    3630           0 :                                         syscalCols.trx().putColumnCells(refRow,trx);
    3631             :                                 }
    3632             : 
    3633           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
    3634             :                                 {
    3635           3 :                                         syscalCols.trxFlag().putColumnCells(refRow,trxFlag);
    3636             :                                 }
    3637             : 
    3638           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
    3639             :                                 {
    3640           3 :                                         syscalCols.trxSpectrum().putColumnCells(refRow,trxSpectrum);
    3641             :                                 }
    3642             : 
    3643           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
    3644             :                                 {
    3645           0 :                                         syscalCols.tsky().putColumnCells(refRow,tsky);
    3646             :                                 }
    3647             : 
    3648           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
    3649             :                                 {
    3650           3 :                                         syscalCols.tskyFlag().putColumnCells(refRow,tskyFlag);
    3651             :                                 }
    3652             : 
    3653           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
    3654             :                                 {
    3655           3 :                                         syscalCols.tskySpectrum().putColumnCells(refRow,tskySpectrum);
    3656             :                                 }
    3657             : 
    3658           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
    3659             :                                 {
    3660           0 :                                         syscalCols.tsys().putColumnCells(refRow,tsys);
    3661             :                                 }
    3662             : 
    3663           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
    3664             :                                 {
    3665           3 :                                         syscalCols.tsysFlag().putColumnCells(refRow,tsysFlag);
    3666             :                                 }
    3667             : 
    3668           3 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
    3669             :                                 {
    3670           3 :                                         syscalCols.tsysSpectrum().putColumnCells(refRow,tsysSpectrum);
    3671             :                                 }
    3672             : 
    3673             :                                 // Increment row offset
    3674           3 :                                 rowIndex += nRowsPerSpw;
    3675           3 :                         }
    3676             : 
    3677           1 :         }
    3678             :         else
    3679             :         {
    3680           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3681           0 :                                 << "SYSCAL sub-table found but has no valid content" << LogIO::POST;
    3682             :         }
    3683           1 :     }
    3684             :     else
    3685             :     {
    3686          24 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3687          24 :                         << "SYSCAL sub-table not found " << LogIO::POST;
    3688             :     }
    3689             : 
    3690          13 :         return;
    3691             : }
    3692             : 
    3693             : // -----------------------------------------------------------------------
    3694             : //
    3695             : // -----------------------------------------------------------------------
    3696          13 : void MSTransformManager::separateFreqOffsetSubtable()
    3697             : {
    3698             : 
    3699          13 :     if (Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
    3700             :     {
    3701             :         // Access SysCal sub-table
    3702           0 :         MSFreqOffset freqoffsetTable = outputMs_p->freqOffset();
    3703             : 
    3704           0 :         if (freqoffsetTable.nrow() > 0)
    3705             :         {
    3706           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3707           0 :                                                 << " Multiplexing FREQ_OFFSET sub-table to take into account new SPWs " << LogIO::POST;
    3708             : 
    3709           0 :                 MSFreqOffsetColumns freqoffsetCols(freqoffsetTable);
    3710             : 
    3711             :                 // Get original content from columns
    3712           0 :                 Array<Int> antenna1 = freqoffsetCols.antenna1().getColumn();
    3713           0 :                 Array<Int> antenna2 = freqoffsetCols.antenna2().getColumn();
    3714           0 :                 Array<Int> feedId = freqoffsetCols.feedId().getColumn();
    3715           0 :                 Array<Double> interval = freqoffsetCols.interval().getColumn();
    3716           0 :                 Array<Double> offset = freqoffsetCols.offset().getColumn();
    3717           0 :                 Array<Int> spectralWindowId = freqoffsetCols.spectralWindowId().getColumn();
    3718           0 :                 Array<Double> time = freqoffsetCols.time().getColumn();
    3719             : 
    3720             :                 // NOTE (jagonzal): FreqOffset does not have optional columns
    3721             : 
    3722           0 :                 auto nRowsPerSpw = freqoffsetCols.spectralWindowId().nrow();
    3723           0 :                 auto rowIndex = nRowsPerSpw;
    3724           0 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3725             :                 {
    3726             :                         // Add rows
    3727           0 :                         freqoffsetTable.addRow(nRowsPerSpw);
    3728             : 
    3729             :                         // Prepare row reference object
    3730           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3731             : 
    3732             :                         // Re-index SPW col
    3733           0 :                         spectralWindowId = spw_i;
    3734           0 :                         freqoffsetCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3735             : 
    3736             :                         // Columns that can be just copied
    3737           0 :                         freqoffsetCols.antenna1().putColumnCells(refRow,antenna1);
    3738           0 :                         freqoffsetCols.antenna2().putColumnCells(refRow,antenna2);
    3739           0 :                         freqoffsetCols.feedId().putColumnCells(refRow,feedId);
    3740           0 :                         freqoffsetCols.interval().putColumnCells(refRow,interval);
    3741           0 :                         freqoffsetCols.offset().putColumnCells(refRow,offset);
    3742           0 :                         freqoffsetCols.time().putColumnCells(refRow,time);
    3743             : 
    3744             :                         // Increment row offset
    3745           0 :                         rowIndex += nRowsPerSpw;
    3746           0 :                 }
    3747             : 
    3748           0 :         }
    3749             :         else
    3750             :         {
    3751           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3752           0 :                                 << "FREQ_OFFSET sub-table found but has no valid content" << LogIO::POST;
    3753             :         }
    3754           0 :     }
    3755             :     else
    3756             :     {
    3757          26 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3758          26 :                         << "FREQ_OFFSET sub-table not found " << LogIO::POST;
    3759             :     }
    3760             : 
    3761          13 :         return;
    3762             : }
    3763             : 
    3764             : // -----------------------------------------------------------------------
    3765             : //
    3766             : // -----------------------------------------------------------------------
    3767          13 : void MSTransformManager::separateCalDeviceSubtable()
    3768             : {
    3769          13 :         if (Table::isReadable(outputMs_p->tableName() + "/CALDEVICE"))
    3770             :         {
    3771           2 :                 Table subtable(outputMs_p->tableName() + "/CALDEVICE", Table::Update);
    3772             : 
    3773           2 :                 if (subtable.nrow() > 0)
    3774             :                 {
    3775           4 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3776           4 :                                 << " Multiplexing CALDEVICE sub-table to take into account new SPWs " << LogIO::POST;
    3777             : 
    3778             :                 // Get RW access to columns
    3779           2 :                         ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
    3780           2 :                         ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
    3781           2 :                         ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
    3782           2 :                         ScalarColumn<Double> timeCol(subtable, "TIME");
    3783           2 :                         ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
    3784           2 :                         ScalarColumn<Int> numCalLoadCol(subtable, "NUM_CAL_LOAD");
    3785           2 :                         ArrayColumn<String> calLoadNamesCol(subtable, "CAL_LOAD_NAMES");
    3786           2 :                         ScalarColumn<Int> numReceptorCol(subtable, "NUM_RECEPTOR");
    3787           2 :                         ArrayColumn<Float> noiseCalCol(subtable, "NOISE_CAL");
    3788           2 :                         ArrayColumn<Float> calEffCol(subtable, "CAL_EFF");
    3789           2 :                         ArrayColumn<Double> temperatureLoadCol(subtable, "TEMPERATURE_LOAD");
    3790             : 
    3791             :                 // Get original content of columns
    3792           2 :                         Array<Int> antennaId;
    3793           2 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3794           2 :                                 antennaId = antennaIdCol.getColumn();
    3795           2 :                         Array<Int> feedId;
    3796           2 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3797           2 :                                 feedId = feedIdCol.getColumn();
    3798           2 :                         Array<Int> spectralWindowId;
    3799           2 :                         if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
    3800           2 :                                 spectralWindowId = spectralWindowIdCol.getColumn();
    3801           2 :                         Array<Double> time;
    3802           2 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3803           2 :                                 time = timeCol.getColumn();
    3804           2 :                         Array<Double> interval;
    3805           2 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3806           2 :                                 interval = intervalCol.getColumn();
    3807             : 
    3808           2 :                         Array<Int> numCalLoad;
    3809           2 :                         if (MSTransformDataHandler::columnOk(numCalLoadCol))
    3810           2 :                                 numCalLoad = numCalLoadCol.getColumn();
    3811           2 :                         Array<String> calLoadNames;
    3812           2 :                         if (MSTransformDataHandler::columnOk(calLoadNamesCol))
    3813           2 :                                 calLoadNames = calLoadNamesCol.getColumn();
    3814           2 :                         Array<Int> numReceptor;
    3815           2 :                         if (MSTransformDataHandler::columnOk(numReceptorCol))
    3816           2 :                                 numReceptor = numReceptorCol.getColumn();
    3817           2 :                         Array<Float> noiseCal;
    3818           2 :                         if (MSTransformDataHandler::columnOk(noiseCalCol))
    3819           1 :                                 noiseCal = noiseCalCol.getColumn();
    3820           2 :                         Array<Float> calEff;
    3821           2 :                         if (MSTransformDataHandler::columnOk(calEffCol))
    3822           0 :                                 calEff = calEffCol.getColumn();
    3823           2 :                         Array<Double> temperatureLoad;
    3824           2 :                         if (MSTransformDataHandler::columnOk(temperatureLoadCol))
    3825           1 :                                 temperatureLoad = temperatureLoadCol.getColumn();
    3826             : 
    3827             : 
    3828           2 :                 uInt nRowsPerSpw = spectralWindowId.nelements();
    3829           2 :                 uInt rowIndex = nRowsPerSpw;
    3830           6 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3831             :                 {
    3832             :                         // Add rows
    3833           4 :                         subtable.addRow(nRowsPerSpw);
    3834             : 
    3835             :                         // Prepare row reference object
    3836           4 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3837             : 
    3838             :                         // Re-index SPW col
    3839           4 :                         spectralWindowId = spw_i;
    3840           4 :                         spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
    3841             : 
    3842             :                         // Columns that can be just copied
    3843           4 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3844           4 :                                 antennaIdCol.putColumnCells(refRow,antennaId);
    3845           4 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3846           4 :                                 feedIdCol.putColumnCells(refRow,feedId);
    3847           4 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3848           4 :                                 timeCol.putColumnCells(refRow,time);
    3849           4 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3850           4 :                                 intervalCol.putColumnCells(refRow,interval);
    3851             : 
    3852           4 :                         if (MSTransformDataHandler::columnOk(numCalLoadCol))
    3853           4 :                                 numCalLoadCol.putColumnCells(refRow,numCalLoad);
    3854           4 :                         if (MSTransformDataHandler::columnOk(calLoadNamesCol))
    3855           4 :                                 calLoadNamesCol.putColumnCells(refRow,calLoadNames);
    3856           4 :                         if (MSTransformDataHandler::columnOk(numReceptorCol))
    3857           4 :                                 numReceptorCol.putColumnCells(refRow,numReceptor);
    3858           4 :                         if (MSTransformDataHandler::columnOk(noiseCalCol))
    3859           1 :                                 noiseCalCol.putColumnCells(refRow,noiseCal);
    3860           4 :                         if (MSTransformDataHandler::columnOk(calEffCol))
    3861           0 :                                 calEffCol.putColumnCells(refRow,calEff);
    3862           4 :                         if (MSTransformDataHandler::columnOk(temperatureLoadCol))
    3863           3 :                                 temperatureLoadCol.putColumnCells(refRow,temperatureLoad);
    3864             : 
    3865             :                         // Increment row offset
    3866           4 :                         rowIndex += nRowsPerSpw;
    3867           4 :                 }
    3868             : 
    3869           2 :                 }
    3870             :                 else
    3871             :                 {
    3872           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3873           0 :                                 << "CALDEVICE sub-table found but has no valid content" << LogIO::POST;
    3874             :                 }
    3875           2 :         }
    3876             :         else
    3877             :         {
    3878          22 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3879          22 :                         << "CALDEVICE sub-table not found." << LogIO::POST;
    3880             :         }
    3881             : 
    3882          13 :         return;
    3883             : }
    3884             : 
    3885             : // -----------------------------------------------------------------------
    3886             : //
    3887             : // -----------------------------------------------------------------------
    3888          13 : void MSTransformManager::separateSysPowerSubtable()
    3889             : {
    3890          13 :         if (Table::isReadable(outputMs_p->tableName() + "/SYSPOWER"))
    3891             :         {
    3892           2 :                 Table subtable(outputMs_p->tableName() + "/SYSPOWER", Table::Update);
    3893             : 
    3894           2 :                 if (subtable.nrow() > 0)
    3895             :                 {
    3896           2 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3897           2 :                                 << " Multiplexing SYSPOWER sub-table to take into account new SPWs " << LogIO::POST;
    3898             : 
    3899             :                 // Get RW access to columns
    3900           1 :                         ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
    3901           1 :                         ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
    3902           1 :                         ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
    3903           1 :                         ScalarColumn<Double> timeCol(subtable, "TIME");
    3904           1 :                         ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
    3905           1 :                         ArrayColumn<Float> switchedDiffCol(subtable, "SWITCHED_DIFF");
    3906           1 :                         ArrayColumn<Float> switchedSumCol(subtable, "SWITCHED_SUM");
    3907           1 :                         ArrayColumn<Float> requantizerGainCol(subtable, "REQUANTIZER_GAIN");
    3908             : 
    3909             :                 // Get original content of columns
    3910           1 :                         Array<Int> antennaId;
    3911           1 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3912           1 :                                 antennaId = antennaIdCol.getColumn();
    3913           1 :                         Array<Int> feedId;
    3914           1 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3915           1 :                                 feedId = feedIdCol.getColumn();
    3916           1 :                         Array<Int> spectralWindowId;
    3917           1 :                         if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
    3918           1 :                                 spectralWindowId = spectralWindowIdCol.getColumn();
    3919           1 :                         Array<Double> time;
    3920           1 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3921           1 :                                 time = timeCol.getColumn();
    3922           1 :                         Array<Double> interval;
    3923           1 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3924           1 :                                 interval = intervalCol.getColumn();
    3925             : 
    3926           1 :                         Array<Float> switchedDiff;
    3927           1 :                         if (MSTransformDataHandler::columnOk(switchedDiffCol))
    3928           1 :                                 switchedDiff = switchedDiffCol.getColumn();
    3929           1 :                         Array<Float> switchedSum;
    3930           1 :                         if (MSTransformDataHandler::columnOk(switchedSumCol))
    3931           1 :                                 switchedSum = switchedSumCol.getColumn();
    3932           1 :                         Array<Float> requantizerGain;
    3933           1 :                         if (MSTransformDataHandler::columnOk(requantizerGainCol))
    3934           1 :                                 requantizerGain = requantizerGainCol.getColumn();
    3935             : 
    3936           1 :                 auto nRowsPerSpw = spectralWindowId.nelements();
    3937           1 :                 auto rowIndex = nRowsPerSpw;
    3938           2 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3939             :                 {
    3940             :                         // Add rows
    3941           1 :                         subtable.addRow(nRowsPerSpw);
    3942             : 
    3943             :                         // Prepare row reference object
    3944           1 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3945             : 
    3946             :                         // Re-index SPW col
    3947           1 :                         spectralWindowId = spw_i;
    3948           1 :                         spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
    3949             : 
    3950             :                         // Columns that can be just copied
    3951           1 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3952           1 :                                 antennaIdCol.putColumnCells(refRow,antennaId);
    3953           1 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3954           1 :                                 feedIdCol.putColumnCells(refRow,feedId);
    3955           1 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3956           1 :                                 timeCol.putColumnCells(refRow,time);
    3957           1 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3958           1 :                                 intervalCol.putColumnCells(refRow,interval);
    3959             : 
    3960           1 :                         if (MSTransformDataHandler::columnOk(switchedDiffCol))
    3961           1 :                                         switchedDiffCol.putColumnCells(refRow,switchedDiff);
    3962           1 :                         if (MSTransformDataHandler::columnOk(switchedSumCol))
    3963           1 :                                         switchedSumCol.putColumnCells(refRow,switchedSum);
    3964           1 :                         if (MSTransformDataHandler::columnOk(requantizerGainCol))
    3965           1 :                                         requantizerGainCol.putColumnCells(refRow,requantizerGain);
    3966             : 
    3967             :                         // Increment row offset
    3968           1 :                         rowIndex += nRowsPerSpw;
    3969           1 :                 }
    3970             : 
    3971           1 :                 }
    3972             :                 else
    3973             :                 {
    3974           2 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3975           2 :                                 << "SYSPOWER sub-table found but has no valid content" << LogIO::POST;
    3976             :                 }
    3977           2 :         }
    3978             :         else
    3979             :         {
    3980          22 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3981          22 :                         << "SYSPOWER sub-table not found." << LogIO::POST;
    3982             :         }
    3983             : 
    3984          13 :         return;
    3985             : }
    3986             : 
    3987             : // -----------------------------------------------------------------------
    3988             : // Return polarization id corresponding to polarization averaged data (Stokes I)
    3989             : // Append Polarization row if necessary
    3990             : // -----------------------------------------------------------------------
    3991           6 : Int MSTransformManager::getAveragedPolarizationId() {
    3992           6 :   logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
    3993           6 :   MSPolarizationColumns cols(outputMs_p->polarization());
    3994           6 :   Int polId = -1;
    3995           6 :   auto nrow = cols.nrow();
    3996          14 :   for (rownr_t i = 0; i < nrow; ++i) {
    3997           8 :     auto const numCorr = cols.numCorr()(i);
    3998           8 :     auto const flagRow = cols.flagRow()(i);
    3999           8 :     if (numCorr == 1 && flagRow == False) {
    4000           2 :       Vector<Int> const corrType = cols.corrType()(i);
    4001           2 :       Int const corrType0 = corrType[0];
    4002           2 :       if (Stokes::type(corrType0) == Stokes::I) {
    4003           0 :         logger_p << "Matched " << i << LogIO::POST;
    4004           0 :         polId = i;
    4005           0 :         break;
    4006             :       }
    4007           2 :     }
    4008             :   }
    4009             : 
    4010           6 :   if (polId < 0) {
    4011             :     // add new row to PolarizationTable
    4012           6 :     outputMs_p->polarization().addRow(1, False);
    4013           6 :     polId = nrow;
    4014           6 :     Matrix<Int> corrProduct(2, 1, 0);
    4015           6 :     cols.corrProduct().put(polId, corrProduct);
    4016           6 :     Vector<Int> corrType(1, Stokes::I);
    4017           6 :     cols.corrType().put(polId, corrType);
    4018           6 :     cols.flagRow().put(polId, False);
    4019           6 :     cols.numCorr().put(polId, 1);
    4020           6 :   }
    4021             : 
    4022           6 :   return polId;
    4023           6 : }
    4024             : 
    4025             : // -----------------------------------------------------------------------
    4026             : // Re-index POLARIZATION_ID's in DATA_DESCRIPTION table
    4027             : // -----------------------------------------------------------------------
    4028           6 : void MSTransformManager::reindexPolarizationIdInDataDesc(Int newPolarizationId) {
    4029           6 :   logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
    4030           6 :   logger_p << "new polid is " << newPolarizationId << LogIO::POST;
    4031           6 :   MSDataDescColumns ddcols(outputMs_p->dataDescription());
    4032           6 :   MSPolarizationColumns pcols(outputMs_p->polarization());
    4033           6 :   rownr_t nrow = ddcols.nrow();
    4034          36 :   auto __isValidType = [&](Vector<Int> const &ctype) {
    4035          68 :     return (anyEQ(ctype, (Int)Stokes::XX) && anyEQ(ctype, (Int)Stokes::YY))
    4036          68 :       || (anyEQ(ctype, (Int)Stokes::RR) && anyEQ(ctype, (Int)Stokes::LL));
    4037             :   };
    4038          44 :   for (rownr_t i = 0; i < nrow; ++i) {
    4039          38 :     Int const polarizationId = ddcols.polarizationId()(i);
    4040          38 :     Int nCorr = pcols.numCorr()(polarizationId);
    4041          38 :     Vector<Int> corrType = pcols.corrType()(polarizationId);
    4042          38 :     bool flagRow = pcols.flagRow()(polarizationId);
    4043          38 :     bool needReindex = (polarizationId != newPolarizationId) &&
    4044          76 :         (nCorr > 1) && (flagRow == False) && __isValidType(corrType);
    4045          38 :     if (needReindex) {
    4046          36 :       logger_p << "ddid " << i << " polid " << polarizationId << " needs reindex" << LogIO::POST;
    4047          36 :       ddcols.polarizationId().put(i, newPolarizationId);
    4048             :     }
    4049          38 :   }
    4050           6 : }
    4051             : 
    4052             : 
    4053             : // -----------------------------------------------------------------------
    4054             : //
    4055             : // -----------------------------------------------------------------------
    4056         190 : void MSTransformManager::checkAndPreaverageChannelsIfNeeded(Int spwId,
    4057             :                                                             Vector<Double> &inputCHAN_FREQ,
    4058             :                                                             Vector<Double> &inputCHAN_WIDTH,
    4059             : 
    4060             :                                                             const Vector<Double> &originalCHAN_FREQ,
    4061             :                                                             const Vector<Double> &originalCHAN_WIDTH,
    4062             :                                                             const Vector<Double> &regriddedCHAN_FREQ,
    4063             :                                                             const Vector<Double> &regriddedCHAN_WIDTH
    4064             :                                                             ) {
    4065             :   // Check if pre-averaging step is necessary
    4066         190 :   if (freqbinMap_p.find(spwId) == freqbinMap_p.end()) {
    4067             :     Double weightScaleDummy;
    4068         188 :     Vector<Double> tmpCHAN_FREQ;
    4069         188 :     Vector<Double> tmpCHAN_WIDTH;
    4070         376 :     MSTransformRegridder::calcChanFreqs(logger_p, tmpCHAN_FREQ, tmpCHAN_WIDTH,
    4071             :                                         weightScaleDummy, originalCHAN_FREQ,
    4072         188 :                                         originalCHAN_WIDTH, phaseCenter_p,
    4073             :                                         inputReferenceFrame_p,
    4074         188 :                                         referenceTime_p,
    4075         188 :                                         observatoryPosition_p,
    4076         376 :                                         String("channel"), -1,
    4077         376 :                                         String("0"), String("1"),
    4078         188 :                                         restFrequency_p,
    4079         188 :                                         outputReferenceFramePar_p,
    4080         188 :                                         velocityType_p, false // verbose
    4081             :                                         );
    4082             : 
    4083         188 :     Double avgCombinedWidth = 0;
    4084      119801 :     for (uInt chanIdx = 0; chanIdx < tmpCHAN_WIDTH.size(); ++chanIdx) {
    4085      119613 :       avgCombinedWidth += tmpCHAN_WIDTH(chanIdx);
    4086             :     }
    4087         188 :     avgCombinedWidth /= tmpCHAN_WIDTH.size();
    4088             : 
    4089         188 :     Double avgRegriddedWidth = 0;
    4090       50758 :     for (uInt chanIdx=0;chanIdx<regriddedCHAN_WIDTH.size();chanIdx++) {
    4091       50570 :       avgRegriddedWidth += regriddedCHAN_WIDTH(chanIdx);
    4092             :     }
    4093         188 :     avgRegriddedWidth /= regriddedCHAN_WIDTH.size();
    4094             : 
    4095         188 :     Double widthFactor = fabs(avgRegriddedWidth/avgCombinedWidth);
    4096         188 :     uInt widthFactorInt =  (uInt)floor(widthFactor + 0.001);
    4097             : 
    4098         188 :     if ((widthFactorInt >= 2) and 2*widthFactorInt <= originalCHAN_WIDTH.size()) {
    4099          23 :       if (!enableChanPreAverage_p) {
    4100          46 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4101             :                  << "Ratio between input and output width is >=2: " << avgRegriddedWidth/avgCombinedWidth
    4102             :                  << ", but not doing pre-channel average (it is disabled by "
    4103          46 :                  << "default since CASA release 5.0)." << LogIO::POST;
    4104             : 
    4105          46 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4106             :                  << "Regridding to intermediate grid ("
    4107             :                  << originalCHAN_FREQ.size()
    4108             :                  << " channels) for interpolation as in tclean when the "
    4109             :                  << " ratio between the output and input widths is >2."
    4110          46 :                  << LogIO::POST;
    4111             : 
    4112          23 :         initGridForRegridTClean(originalCHAN_FREQ, regriddedCHAN_FREQ,
    4113             :                                 regriddedCHAN_WIDTH, widthFactor);
    4114             : 
    4115             :       } else {
    4116           0 :         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    4117             :                  << "mstransform with regridms does not regrid properly for channel widths "
    4118             :           "> or = 2 x the native channel width, when using channel pre-averaging. Please "
    4119             :           "use clean or tclean for larger regridding. "
    4120           0 :                  << LogIO::POST;
    4121             : 
    4122           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4123             :                  << "Ratio between input and output width is " << avgRegriddedWidth/avgCombinedWidth
    4124           0 :                  << ", setting pre-channel average width to " << widthFactorInt << LogIO::POST;
    4125             : 
    4126           0 :         doPreAveragingBeforeRegridding(widthFactorInt, spwId,
    4127             :                                        originalCHAN_FREQ, originalCHAN_WIDTH,
    4128             :                                        inputCHAN_FREQ, inputCHAN_WIDTH);
    4129             :       }
    4130             :     }
    4131         188 :   }
    4132         190 : }
    4133             : 
    4134             : // -----------------------------------------------------------------------
    4135             : //
    4136             : // -----------------------------------------------------------------------
    4137           0 : void MSTransformManager::doPreAveragingBeforeRegridding(uInt widthFactor, Int spwId,
    4138             :                                                         const Vector<Double> &originalCHAN_FREQ,
    4139             :                                                         const Vector<Double> &originalCHAN_WIDTH,
    4140             :                                                         Vector<Double> &inputCHAN_FREQ,
    4141             :                                                         Vector<Double> &inputCHAN_WIDTH) {
    4142           0 :   channelAverage_p = true;
    4143           0 :   freqbinMap_p[spwId] = widthFactor;
    4144           0 :   newWeightFactorMap_p[spwId] /= widthFactor; // jagonzal: Remove channel width contribution to the scale factor
    4145             : 
    4146             :   // Calculate averaged frequencies
    4147           0 :   calculateIntermediateFrequencies(spwId, originalCHAN_FREQ, originalCHAN_WIDTH,
    4148             :                                    inputCHAN_FREQ, inputCHAN_WIDTH);
    4149             : 
    4150           0 :   ostringstream oss;
    4151           0 :   oss   << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
    4152             :         << " channels, first channel = "
    4153           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    4154           0 :         << inputCHAN_FREQ(0) << " Hz"
    4155             :         << ", last channel = "
    4156           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    4157           0 :         << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
    4158           0 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4159           0 :            << oss.str() << LogIO::POST;
    4160           0 : }
    4161             : 
    4162             : // -----------------------------------------------------------------------
    4163             : //
    4164             : // -----------------------------------------------------------------------
    4165           2 : void MSTransformManager::calculateIntermediateFrequencies(      Int spwId,
    4166             :                                                                                                                                 const Vector<Double> &inputChanFreq,
    4167             :                                                                                                                                 const Vector<Double> &inputChanWidth,
    4168             :                                                                                                                                 Vector<Double> &intermediateChanFreq,
    4169             :                                                                                                                                 Vector<Double> &intermediateChanWidth)
    4170             : {
    4171           2 :         uInt mumOfInterChan = inputChanFreq.size() / freqbinMap_p[spwId];
    4172           2 :         uInt lastChannelWidth = inputChanFreq.size() % freqbinMap_p[spwId];
    4173           2 :         if (lastChannelWidth > 0)
    4174             :         {
    4175           2 :                 mumOfInterChan += 1;
    4176             :         }
    4177           2 :         numOfCombInputChanMap_p[spwId] = inputChanFreq.size();
    4178           2 :         numOfCombInterChanMap_p[spwId] = mumOfInterChan;
    4179           2 :         intermediateChanFreq.resize(mumOfInterChan,false);
    4180           2 :         intermediateChanWidth.resize(mumOfInterChan,false);
    4181           2 :         simpleAverage(freqbinMap_p[spwId], inputChanFreq, intermediateChanFreq);
    4182           2 :         simpleAverage(freqbinMap_p[spwId], inputChanWidth, intermediateChanWidth);
    4183             : 
    4184          30 :         for (uInt chanIdx=0;chanIdx<mumOfInterChan;chanIdx++)
    4185             :         {
    4186          28 :                 intermediateChanWidth[chanIdx] *= freqbinMap_p[spwId];
    4187             :         }
    4188             : 
    4189           2 :         if (lastChannelWidth > 0)
    4190             :         {
    4191           2 :                 intermediateChanWidth[mumOfInterChan-1] /= freqbinMap_p[spwId];
    4192           2 :                 intermediateChanWidth[mumOfInterChan-1] *= lastChannelWidth;
    4193             :         }
    4194             : 
    4195           2 :     return;
    4196             : }
    4197             : 
    4198             : /**
    4199             :  * Create a fake grid and create a map [input channels] => [output channels]
    4200             :  * from it. This is for the tclean-like interpolation that is applied when
    4201             :  * the width of the output is > 2 x width of the inputs.
    4202             :  *
    4203             :  * Irrespective of channel widths, we want as many channels as in the
    4204             :  * original input, with their (lower) width, but projected/aligned
    4205             :  * with the output grid. As the output grid is fixed based on the
    4206             :  * first row timestamp, this only need to be done once, at init time.
    4207             :  *
    4208             :  * After this method is run, the interpolation methods can use
    4209             :  * regridTCleanChanMap_p to interpolate the tclean way.
    4210             :  *
    4211             :  * @param originalCHAN_FREQ initial input channel frequencies
    4212             :  * @param outCHAN_FREQ final output channel frequencies
    4213             :  * @param outCHAN_WIDTH final output channel widths
    4214             :  * @param widthFactor avg(output_widths) / avg(input_widths)
    4215             :  */
    4216          23 : void MSTransformManager::initGridForRegridTClean(const Vector<Double> &originalCHAN_FREQ,
    4217             :                                                  const Vector<Double> &outCHAN_FREQ,
    4218             :                                                  const Vector<Double> &outCHAN_WIDTH,
    4219             :                                                  Double widthFactor)
    4220             : {
    4221             :   // build grid with widths of the input channels but aligned with the output
    4222             :   // grid
    4223          23 :   regridTCleanCHAN_FREQ_p.resize(originalCHAN_FREQ.size());
    4224          23 :   Vector<Double> regridTCleanCHAN_WIDTH_p;
    4225          23 :   regridTCleanCHAN_WIDTH_p.resize(regridTCleanCHAN_FREQ_p.size());
    4226             : 
    4227          23 :   const auto &outputFreqs = outCHAN_FREQ;
    4228          23 :   bool negativeWidths = outputFreqs[0] > outputFreqs[outputFreqs.size()-1];
    4229             : 
    4230             :   // swap first/last if "negative width" (decreasing frequencies)
    4231          23 :   auto startIdx = negativeWidths ? (outCHAN_FREQ.size() -1) : 0;
    4232          23 :   regridTCleanCHAN_FREQ_p[0] = outCHAN_FREQ[startIdx] - outCHAN_WIDTH[startIdx]/2.;
    4233          23 :   regridTCleanCHAN_WIDTH_p[0] = outCHAN_WIDTH[startIdx] / widthFactor;
    4234          23 :   Double widthFactorIdx = static_cast<Double>(regridTCleanCHAN_FREQ_p.size()) /
    4235          23 :     outCHAN_FREQ.size();
    4236             : 
    4237       46394 :   for (size_t idx = 1; idx < regridTCleanCHAN_FREQ_p.size(); ++idx) {
    4238       46371 :     Int outIdx = static_cast<Int>(idx / widthFactorIdx);
    4239       46371 :     regridTCleanCHAN_WIDTH_p[idx] = outCHAN_WIDTH[outIdx] / widthFactorIdx;
    4240       92742 :     regridTCleanCHAN_FREQ_p[idx] = regridTCleanCHAN_FREQ_p[idx-1] +
    4241       46371 :       regridTCleanCHAN_WIDTH_p[idx];
    4242             :   }
    4243             : 
    4244             : 
    4245             :   // Build map from fake input channels => output channels
    4246          23 :   regridTCleanChanMap_p.resize(regridTCleanCHAN_FREQ_p.size());
    4247          23 :   regridTCleanChanMap_p = -1;
    4248          23 :   const auto &intermFreqs = regridTCleanCHAN_FREQ_p;
    4249          23 :   const auto &outputWidths = outCHAN_WIDTH;
    4250       46417 :   for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
    4251     3759393 :     for (uInt outIdx = 0; outIdx < outputFreqs.size(); ++outIdx) {
    4252     5974130 :       if (intermFreqs[mapIdx] >= outputFreqs[outIdx] - outputWidths[outIdx]/2. and
    4253     2214737 :           intermFreqs[mapIdx] < outputFreqs[outIdx] + outputWidths[outIdx]/2.) {
    4254       46394 :         regridTCleanChanMap_p(mapIdx) = outIdx;
    4255       46394 :         break;
    4256             :       }
    4257             :     }
    4258             :   }
    4259          23 :   regridTClean_p = true;
    4260          23 : }
    4261             : 
    4262             : // -----------------------------------------------------------------------
    4263             : // Method to set all the elements of a scalar column to a given value
    4264             : // -----------------------------------------------------------------------
    4265         189 : void MSTransformManager::reindexColumn(ScalarColumn<Int> &inputCol, Int value)
    4266             : {
    4267      781654 :         for(rownr_t idx=0; idx<inputCol.nrow(); idx++)
    4268             :         {
    4269      781465 :                 inputCol.put(idx,value);
    4270             :         }
    4271             : 
    4272         189 :         return;
    4273             : }
    4274             : 
    4275             : // -----------------------------------------------------------------------
    4276             : // Method to re-index Spectral Window column in Source sub-table
    4277             : // -----------------------------------------------------------------------
    4278          90 : void MSTransformManager::reindexSourceSubTable()
    4279             : {
    4280          90 :     if(Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
    4281             :     {
    4282             : 
    4283         180 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4284         180 :                         << "Re-indexing SOURCE sub-table" << LogIO::POST;
    4285             : 
    4286             : 
    4287          90 :         MSSource sourceSubtable = outputMs_p->source();
    4288          90 :         MSSourceColumns tableCols(sourceSubtable);
    4289          90 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4290          90 :         ScalarColumn<Int> sourceId = tableCols.sourceId();
    4291          90 :         reindexColumn(spectralWindowId,0);
    4292             : 
    4293             :         // Remove duplicates
    4294          90 :         std::vector<rownr_t> duplicateIdx;
    4295          90 :         std::vector< std::pair<uInt,uInt> > sourceIdSpwIdMap;
    4296             : 
    4297        2817 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4298             :         {
    4299        2727 :                 std::pair<uInt,uInt> sourceIdSpwId = std::make_pair(spectralWindowId(idx),sourceId(idx));
    4300             : 
    4301        2727 :                 if (std::find(sourceIdSpwIdMap.begin(),sourceIdSpwIdMap.end(),sourceIdSpwId) != sourceIdSpwIdMap.end())
    4302             :                 {
    4303        2479 :                         duplicateIdx.push_back(idx);
    4304             :                 }
    4305             :                 else
    4306             :                 {
    4307         248 :                         sourceIdSpwIdMap.push_back(sourceIdSpwId);
    4308             :                 }
    4309             :         }
    4310             : 
    4311          90 :         sourceSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4312             : 
    4313          90 :     }
    4314             :     else
    4315             :     {
    4316           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4317           0 :                         << "SOURCE sub-table not found " << LogIO::POST;
    4318             :     }
    4319             : 
    4320          90 :     return;
    4321             : }
    4322             : 
    4323             : // -----------------------------------------------------------------------
    4324             : // Method to re-index Spectral Window column in DDI sub-table
    4325             : // -----------------------------------------------------------------------
    4326          96 : void MSTransformManager::reindexDDISubTable()
    4327             : {
    4328          96 :     if(Table::isReadable(outputMs_p->dataDescriptionTableName()) and !outputMs_p->dataDescription().isNull())
    4329             :     {
    4330         192 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4331         192 :                         << "Re-indexing DDI sub-table" << LogIO::POST;
    4332             : 
    4333             :         // Access DDI sub-table
    4334          96 :         MSDataDescription ddiTable = outputMs_p->dataDescription();
    4335          96 :         MSDataDescColumns ddiCols(ddiTable);
    4336             : 
    4337             :         // Add a new row for each of the separated SPWs
    4338          96 :         uInt rowIndex = 0;
    4339         238 :       for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
    4340             :         {
    4341         142 :                 if (rowIndex > 0)
    4342             :                 {
    4343             :                         // Add row
    4344          46 :                         ddiTable.addRow(1,true);
    4345             : 
    4346             :                     // Copy polID and flagRow from the first original SPW
    4347          46 :                         ddiCols.polarizationId().put(rowIndex,ddiCols.polarizationId()(0));
    4348          46 :                         ddiCols.flagRow().put(rowIndex,ddiCols.flagRow()(0));
    4349             : 
    4350             :                         // Optional columns
    4351          46 :                         if (ddiCols.lagId().isNull()==false and ddiCols.lagId().hasContent()==true)
    4352             :                         {
    4353           0 :                                 ddiCols.lagId().put(rowIndex,ddiCols.lagId()(0));
    4354             :                         }
    4355             :                 }
    4356             : 
    4357             :                 // Set SPW id separately
    4358         142 :                 ddiCols.spectralWindowId().put(rowIndex,ddiStart_p+spw_i);
    4359             : 
    4360         142 :                 rowIndex += 1;
    4361             :         }
    4362             : 
    4363             :         // Delete the old rows
    4364          96 :         rownr_t nrowsToDelete = ddiCols.nrow()-nspws_p;
    4365          96 :         if (nrowsToDelete > 0)
    4366             :         {
    4367          90 :             rownr_t rownr = ddiCols.nrow()-1;
    4368          90 :             Vector<rownr_t> rowsToDelete(nrowsToDelete);
    4369         624 :             for(rownr_t idx=0; idx<nrowsToDelete; idx++)
    4370             :             {
    4371         534 :                 rowsToDelete(idx) = rownr;
    4372         534 :                 rownr -= 1;
    4373             :             }
    4374             : 
    4375          90 :             ddiTable.removeRow(rowsToDelete);
    4376          90 :         }
    4377             : 
    4378             : 
    4379          96 :     }
    4380             :     else
    4381             :     {
    4382           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4383           0 :                         << "DATA_DESCRIPTION sub-table not found " << LogIO::POST;
    4384             :     }
    4385          96 : }
    4386             : 
    4387             : // -----------------------------------------------------------------------
    4388             : // Method to re-index Spectral Window column in Feed sub-table
    4389             : // -----------------------------------------------------------------------
    4390           0 : void MSTransformManager::reindexFeedSubTable()
    4391             : {
    4392           0 :     if(Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
    4393             :     {
    4394           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4395           0 :                         << "Re-indexing FEED sub-table and removing duplicates" << LogIO::POST;
    4396             : 
    4397           0 :         MSFeed feedSubtable = outputMs_p->feed();
    4398           0 :         MSFeedColumns tableCols(feedSubtable);
    4399           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4400           0 :         ScalarColumn<Int> antennaId = tableCols.antennaId();
    4401           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4402           0 :         ScalarColumn<Double> time = tableCols.time();
    4403             : 
    4404             :         // Re-index SPWId to be 0
    4405           0 :         reindexColumn(spectralWindowId,0);
    4406             : 
    4407             :         // Remove duplicates
    4408           0 :         std::vector<rownr_t> duplicateIdx;
    4409           0 :         std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4410           0 :         std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4411             : 
    4412           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4413             :         {
    4414           0 :                 std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4415           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4416             : 
    4417           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4418             :                 {
    4419           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4420             :                         {
    4421           0 :                                 duplicateIdx.push_back(idx);
    4422             :                         }
    4423             :                         else
    4424             :                         {
    4425           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4426             :                         }
    4427             :                 }
    4428             :                 else
    4429             :                 {
    4430           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4431             :                 }
    4432             :         }
    4433             : 
    4434             : 
    4435           0 :         feedSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4436             : 
    4437           0 :     }
    4438             :     else
    4439             :     {
    4440           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__) <<
    4441           0 :                          "FEED sub-table not found " << LogIO::POST;
    4442             :     }
    4443             : 
    4444           0 :         return;
    4445             : }
    4446             : 
    4447             : // -----------------------------------------------------------------------
    4448             : // Method to re-index Spectral Window column in SysCal sub-table
    4449             : // -----------------------------------------------------------------------
    4450           0 : void MSTransformManager::reindexSysCalSubTable()
    4451             : {
    4452           0 :     if(Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
    4453             :     {
    4454           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4455           0 :                         << "Re-indexing SYSCAL sub-table and removing duplicates" << LogIO::POST;
    4456             : 
    4457           0 :         MSSysCal syscalSubtable = outputMs_p->sysCal();
    4458           0 :         MSSysCalColumns tableCols(syscalSubtable);
    4459           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4460           0 :         ScalarColumn<Int> antennaId = tableCols.antennaId();
    4461           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4462           0 :         ScalarColumn<Double> time = tableCols.time();
    4463             : 
    4464             :         // Re-index SPWId to be 0
    4465           0 :         reindexColumn(spectralWindowId,0);
    4466             : 
    4467             :         // Remove duplicates
    4468           0 :         std::vector<rownr_t> duplicateIdx;
    4469           0 :         std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4470           0 :         std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4471             : 
    4472           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4473             :         {
    4474           0 :                 std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4475           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4476             : 
    4477           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4478             :                 {
    4479           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4480             :                         {
    4481           0 :                                 duplicateIdx.push_back(idx);
    4482             :                         }
    4483             :                         else
    4484             :                         {
    4485           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4486             :                         }
    4487             :                 }
    4488             :                 else
    4489             :                 {
    4490           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4491             :                 }
    4492             :         }
    4493             : 
    4494           0 :         syscalSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4495             : 
    4496           0 :     }
    4497             :     else
    4498             :     {
    4499           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4500           0 :                         << "SYSCAL sub-table not found " << LogIO::POST;
    4501             :     }
    4502             : 
    4503           0 :         return;
    4504             : }
    4505             : 
    4506             : // -----------------------------------------------------------------------
    4507             : // Method to re-index Spectral Window column in FreqOffset sub-table
    4508             : // -----------------------------------------------------------------------
    4509          90 : void MSTransformManager::reindexFreqOffsetSubTable()
    4510             : {
    4511          90 :     if(Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
    4512             :     {
    4513           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4514           0 :                         << "Re-indexing FREQ_OFFSET sub-table and removing duplicates" << LogIO::POST;
    4515             : 
    4516           0 :         MSFreqOffset freqoffsetSubtable = outputMs_p->freqOffset();
    4517           0 :         MSFreqOffsetColumns tableCols(freqoffsetSubtable);
    4518           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4519           0 :         ScalarColumn<Int> antenna1 = tableCols.antenna1();
    4520           0 :         ScalarColumn<Int> antenna2 = tableCols.antenna2();
    4521           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4522           0 :         ScalarColumn<Double> time = tableCols.time();
    4523             : 
    4524             :         // Re-index SPWId to be 0
    4525           0 :         reindexColumn(spectralWindowId,0);
    4526             : 
    4527             :         // Remove duplicates
    4528           0 :         std::vector<rownr_t> duplicateIdx;
    4529           0 :         std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double > antennaFeedTimeMap;
    4530           0 :         std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double >::iterator antennaFeedTimeIter;
    4531             : 
    4532           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4533             :         {
    4534           0 :                 std::pair < std::pair<uInt,uInt> , uInt> antennaFeedPair = std::make_pair(std::make_pair(antenna1(idx),antenna2(idx)),feedId(idx));
    4535           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4536             : 
    4537           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4538             :                 {
    4539           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4540             :                         {
    4541           0 :                                 duplicateIdx.push_back(idx);
    4542             :                         }
    4543             :                         else
    4544             :                         {
    4545           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4546             :                         }
    4547             :                 }
    4548             :                 else
    4549             :                 {
    4550           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4551             :                 }
    4552             :         }
    4553             : 
    4554           0 :         freqoffsetSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4555             : 
    4556           0 :     }
    4557             :     else
    4558             :     {
    4559         180 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4560         180 :                         << "FREQ_OFFSET sub-table not found " << LogIO::POST;
    4561             :     }
    4562             : 
    4563          90 :     return;
    4564             : }
    4565             : 
    4566             : // -----------------------------------------------------------------------
    4567             : // Method to re-index Spectral Window column in a generic sub-table (with feedId, antennaId and time columns)
    4568             : // -----------------------------------------------------------------------
    4569         360 : void MSTransformManager::reindexGenericTimeDependentSubTable(const String& subtabname)
    4570             : {
    4571         360 :         if (Table::isReadable(outputMs_p->tableName() + "/" + subtabname))
    4572             :         {
    4573         294 :                 Table subtable(outputMs_p->tableName() + "/" + subtabname, Table::Update);
    4574             : 
    4575         147 :                 if (subtable.nrow() > 0)
    4576             :                 {
    4577         198 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4578             :                                 << "Re-indexing SPW column of " << subtabname
    4579         198 :                                 << " sub-table and removing duplicates " << LogIO::POST;
    4580             : 
    4581          99 :                         ScalarColumn<Int> feedId(subtable, "FEED_ID");
    4582          99 :                         ScalarColumn<Int> antennaId(subtable, "ANTENNA_ID");
    4583          99 :                         ScalarColumn<Int> spectralWindowId(subtable, "SPECTRAL_WINDOW_ID");
    4584          99 :                         ScalarColumn<Double> time(subtable, "TIME");
    4585             : 
    4586             :                 // Re-index SPWId to be 0
    4587          99 :                 reindexColumn(spectralWindowId,0);
    4588             : 
    4589             :                 // Remove duplicates
    4590          99 :                 std::vector<rownr_t> duplicateIdx;
    4591          99 :                 std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4592          99 :                 std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4593             : 
    4594      778837 :                 for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4595             :                 {
    4596      778738 :                         std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4597      778738 :                         antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4598             : 
    4599      778738 :                         if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4600             :                         {
    4601      777490 :                                 if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4602             :                                 {
    4603      389852 :                                         duplicateIdx.push_back(idx);
    4604             :                                 }
    4605             :                                 else
    4606             :                                 {
    4607      387638 :                                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4608             :                                 }
    4609             :                         }
    4610             :                         else
    4611             :                         {
    4612        1248 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4613             :                         }
    4614             :                 }
    4615             : 
    4616          99 :                 subtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4617             : 
    4618          99 :                 }
    4619             :                 else
    4620             :                 {
    4621          48 :                         if (subtabname == casacore::String("FEED"))
    4622             :                         {
    4623           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4624           0 :                                         << subtabname << " sub-table found but has no valid content" << LogIO::POST;
    4625             :                         }
    4626             :                         else
    4627             :                         {
    4628          96 :                         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4629          96 :                                         << subtabname << " sub-table found but has no valid content" << LogIO::POST;
    4630             :                         }
    4631             :                 }
    4632         147 :         }
    4633             :         else
    4634             :         {
    4635         213 :                 if (subtabname == casacore::String("FEED"))
    4636             :                 {
    4637           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4638           0 :                                 << subtabname << " sub-table not found" << LogIO::POST;
    4639             :                 }
    4640             :                 else
    4641             :                 {
    4642         426 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4643         426 :                                 << subtabname << " sub-table not found" << LogIO::POST;
    4644             :                 }
    4645             :         }
    4646             : 
    4647         360 :         return;
    4648             : }
    4649             : 
    4650             : // -----------------------------------------------------------------------
    4651             : //
    4652             : // -----------------------------------------------------------------------
    4653        1890 : void MSTransformManager::getInputNumberOfChannels()
    4654             : {
    4655             :     // Access spectral window sub-table
    4656        1890 :     MSSpectralWindow spwTable = inputMs_p->spectralWindow();
    4657        1890 :     auto nInputSpws = spwTable.nrow();
    4658        1890 :     MSSpWindowColumns spwCols(spwTable);
    4659        1890 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4660             : 
    4661             :     // Get number of output channels per input spw
    4662       19447 :     for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4663             :     {
    4664       17557 :         numOfInpChanMap_p[spw_idx] = numChanCol(spw_idx);
    4665             :     }
    4666             : 
    4667        3780 :     return;
    4668        1890 : }
    4669             : 
    4670             : // -----------------------------------------------------------------------
    4671             : //
    4672             : // -----------------------------------------------------------------------
    4673         136 : void MSTransformManager::dropNonUniformWidthChannels()
    4674             : {
    4675             :         // Access spectral window sub-table
    4676         136 :         MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    4677         136 :         auto nInputSpws = spwTable.nrow();
    4678         136 :         MSSpWindowColumns spwCols(spwTable);
    4679         136 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    4680         136 :     ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    4681         136 :     ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    4682         136 :     ArrayColumn<Double> resolutionCol = spwCols.resolution();
    4683         136 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4684         136 :     ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    4685             : 
    4686             :         uInt nChans;
    4687             :         Int spwId;
    4688        1518 :         for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4689             :         {
    4690        1382 :                 nChans = numChanCol(spw_idx);
    4691        1382 :                 Vector<Double> widthVector = chanWidthCol(spw_idx);
    4692             : 
    4693        1382 :         if (outputInputSPWIndexMap_p.size()>0)
    4694             :         {
    4695          57 :                 spwId = outputInputSPWIndexMap_p[spw_idx];
    4696             :         }
    4697             :         else
    4698             :         {
    4699        1325 :                 spwId = spw_idx;
    4700             :         }
    4701             : 
    4702             :         // Skip this SPW in non-reindex mode
    4703        1382 :         if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end())) continue;
    4704             : 
    4705             :         //logger_p << dataHandler_p->getDroppedChannelsMap() << LogIO::POST;
    4706             : 
    4707        1382 :         if (dataHandler_p->getDroppedChannelsMap().find(spwId) != dataHandler_p->getDroppedChannelsMap().end())
    4708             :         {
    4709          14 :                 vector<Int>::iterator iter;
    4710          14 :                 Double droppedWidth = 0;
    4711          14 :                 vector<Int> &droppedChannels = dataHandler_p->getDroppedChannelsMap()[spwId];
    4712          28 :                 for (iter = droppedChannels.begin(); iter != droppedChannels.end(); iter++)
    4713             :                 {
    4714          28 :                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    4715             :                                                 << "Not enough input channels to populate output channel n# "
    4716          14 :                                                 << *iter << " from SPW " << spwId << "." << endl
    4717             :                                                 << "The channel will be dropped in order to have an uniform grid."
    4718          28 :                                                 << LogIO::POST;
    4719             : 
    4720          14 :                         droppedWidth += widthVector(*iter);
    4721             :                 }
    4722             : 
    4723             :                 // Calculate final number of channels
    4724          14 :                 uInt nChansFinal = nChans-droppedChannels.size();
    4725             : 
    4726          14 :                 if (nChansFinal <= 0)
    4727             :                 {
    4728           0 :                         logger_p        << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4729             :                                                 << "Channel selection does not allow to produce any output channel with the requested width "
    4730           0 :                                                 << LogIO::POST;
    4731             : 
    4732           0 :                         throw AipsError("Channel selection does not allow to produce any output channel with the requested width ");
    4733             :                 }
    4734             : 
    4735             : 
    4736             : 
    4737          14 :                 numChanCol.put(spw_idx, nChansFinal);
    4738             : 
    4739             :                 // Total BW has to be reduced to account for the dropped channels
    4740          14 :                 totalBandwidthCol.put(spw_idx, totalBandwidthCol(spw_idx)-droppedWidth);
    4741             : 
    4742             :                 // Get current vectors
    4743          14 :                 Vector<Double> effectiveBWVector = effectiveBWCol(spw_idx);
    4744          14 :                 Vector<Double> resolutionVector = resolutionCol(spw_idx);
    4745          14 :                 Vector<Double> frequencyVector = chanFreqCol(spw_idx);
    4746             : 
    4747             :                 // Declare new vectors
    4748          14 :                 Vector<Double> newWidthVector(nChansFinal);
    4749          14 :                 Vector<Double> newEffectiveBWVector(nChansFinal);
    4750          14 :                 Vector<Double> newResolutionVector(nChansFinal);
    4751          14 :                 Vector<Double> newFrequencyVector(nChansFinal);
    4752             : 
    4753             :                 // Create a new frequency vector
    4754          14 :                 uInt finalIdx = 0;
    4755          14 :                 vector<Int>::iterator matchIdx;
    4756         302 :                 for (uInt idx=0;idx < widthVector.size(); idx++)
    4757             :                 {
    4758         288 :                         matchIdx = find (droppedChannels.begin(), droppedChannels.end(), idx);
    4759         288 :                         if (matchIdx == droppedChannels.end() )
    4760             :                         {
    4761         274 :                                 newWidthVector(finalIdx) = widthVector(idx);
    4762         274 :                                 newEffectiveBWVector(finalIdx) = effectiveBWVector(idx);
    4763         274 :                                 newResolutionVector(finalIdx) = resolutionVector(idx);
    4764         274 :                                 newFrequencyVector(finalIdx) = frequencyVector(idx);
    4765         274 :                                 finalIdx ++;
    4766             :                         }
    4767             :                 }
    4768             : 
    4769             :                 // Put new vectors in corresponding columns
    4770          14 :                 chanWidthCol.put(spw_idx, newWidthVector);
    4771          14 :                 effectiveBWCol.put(spw_idx, newEffectiveBWVector);
    4772          14 :                 resolutionCol.put(spw_idx, newResolutionVector);
    4773          14 :                 chanFreqCol.put(spw_idx, newFrequencyVector);
    4774             : 
    4775             :                 // Update output number of channels
    4776          14 :                 if (regridding_p) inputOutputSpwMap_p[spw_idx].second.resize(nChansFinal);
    4777          14 :         }
    4778        1382 :         }
    4779             : 
    4780         272 :         return;
    4781         136 : }
    4782             : 
    4783             : 
    4784             : // -----------------------------------------------------------------------
    4785             : //
    4786             : // -----------------------------------------------------------------------
    4787         144 : void MSTransformManager::getOutputNumberOfChannels()
    4788             : {
    4789         144 :         if (regridding_p or combinespws_p)
    4790             :         {
    4791           8 :                 map<uInt,uInt>::iterator iter;
    4792          18 :                 for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4793             :                 {
    4794          10 :                         if (freqbinMap_p.find(iter->first) == freqbinMap_p.end())
    4795             :                         {
    4796             :                                 // When doing only re-gridding, maybe not all SPWs require pre-averaging
    4797           8 :                                 if (not combinespws_p)
    4798             :                                 {
    4799           6 :                                         freqbinMap_p[iter->first] = 1;
    4800             :                                 }
    4801             :                                 // When combining SPWs all of them get the same freqbin
    4802             :                                 else
    4803             :                                 {
    4804           2 :                                         freqbinMap_p[iter->first] = freqbinMap_p[0];
    4805             :                                 }
    4806             :                         }
    4807             :                 }
    4808             :         }
    4809             : 
    4810             :         // Access spectral window sub-table
    4811         144 :         MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    4812         144 :     auto nInputSpws = spwTable.nrow();
    4813         144 :     MSSpWindowColumns spwCols(spwTable);
    4814         144 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4815         144 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    4816             : 
    4817         144 :     if (combinespws_p)
    4818             :     {
    4819           2 :                 map<uInt,uInt>::iterator iter;
    4820           6 :                 for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4821             :                 {
    4822             :                         // Note: This will truncate the result, but it is ok because we are dropping the last channel
    4823           4 :                         numOfOutChanMap_p[iter->first] = numOfSelChanMap_p[iter->first] / freqbinMap_p[iter->first];
    4824             :                 }
    4825             :     }
    4826             :     else
    4827             :     {
    4828             :             // Get number of output channels per input spw
    4829             :             Int spwId;
    4830        1530 :             for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4831             :             {
    4832        1388 :                 if (outputInputSPWIndexMap_p.size()>0)
    4833             :                 {
    4834          60 :                         spwId = outputInputSPWIndexMap_p[spw_idx];
    4835             :                 }
    4836             :                 else
    4837             :                 {
    4838        1328 :                         spwId = spw_idx;
    4839             :                 }
    4840             : 
    4841        1388 :                 numOfOutChanMap_p[spwId] = numChanCol(spw_idx);
    4842             :             }
    4843             :     }
    4844             : 
    4845         288 :         return;
    4846         144 : }
    4847             : 
    4848             : // -----------------------------------------------------------------------
    4849             : //
    4850             : // -----------------------------------------------------------------------
    4851           0 : void MSTransformManager::calculateWeightAndSigmaFactors()
    4852             : {
    4853           0 :         map<uInt,uInt>::iterator iter;
    4854           0 :         for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4855             :         {
    4856           0 :                 weightFactorMap_p[iter->first] = (Float)numOfSelChanMap_p[iter->first] /
    4857           0 :                                                                                 (Float)numOfInpChanMap_p[iter->first];
    4858           0 :                 sigmaFactorMap_p[iter->first] = 1./sqrt((Float)numOfSelChanMap_p[iter->first] /
    4859           0 :                                                                                 (Float)numOfOutChanMap_p[iter->first]);
    4860             :         }
    4861             : 
    4862           0 :         return;
    4863             : }
    4864             : 
    4865             : // -----------------------------------------------------------------------
    4866             : //
    4867             : // -----------------------------------------------------------------------
    4868         286 : void MSTransformManager::calculateNewWeightAndSigmaFactors()
    4869             : {
    4870             : 
    4871         286 :         map<uInt, uInt>::iterator iter;
    4872        2392 :         for (iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4873             :         {
    4874             :                 // Populateremaining SPWs of weight factor map
    4875        2106 :                 if (newWeightFactorMap_p.find(iter->first)== newWeightFactorMap_p.end())
    4876             :                 {
    4877             :                         // When doing only re-gridding, maybe not all SPWs require pre-averaging
    4878         550 :                         if (not combinespws_p)
    4879             :                         {
    4880           0 :                                 newWeightFactorMap_p[iter->first] = 1;
    4881             :                         }
    4882             :                         // When combining SPWs all of them get the same freqbin
    4883             :                         else
    4884             :                         {
    4885         550 :                                 newWeightFactorMap_p[iter->first] = newWeightFactorMap_p[0];
    4886             :                         }
    4887             :                 }
    4888             : 
    4889             :                 // Populate sigma factor map
    4890        2106 :                 newSigmaFactorMap_p[iter->first] = 1 / sqrt(newWeightFactorMap_p[iter->first]);
    4891             :         }
    4892             : 
    4893         572 :         return;
    4894             : }
    4895             : 
    4896             : // -----------------------------------------------------------------------
    4897             : // Method to check if flag category has to be filled
    4898             : // -----------------------------------------------------------------------
    4899        1864 : void MSTransformManager::checkFillFlagCategory()
    4900             : {
    4901        1864 :         inputFlagCategoryAvailable_p = false;
    4902        1864 :         if (    !selectedInputMsCols_p->flagCategory().isNull()
    4903        1864 :                         && selectedInputMsCols_p->flagCategory().isDefined(0)
    4904        5592 :                         && selectedInputMsCols_p->flagCategory()(0).shape() == 3)
    4905             :         {
    4906           0 :                 inputFlagCategoryAvailable_p = true;
    4907           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4908           0 :                                 << "Optional column FLAG_CATEGORY found in input MS will be written to output MS" << LogIO::POST;
    4909             :         }
    4910             : 
    4911        1864 :         return;
    4912             : }
    4913             : 
    4914             : // -----------------------------------------------------------------------
    4915             : // Method to check if weight spectrum column has to be filled
    4916             : // -----------------------------------------------------------------------
    4917        1864 : void MSTransformManager::checkFillWeightSpectrum()
    4918             : {
    4919        1864 :         inputWeightSpectrumAvailable_p = false;
    4920        2898 :         if (!selectedInputMsCols_p->weightSpectrum().isNull() and
    4921        1034 :             selectedInputMsCols_p->weightSpectrum().isDefined(0))
    4922             :         {
    4923         207 :                 inputWeightSpectrumAvailable_p = true;
    4924         414 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4925         414 :                                 << "Optional column WEIGHT_SPECTRUM found in input MS will be written to output MS" << LogIO::POST;
    4926             :         }
    4927        1864 : }
    4928             : 
    4929             : /**
    4930             :  * Early check for a potential issue that would prevent an MSTransform
    4931             :  * setup which looks in principle fine from running correctly. Ensures
    4932             :  * that we catch a current limitation in the underlying iterators /
    4933             :  * VI/VB2 framework whereby combinespws won't work when the number of
    4934             :  * channels is different for different SPWs.
    4935             :  *
    4936             :  * Requires that numOfInpChanMap_p be populated previously (in
    4937             :  * getInputNumberOfChannels()).
    4938             :  *
    4939             :  * @throws AipsError if combinespws is enabled and the input MS of the
    4940             :  * current configuration has different number of channels for
    4941             :  * different SPWs
    4942             :  */
    4943        1886 : void MSTransformManager::checkSPWChannelsKnownLimitation()
    4944             : {
    4945        1886 :   if (not combinespws_p)
    4946        1782 :     return;
    4947             : 
    4948         132 :   auto nSpws = inputMs_p->spectralWindow().nrow();
    4949         132 :   if (1 >= nSpws or numOfInpChanMap_p.empty() or numOfSelChanMap_p.empty())
    4950          28 :     return;
    4951             : 
    4952         104 :   auto firstNum = numOfSelChanMap_p.begin()->second;
    4953         104 :   auto diff = std::find_if(numOfSelChanMap_p.begin(), numOfSelChanMap_p.end(),
    4954         644 :                            [&firstNum](const std::pair<casacore::uInt,casacore::uInt> &other) {
    4955         644 :                              return firstNum != other.second; });
    4956             : 
    4957             : 
    4958         104 :   if (numOfSelChanMap_p.end() != diff) {
    4959           4 :     auto otherNum = diff->second;
    4960           4 :     throw AipsError("Currently the option 'combinespws' is only supported when the number "
    4961             :                     "of channels is the same for all the spw's selected. One of the SPWs "
    4962           8 :                     "selected has " + std::to_string(firstNum) + " channels, but another "
    4963          16 :                     "selected SPW has " + std::to_string(otherNum) + " channels.");
    4964             :   }
    4965             : }
    4966             : 
    4967             : /**
    4968             :  * Early check to issue a warning if the data was preaveraged
    4969             :  * by the correlator ans we are performing a further
    4970             :  * smoothing and average.
    4971             :  */
    4972        1890 : void MSTransformManager::checkCorrelatorPreaveraging()
    4973             : {
    4974        1890 :   std::string spwPreaveraged;
    4975        1890 :   if (hanningSmooth_p || channelAverage_p)
    4976             :   {
    4977         163 :     auto spwTable = inputMs_p->spectralWindow();
    4978         163 :     MSSpWindowColumns spwColumns(spwTable);
    4979         326 :     if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
    4980         163 :         spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION") &&
    4981         489 :         spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
    4982         163 :         spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
    4983             :     {
    4984           0 :       auto nrows = spwColumns.nrow();
    4985           0 :       auto effBWCol = spwColumns.effectiveBW();
    4986           0 :       auto chanWidthCol = spwColumns.chanWidth();
    4987           0 :       ScalarColumn<String> windowFunctionCol(spwTable, "SDM_WINDOW_FUNCTION");
    4988           0 :       ScalarColumn<Int> numBinCol(spwTable, "SDM_NUM_BIN");
    4989           0 :       for (size_t spwIdx = 0; spwIdx < nrows; spwIdx++)
    4990             :       {
    4991           0 :         auto numBin =  numBinCol(spwIdx);
    4992           0 :         auto windowFunction = windowFunctionCol(spwIdx);
    4993           0 :         if(windowFunction != "UNKNOWN" && numBin != 1)
    4994           0 :           spwPreaveraged += std::to_string(spwIdx)+" ";
    4995           0 :       }
    4996           0 :     }
    4997         163 :   }
    4998             : 
    4999        1890 :   if(spwPreaveraged != "")
    5000           0 :     logger_p << LogIO::WARN<<LogOrigin("MSTransformManager", __func__) <<
    5001             :         "The data has already been preaveraged by the correlator but "
    5002             :         "further smoothing or averaging has been requested. "
    5003           0 :         "Preaveraged SPWs are: "<<spwPreaveraged<<LogIO::POST;
    5004        1890 : }
    5005             : 
    5006             : // -----------------------------------------------------------------------
    5007             : //
    5008             : // -----------------------------------------------------------------------
    5009        1890 : void MSTransformManager::checkDataColumnsAvailable()
    5010             : {
    5011        1890 :         dataColumnAvailable_p = false;
    5012        1890 :         correctedDataColumnAvailable_p = false;
    5013        1890 :         modelDataColumnAvailable_p = false;
    5014             : 
    5015             : 
    5016        1890 :         floatDataColumnAvailable_p = false;
    5017        1890 :         lagDataColumnAvailable_p = false;
    5018             : 
    5019             : 
    5020             :         // DATA
    5021        1890 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::DATA)))
    5022             :         {
    5023        1394 :                 dataColumnAvailable_p = true;
    5024             :         }
    5025             : 
    5026             : 
    5027             :         // CORRECTED_DATA already exists in the input MS
    5028        1890 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::CORRECTED_DATA)))
    5029             :         {
    5030         817 :                 correctedDataColumnAvailable_p = true;
    5031             :         }
    5032             :         // CORRECTED_DATA does not exist but there is a calibration parameter set available
    5033        1073 :         else if (calibrate_p and (makeVirtualCorrectedColReal_p or bufferMode_p))
    5034             :         {
    5035           9 :                 correctedDataColumnAvailable_p = true;
    5036             :         }
    5037             :         // There is no calibration parameter set available
    5038             :         else
    5039             :         {
    5040             :                 // TODO: Inform that virtual CORRECTED_DATA is not available
    5041             : 
    5042             :                 // Unset makeVirtualModelColReal_p as virtual CORRECTED col. is not available
    5043        1064 :                 makeVirtualCorrectedColReal_p = false;
    5044             :         }
    5045             : 
    5046             :         // FLOAT_DATA
    5047        1890 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::FLOAT_DATA)))
    5048             :         {
    5049         496 :                 floatDataColumnAvailable_p = true;
    5050             :         }
    5051             : 
    5052             : 
    5053             :         // MODEL_DATA already exists in the input MS
    5054        1890 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::MODEL_DATA)))
    5055             :         {
    5056         706 :                 modelDataColumnAvailable_p = true;
    5057             :         }
    5058             :         // MODEL_DATA does not exist but there is a model available in the SOURCE sub-table
    5059             :         // MODEL_DATA should not be made real if the user does not specify it implicitly
    5060        1184 :         else if (inputMs_p->source().isColumn(MSSource::SOURCE_MODEL) and makeVirtualModelColReal_p)
    5061             :         {
    5062           1 :                 modelDataColumnAvailable_p = true;
    5063             :         }
    5064             :         // CAS-7390: Provide default MODEL_DATA in buffer mode
    5065        1183 :         else if (bufferMode_p and not floatDataColumnAvailable_p) // MODEL is not defined for SD data
    5066             :         {
    5067           0 :                 makeVirtualModelColReal_p = true;
    5068           0 :                 modelDataColumnAvailable_p = true;
    5069             :         }
    5070             :         // There is no model available in the SOURCE sub-table
    5071             :         else
    5072             :         {
    5073        1183 :                 modelDataColumnAvailable_p = false;
    5074             : 
    5075             :                 // Inform that virtual MODEL_DATA is not available
    5076        1183 :                 if (makeVirtualModelColReal_p)
    5077             :                 {
    5078           1 :                         if (bufferMode_p)
    5079             :                         {
    5080           0 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5081             :                                                 << "Requested to make virtual MODEL_DATA column available from MSTransformBuffer but"
    5082             :                                                 << "SOURCE_MODEL column is not present in SOURCE sub-table"
    5083           0 :                                                 << LogIO::POST;
    5084             :                         }
    5085             :                         else
    5086             :                         {
    5087           2 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5088             :                                                  << "Requested to make virtual MODEL_DATA column real but "
    5089             :                                                  << "SOURCE_MODEL column is not present in SOURCE sub-table"
    5090           2 :                                                  << LogIO::POST;
    5091             :                         }
    5092             :                 }
    5093             : 
    5094             :                 // Unset makeVirtualModelColReal_p as virtual MODEL col. is not available
    5095        1183 :                 makeVirtualModelColReal_p = false;
    5096             :         }
    5097             : 
    5098             : 
    5099             :         // LAG_DATA
    5100        1890 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::LAG_DATA)))
    5101             :         {
    5102           0 :                 lagDataColumnAvailable_p = true;
    5103             :         }
    5104             : 
    5105        1890 :         return;
    5106             : }
    5107             : 
    5108             : // -----------------------------------------------------------------------
    5109             : // Method to check which data columns have to be filled
    5110             : // -----------------------------------------------------------------------
    5111        1890 : void MSTransformManager::checkDataColumnsToFill()
    5112             : {
    5113        1890 :         dataColMap_p.clear();
    5114        1890 :         bool mainColSet=false;
    5115        1890 :         timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
    5116             : 
    5117        1890 :         if (datacolumn_p.contains("ALL"))
    5118             :         {
    5119         366 :                 if (dataColumnAvailable_p)
    5120             :                 {
    5121         362 :                         if (!mainColSet)
    5122             :                         {
    5123         362 :                                 mainColumn_p = MS::DATA;
    5124         362 :                                 mainColSet = true;
    5125             :                         }
    5126         362 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5127         362 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5128             : 
    5129         362 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5130         362 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5131             :                 }
    5132             : 
    5133         366 :                 if (correctedDataColumnAvailable_p)
    5134             :                 {
    5135         191 :                         if (!mainColSet)
    5136             :                         {
    5137           4 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5138           4 :                                 mainColSet = true;
    5139             :                         }
    5140         191 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
    5141         191 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5142             : 
    5143         191 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5144         191 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5145             :                 }
    5146         366 :         if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
    5147         187 :             bothDataColumnsAreOutput_p = true;
    5148             : 
    5149             : 
    5150         366 :                 if (modelDataColumnAvailable_p)
    5151             :                 {
    5152         172 :                         if (!mainColSet)
    5153             :                         {
    5154           0 :                                 mainColumn_p = MS::MODEL_DATA;
    5155           0 :                                 mainColSet = true;
    5156             :                         }
    5157         172 :                         dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
    5158         172 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5159             : 
    5160         172 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5161             : 
    5162         172 :                         if (correctedDataColumnAvailable_p)
    5163             :                         {
    5164         163 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
    5165             :                         }
    5166           9 :                         else if (dataColumnAvailable_p)
    5167             :                         {
    5168           9 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
    5169             :                         }
    5170             :                         else
    5171             :                         {
    5172           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5173             :                         }
    5174             :                 }
    5175             : 
    5176         366 :                 if (floatDataColumnAvailable_p)
    5177             :                 {
    5178           4 :                         if (!mainColSet)
    5179             :                         {
    5180           0 :                                 mainColumn_p = MS::FLOAT_DATA;
    5181           0 :                                 mainColSet = true;
    5182             :                         }
    5183           4 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5184           4 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5185             : 
    5186           4 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5187             :                 }
    5188             : 
    5189         366 :                 if (lagDataColumnAvailable_p)
    5190             :                 {
    5191           0 :                         if (!mainColSet)
    5192             :                         {
    5193           0 :                                 mainColumn_p = MS::LAG_DATA;
    5194           0 :                                 mainColSet = true;
    5195             :                         }
    5196           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5197           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5198             : 
    5199             :                         // TODO: LAG_DATA is not yet supported by TVI
    5200             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5201             :                 }
    5202             :         }
    5203        1524 :         else if (datacolumn_p.contains("DATA,MODEL,CORRECTED"))
    5204             :         {
    5205           3 :                 if (dataColumnAvailable_p)
    5206             :                 {
    5207           3 :                         if (!mainColSet)
    5208             :                         {
    5209           3 :                                 mainColumn_p = MS::DATA;
    5210           3 :                                 mainColSet = true;
    5211             :                         }
    5212           3 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5213           3 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5214             : 
    5215           3 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5216           3 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5217             :                 }
    5218             : 
    5219           3 :                 if (correctedDataColumnAvailable_p)
    5220             :                 {
    5221           3 :                         if (!mainColSet)
    5222             :                         {
    5223           0 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5224           0 :                                 mainColSet = true;
    5225             :                         }
    5226           3 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
    5227           3 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5228             : 
    5229           3 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5230           3 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5231             :                 }
    5232             : 
    5233           3 :         if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
    5234           3 :             bothDataColumnsAreOutput_p = true;
    5235           3 :                 if (modelDataColumnAvailable_p)
    5236             :                 {
    5237           3 :                         if (!mainColSet)
    5238             :                         {
    5239           0 :                                 mainColumn_p = MS::MODEL_DATA;
    5240           0 :                                 mainColSet = true;
    5241             :                         }
    5242           3 :                         dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
    5243           3 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5244             : 
    5245           3 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5246             : 
    5247           3 :                         if (correctedDataColumnAvailable_p)
    5248             :                         {
    5249           3 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
    5250             :                         }
    5251           0 :                         else if (dataColumnAvailable_p)
    5252             :                         {
    5253           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
    5254             :                         }
    5255             :                         else
    5256             :                         {
    5257           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5258             :                         }
    5259             :                 }
    5260             :         }
    5261        1521 :         else if (datacolumn_p.contains("FLOAT_DATA,DATA"))
    5262             :         {
    5263             : 
    5264           0 :                 if (dataColumnAvailable_p)
    5265             :                 {
    5266           0 :                         if (!mainColSet)
    5267             :                         {
    5268           0 :                                 mainColumn_p = MS::DATA;
    5269           0 :                                 mainColSet = true;
    5270             :                         }
    5271           0 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5272           0 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5273             : 
    5274           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5275           0 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5276             :                 }
    5277             :                 else
    5278             :                 {
    5279           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5280           0 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5281             :                 }
    5282             : 
    5283           0 :                 if (floatDataColumnAvailable_p)
    5284             :                 {
    5285           0 :                         if (!mainColSet)
    5286             :                         {
    5287           0 :                                 mainColumn_p = MS::FLOAT_DATA;
    5288           0 :                                 mainColSet = true;
    5289             :                         }
    5290           0 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5291           0 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5292             : 
    5293           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5294             :                 }
    5295             :                 else
    5296             :                 {
    5297           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5298           0 :                                         "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
    5299             :                 }
    5300             :         }
    5301        1521 :         else if (datacolumn_p.contains("FLOAT_DATA"))
    5302             :         {
    5303         462 :                 if (floatDataColumnAvailable_p)
    5304             :                 {
    5305         460 :                         if (!mainColSet)
    5306             :                         {
    5307         460 :                                 mainColumn_p = MS::FLOAT_DATA;
    5308         460 :                                 mainColSet = true;
    5309             :                         }
    5310         460 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5311         460 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5312             : 
    5313         460 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5314             :                 }
    5315             :                 else
    5316             :                 {
    5317           4 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5318           4 :                                         "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
    5319             :                 }
    5320             :         }
    5321        1059 :         else if (datacolumn_p.contains("LAG_DATA,DATA"))
    5322             :         {
    5323           0 :                 if (dataColumnAvailable_p)
    5324             :                 {
    5325           0 :                         if (!mainColSet)
    5326             :                         {
    5327           0 :                                 mainColumn_p = MS::DATA;
    5328           0 :                                 mainColSet = true;
    5329             :                         }
    5330           0 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5331           0 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5332             : 
    5333           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5334           0 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5335             :                 }
    5336             :                 else
    5337             :                 {
    5338           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5339           0 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5340             :                 }
    5341             : 
    5342           0 :                 if (lagDataColumnAvailable_p)
    5343             :                 {
    5344           0 :                         if (!mainColSet)
    5345             :                         {
    5346           0 :                                 mainColumn_p = MS::LAG_DATA;
    5347           0 :                                 mainColSet = true;
    5348             :                         }
    5349           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5350           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5351             : 
    5352             :                         // TODO: LAG_DATA is not yet supported by TVI
    5353             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5354             :                 }
    5355             :                 else
    5356             :                 {
    5357           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5358           0 :                                         "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
    5359             :                 }
    5360             :         }
    5361        1059 :         else if (datacolumn_p.contains("LAG_DATA"))
    5362             :         {
    5363           0 :                 if (lagDataColumnAvailable_p)
    5364             :                 {
    5365           0 :                         if (!mainColSet)
    5366             :                         {
    5367           0 :                                 mainColumn_p = MS::LAG_DATA;
    5368           0 :                                 mainColSet = true;
    5369             :                         }
    5370           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5371           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5372             : 
    5373             :                         // TODO: LAG_DATA is not yet supported by TVI
    5374             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5375             :                 }
    5376             :                 else
    5377             :                 {
    5378           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5379           0 :                                         "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
    5380             :                 }
    5381             :         }
    5382        1059 :         else if (datacolumn_p.contains("DATA"))
    5383             :         {
    5384         821 :                 if (dataColumnAvailable_p)
    5385             :                 {
    5386         820 :                         if (!mainColSet)
    5387             :                         {
    5388         820 :                                 mainColumn_p = MS::DATA;
    5389         820 :                                 mainColSet = true;
    5390             :                         }
    5391         820 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5392         820 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5393             : 
    5394         820 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5395         820 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5396             :                 }
    5397             :                 else
    5398             :                 {
    5399           2 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5400           2 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5401             :                 }
    5402             :         }
    5403         238 :         else if (datacolumn_p.contains("CORRECTED"))
    5404             :         {
    5405         203 :                 if (correctedDataColumnAvailable_p)
    5406             :                 {
    5407         197 :                         if (!mainColSet)
    5408             :                         {
    5409         197 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5410         197 :                                 mainColSet = true;
    5411             :                         }
    5412         197 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::DATA;
    5413         197 :                         correctedToData_p = true;
    5414         197 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5415             : 
    5416         197 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5417         197 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5418             :                 }
    5419             :                 else
    5420             :                 {
    5421          12 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5422          12 :                                         "CORRECTED_DATA column requested but not available in input MS "<< LogIO::POST;
    5423             :                 }
    5424             :         }
    5425          35 :         else if (datacolumn_p.contains("MODEL"))
    5426             :         {
    5427             : 
    5428          35 :                 if (modelDataColumnAvailable_p)
    5429             :                 {
    5430          33 :                         if (!mainColSet)
    5431             :                         {
    5432          33 :                                 mainColumn_p = MS::MODEL_DATA;
    5433          33 :                                 mainColSet = true;
    5434             :                         }
    5435             : 
    5436          33 :                         dataColMap_p[MS::MODEL_DATA] = MS::DATA;
    5437          33 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5438          33 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5439          33 :                         timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5440             :                 }
    5441             :                 else
    5442             :                 {
    5443           4 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5444           4 :                                         "MODEL_DATA column requested but not available in input MS "<< LogIO::POST;
    5445             :                 }
    5446             :         }
    5447           0 :         else if (datacolumn_p.contains("NONE") and userBufferMode_p)
    5448             :         {
    5449           0 :                 logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5450             :                                         << "No datacolumn selected in buffer mode"
    5451           0 :                                         << LogIO::POST;
    5452             :         }
    5453             :         else
    5454             :         {
    5455           0 :                 logger_p        << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    5456           0 :                                         << "Requested data column " << datacolumn_p
    5457             :                                         << " is not supported, possible choices are ALL,DATA,CORRECTED,MODEL,FLOAT_DATA,LAG_DATA"
    5458           0 :                                         << LogIO::POST;
    5459             :         }
    5460             : 
    5461        1890 :         if (produceModel_p) {
    5462           3 :             const auto colname = (MS::DATA == mainColumn_p) ? "DATA" : "CORRECTED_DATA";
    5463           6 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5464             :                      << "Will produce a MODEL_DATA column in the output MS, "
    5465             :                      << "with the fit calculated for input " << colname
    5466           6 :                      << LogIO::POST;
    5467           3 :             dataColMap_p[MS::MODEL_DATA] = mainColumn_p;
    5468             :         }
    5469             : 
    5470             :         // Add shortcuts to be used in the context of WeightSpectrum related transformations
    5471        1890 :         dataColMap::iterator iter;
    5472             : 
    5473             :         // Check if we are doing DATA
    5474        1890 :         iter = dataColMap_p.find(MS::DATA);
    5475        1890 :         if (iter != dataColMap_p.end()) doingData_p = true;
    5476             : 
    5477             :         // Check if we are doing CORRECTED_DATA
    5478        1890 :         iter = dataColMap_p.find(MS::CORRECTED_DATA);
    5479        1890 :         if (iter != dataColMap_p.end()) doingCorrected_p = true;
    5480             : 
    5481             :         // Check if we are doing MODEL_DATA
    5482        1890 :         iter = dataColMap_p.find(MS::MODEL_DATA);
    5483        1890 :         if (iter != dataColMap_p.end()) doingModel_p = true;
    5484             : 
    5485        3780 :         return;
    5486             : }
    5487             : 
    5488             : 
    5489             : // -----------------------------------------------------------------------
    5490             : //
    5491             : // -----------------------------------------------------------------------
    5492        2248 : void MSTransformManager::colCheckInfo(const String& inputColName, const String& outputColName)
    5493             : {
    5494        2248 :         if (inputMs_p->tableDesc().isColumn(inputColName))
    5495             :         {
    5496        2238 :                 if (not bufferMode_p)
    5497             :                 {
    5498        4476 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5499             :                                                 << "Adding " << outputColName << " column to output MS from input " << inputColName<< " column"
    5500        4476 :                                                 << LogIO::POST;
    5501             :                 }
    5502             :                 else
    5503             :                 {
    5504           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5505             :                                                 << inputColName << " column present in input MS will be available from MSTransformBuffer"
    5506           0 :                                                 << LogIO::POST;
    5507             :                 }
    5508             :         }
    5509             :         else
    5510             :         {
    5511          10 :                 if (not bufferMode_p)
    5512             :                 {
    5513          20 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5514             :                                                 << "Adding " << outputColName << " column to output MS from input virtual " << inputColName<< " column"
    5515          20 :                                                 << LogIO::POST;
    5516             :                 }
    5517             :                 else
    5518             :                 {
    5519           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5520             :                                                 << "Virtual " << inputColName << " column present in input MS will be available from MSTransformBuffer"
    5521           0 :                                                 << LogIO::POST;
    5522             :                 }
    5523             :         }
    5524             : 
    5525        2248 :         return;
    5526             : }
    5527             : 
    5528             : 
    5529             : // -----------------------------------------------------------------------
    5530             : // Method to determine sort columns order
    5531             : // -----------------------------------------------------------------------
    5532        1117 : void MSTransformManager::setIterationApproach()
    5533             : {
    5534        1117 :         uInt nSortColumns = 7;
    5535             : 
    5536        1117 :         if (timespan_p.contains("scan")) nSortColumns -= 1;
    5537        1117 :         if (timespan_p.contains("state")) nSortColumns -= 1;
    5538        1117 :         if (timespan_p.contains("field")) nSortColumns -= 1;
    5539        1117 :         if ((combinespws_p) || (spwAverage_p)) nSortColumns -= 1;
    5540             : 
    5541        1117 :         sortColumns_p = Block<Int>(nSortColumns);
    5542        1117 :         uInt sortColumnIndex = 0;
    5543             : 
    5544        1117 :         sortColumns_p[0] = MS::OBSERVATION_ID;
    5545        1117 :         sortColumnIndex += 1;
    5546             : 
    5547        1117 :         sortColumns_p[1] = MS::ARRAY_ID;
    5548        1117 :         sortColumnIndex += 1;
    5549             : 
    5550        1117 :         if (!timespan_p.contains("scan"))
    5551             :         {
    5552        1063 :                 sortColumns_p[sortColumnIndex] =  MS::SCAN_NUMBER;
    5553        1063 :                 sortColumnIndex += 1;
    5554             :         }
    5555             :         else
    5556             :         {
    5557         108 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5558         108 :                                 << "Combining data through scans for time average " << LogIO::POST;
    5559             :         }
    5560             : 
    5561        1117 :         if (!timespan_p.contains("state"))
    5562             :         {
    5563        1110 :                 sortColumns_p[sortColumnIndex] =  MS::STATE_ID;
    5564        1110 :                 sortColumnIndex += 1;
    5565             :         }
    5566             :         else
    5567             :         {
    5568          14 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5569          14 :                                 << "Combining data through state for time average" << LogIO::POST;
    5570             :         }
    5571             : 
    5572        1117 :         if (!timespan_p.contains("field"))
    5573             :         {
    5574        1117 :                 sortColumns_p[sortColumnIndex] =  MS::FIELD_ID;
    5575        1117 :                 sortColumnIndex += 1;
    5576             :         }
    5577             :         else
    5578             :         {
    5579           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5580           0 :                                 << "Combining data through field time average" << LogIO::POST;
    5581             :         }
    5582             : 
    5583        1117 :         if ((!combinespws_p) && (!spwAverage_p))
    5584             :         {
    5585        1027 :                 sortColumns_p[sortColumnIndex] =  MS::DATA_DESC_ID;
    5586        1027 :                 sortColumnIndex += 1;
    5587             :         }
    5588             :         else
    5589             :         {
    5590         180 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5591         180 :                                 << "Combining data from selected spectral windows" << LogIO::POST;
    5592             :         }
    5593             : 
    5594        1117 :         sortColumns_p[sortColumnIndex] =  MS::TIME;
    5595             : 
    5596        1117 :         return;
    5597             : }
    5598             : 
    5599             : 
    5600             : // -----------------------------------------------------------------------
    5601             : // Method to generate the initial iterator
    5602             : // -----------------------------------------------------------------------
    5603        1863 : void MSTransformManager::generateIterator()
    5604             : {
    5605        1863 :         bool isWritable = false;
    5606        1863 :         if (interactive_p) isWritable = true;
    5607             : 
    5608             :         // Prepare time average parameters (common for all cases)
    5609        1863 :         std::shared_ptr<vi::AveragingParameters> timeavgParams = nullptr;
    5610        1863 :         if (timeAverage_p)
    5611             :         {
    5612         202 :                 if (maxuvwdistance_p > 0)
    5613             :                 {
    5614           1 :                         timeAvgOptions_p |= vi::AveragingOptions::BaselineDependentAveraging;
    5615             :                 }
    5616             : 
    5617             :                 timeavgParams = std::make_shared<vi::AveragingParameters>
    5618         404 :                     (timeBin_p, .0, vi::SortColumns(sortColumns_p, false),
    5619         606 :                      timeAvgOptions_p, maxuvwdistance_p, nullptr, isWritable, dx_p, dy_p);
    5620             :         }
    5621             : 
    5622             :         // Calibrating VI
    5623        1863 :         if (uvcontsub_p)
    5624             :         {
    5625             :                 // First determine number of layers
    5626          54 :                 uInt nTVIs = 1;
    5627          54 :                 if (timeAverage_p) nTVIs++;
    5628          54 :                 if (uvcontsub_p) nTVIs++;
    5629             : 
    5630             :                 // Init vector of TVI factories and populate it
    5631          54 :                 uInt TVIFactoryIdx = 0;
    5632          54 :                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5633             : 
    5634             :                 // Data layer
    5635          54 :                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5636          54 :                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5637          54 :                 TVIFactories[TVIFactoryIdx]=&dataLayerTVIFactory;
    5638          54 :                 TVIFactoryIdx++;
    5639             : 
    5640             :                 // Time avg. layer
    5641          54 :                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5642          54 :                 if (timeAverage_p)
    5643             :                 {
    5644           0 :                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5645           0 :                         TVIFactories[TVIFactoryIdx]=timeAverageTVIFactory.get();
    5646           0 :                         TVIFactoryIdx++;
    5647             :                 }
    5648             : 
    5649             :                 // UVContSub layer
    5650          54 :                 std::unique_ptr<vi::UVContSubTVILayerFactory> uvContSubTVIFactory;
    5651          54 :                 if (uvcontsub_p)
    5652             :                 {
    5653             :                         // needed for warning to prevent confusion with old uvcontsub!
    5654          54 :                         uvcontsubRec_p.define("allowed_spws", spwSelection_p);
    5655          54 :                         uvContSubTVIFactory.reset(new vi::UVContSubTVILayerFactory (uvcontsubRec_p));
    5656          54 :                         TVIFactories[TVIFactoryIdx]=uvContSubTVIFactory.get();
    5657          54 :                         TVIFactoryIdx++;
    5658             :                 }
    5659             : 
    5660          54 :                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5661             : 
    5662          88 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5663          88 :                                 << "TVI chain is " << visibilityIterator_p->ViiType() << LogIO::POST;
    5664          94 :         }
    5665        1809 :         else if (calibrate_p || scalarAverage_p)
    5666             :         {
    5667             :                 try
    5668             :                 {
    5669             :                         // Isolate iteration parameters
    5670           9 :                         vi::IteratingParameters iterpar;
    5671           9 :                         if (scalarAverage_p)
    5672           0 :                                 iterpar = vi::IteratingParameters(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5673             :                         else
    5674           9 :                                 iterpar = vi::IteratingParameters(0,vi::SortColumns(sortColumns_p, false));
    5675             : 
    5676             :                         // By callib String
    5677           9 :                         if (callib_p.length() > 0)
    5678             :                         {
    5679           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    5680             :                                         << "OTF calibration activated, using calibration file spec to generate iterator"
    5681           0 :                                         << LogIO::POST;
    5682             : 
    5683           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callib_p, timeavgParams.get()));
    5684             :                         }
    5685             :                         // By callib Record
    5686           9 :                         else if (callibRec_p.nfields() > 0)
    5687             :                         {
    5688          18 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    5689             :                                         << "OTF calibration activated, using calibration record spec to generate iterator"
    5690          18 :                                         << LogIO::POST;
    5691             : 
    5692           9 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callibRec_p, timeavgParams.get()));
    5693             :                         }
    5694             :                         else // scalar
    5695             :                         {
    5696           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar));
    5697             :                         }
    5698           9 :                 }
    5699           0 :                 catch (MSSelectionError x)
    5700             :                 {
    5701           0 :                         delete visibilityIterator_p;
    5702             : 
    5703           0 :                         correctedDataColumnAvailable_p = false;
    5704           0 :                         checkDataColumnsToFill();
    5705             : 
    5706             :                         // Averaging VI
    5707           0 :                         if (timeAverage_p && !tviphaseshift_p)
    5708             :                         {
    5709           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
    5710             :                         }
    5711             :                         // Polarization Averaging VI
    5712           0 :                         else if (polAverage_p) {
    5713           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
    5714           0 :                                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5715             :                         }
    5716             :                         // Pointings Interpolator VI
    5717           0 :                         else if (pointingsInterpolation_p) {
    5718           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
    5719           0 :                                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5720             :                         }
    5721             :                         // CAS-12706 To run phase shift via a TVI which has
    5722             :                         // support for shifting across large offset/angles
    5723           0 :                         else if (tviphaseshift_p) {
    5724             : 
    5725             :                                 // First determine number of layers
    5726           0 :                                 uInt nTVIs = (timeAverage_p ? 3 : 2);
    5727             : 
    5728             :                                 // Init vector of TVI factories and populate it
    5729           0 :                                 uInt TVIFactoryIdx = 0;
    5730           0 :                                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5731             : 
    5732             :                                 // Data layer
    5733           0 :                                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5734           0 :                                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5735           0 :                                 TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
    5736             : 
    5737             :                                 // Time avg. layer
    5738           0 :                                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5739           0 :                                 if (timeAverage_p)
    5740             :                                 {
    5741           0 :                                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5742           0 :                                         TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
    5743             :                                 }
    5744             : 
    5745             :                                 // Phaseshift layer
    5746           0 :                                 vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
    5747           0 :                                 TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
    5748             : 
    5749           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5750           0 :                         }
    5751             :                         // Plain VI
    5752             :                         else
    5753             :                         {
    5754           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
    5755           0 :                                                                                                                                         isWritable, NULL, timeBin_p);
    5756             :                         }
    5757           0 :                 }
    5758           0 :                 catch (AipsError x)
    5759             :                 {
    5760           0 :                         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    5761             :                                 << "Error initializing calibration VI: " << x.getMesg()
    5762           0 :                                 << LogIO::POST;
    5763           0 :                         throw(x);
    5764           0 :                 }
    5765           9 :         }
    5766             :         // Averaging VI
    5767        1800 :         else if (timeAverage_p && !tviphaseshift_p)
    5768             :         {
    5769         202 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
    5770             :         }
    5771             :         // Polarization Averaging VI
    5772        1598 :         else if (polAverage_p) {
    5773          12 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
    5774          18 :                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5775             :         }
    5776             :         // VI interpolating pointing directions
    5777        1592 :         else if (pointingsInterpolation_p) {
    5778           0 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
    5779           0 :                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5780             :         }
    5781             :         // CAS-12706 To run phase shift via a TVI which has
    5782             :         // support for shifting across large offset/angles
    5783        1592 :         else if (tviphaseshift_p) {
    5784             : 
    5785             :                 // First determine number of layers
    5786          79 :                 uInt nTVIs = (timeAverage_p ? 3 : 2);
    5787             : 
    5788             :                 // Init vector of TVI factories and populate it
    5789          79 :                 uInt TVIFactoryIdx = 0;
    5790          79 :                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5791             : 
    5792             :                 // Data layer
    5793          79 :                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5794          79 :                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5795          79 :                 TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
    5796             : 
    5797             :                 // Time avg. layer
    5798          79 :                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5799          79 :                 if (timeAverage_p)
    5800             :                 {
    5801           0 :                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5802           0 :                         TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
    5803             :                 }
    5804             : 
    5805             :                 // Phaseshift layer
    5806          79 :                 vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
    5807          79 :                 TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
    5808             : 
    5809          79 :                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5810          79 :     }
    5811             :     // Offline ATM correction
    5812        1513 :         else if (doAtmCor_p) {
    5813          56 :                 visibilityIterator_p = new vi::VisibilityIterator2(
    5814          28 :                         vi::SDAtmosphereCorrectionVi2Factory(
    5815          56 :                                 atmCorConfig_p, selectedInputMs_p, vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable
    5816             :                         )
    5817          28 :                 );
    5818             :         }
    5819             :         // Plain VI
    5820             :         else
    5821             :         {
    5822        2970 :                 visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
    5823        1485 :                                                                                                                         isWritable, NULL, timeBin_p);
    5824             :         }
    5825             : 
    5826        1853 :         if (timeAverage_p) visibilityIterator_p->setWeightScaling(vi::WeightScaling::generateUnityWeightScaling());
    5827        1853 :         if (channelSelector_p != NULL) visibilityIterator_p->setFrequencySelection(*channelSelector_p);
    5828             : 
    5829        3706 :         return;
    5830        1863 : }
    5831             : 
    5832             : 
    5833             : // -----------------------------------------------------------------------
    5834             : //
    5835             : // -----------------------------------------------------------------------
    5836      325918 : void MSTransformManager::setupBufferTransformations(vi::VisBuffer2 *vb)
    5837             : {
    5838             :         // Calculate number of rows to add to the output MS depending on the combination parameters
    5839      325918 :         uInt rowsToAdd = 0;
    5840             : 
    5841      325918 :         if ((combinespws_p) or (nspws_p > 1))
    5842             :         {
    5843             :                 // Fill baseline map using as key Ant1,Ant2,Scan and State,
    5844             :                 // Which are the elements that can be combined in one chunk
    5845        7952 :                 rowIndex_p.clear();
    5846        7952 :                 baselineMap_p.clear();
    5847        7952 :                 Vector<Int> antenna1 = vb->antenna1();
    5848        7952 :                 Vector<Int> antenna2 = vb->antenna2();
    5849        7952 :                 Vector<Int> scan = vb->scan();
    5850        7952 :                 Vector<Int> state = vb->stateId();
    5851        7952 :                 Int relativeTimeInMiliseconds = 0;
    5852     1191825 :                 for (uInt row=0;row<antenna1.size();row++)
    5853             :                 {
    5854     1183873 :                         pair<uInt,uInt> baseline = std::make_pair(antenna1(row),antenna2(row));
    5855     1183873 :                         relativeTimeInMiliseconds = (Int)floor(1E3*(vb->time()(row) - vb->time()(0)));
    5856     1183873 :                         pair< pair<uInt,uInt>, uInt > baselineTime = std::make_pair(baseline,relativeTimeInMiliseconds);
    5857             : 
    5858             :                         // Fill row index vector with to the first row for every element in the baseline map
    5859     1183873 :                         if (baselineMap_p.find(baselineTime) == baselineMap_p.end())
    5860             :                         {
    5861      516343 :                                 rowIndex_p.push_back(row);
    5862             :                         }
    5863             : 
    5864     1183873 :                         baselineMap_p[baselineTime].push_back(row);
    5865             : 
    5866             :                 }
    5867             : 
    5868        7952 :                 rowsToAdd = baselineMap_p.size();
    5869             : 
    5870             :                 // Fill row index vector with to the first row for every element in the baseline map
    5871             :                 // jagonzal (CAS-8492): For SPW separation only we don't
    5872             :                 // follow the baselineMap order but the input order
    5873        7952 :                 if (combinespws_p)
    5874             :                 {
    5875        7234 :                         uInt rowIndex = 0;
    5876        7234 :                         rowIndex_p.clear();
    5877      518402 :                         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    5878             :                         {
    5879      511168 :                                 rowIndex_p.push_back((iter->second)[0]);
    5880      511168 :                                 rowIndex ++;
    5881             :                         }
    5882             :                 }
    5883        7952 :         }
    5884             :         else
    5885             :         {
    5886      317966 :                 rowsToAdd = vb->nRows();
    5887             :         }
    5888             : 
    5889             :         // Initialize reference frame transformation parameters
    5890      325918 :         if (refFrameTransformation_p)
    5891             :         {
    5892        1798 :                 initFrequencyTransGrid(vb);
    5893             :         }
    5894             : 
    5895             :         // Calculate total number for rows to add
    5896      325918 :         nRowsToAdd_p = rowsToAdd*nspws_p;
    5897             : 
    5898      325918 :     return;
    5899             : 
    5900             : }
    5901             : 
    5902             : // -----------------------------------------------------------------------
    5903             : // Fill output MS with data from an input VisBuffer
    5904             : // -----------------------------------------------------------------------
    5905      324082 : void MSTransformManager::fillOutputMs(vi::VisBuffer2 *vb)
    5906             : {
    5907      324082 :         setupBufferTransformations(vb);
    5908             : 
    5909      324082 :         if (not bufferMode_p)
    5910             :         {
    5911             :                 // Create RowRef object to fill new rows
    5912      324082 :                 auto currentRows = outputMs_p->nrow();
    5913      324082 :                 RefRows rowRef( currentRows, currentRows + nRowsToAdd_p/nspws_p - 1);
    5914             : 
    5915             :                 // Add new rows to output MS
    5916      324082 :                 outputMs_p->addRow(nRowsToAdd_p,false);
    5917             : 
    5918             :                 // Fill new rows
    5919      324082 :                 weightSpectrumFlatFilled_p = false;
    5920      324082 :                 weightSpectrumFromSigmaFilled_p = false;
    5921      324082 :             fillWeightCols(vb,rowRef);
    5922      324082 :             fillDataCols(vb,rowRef);
    5923      324082 :                 fillIdCols(vb,rowRef);
    5924      324082 :         }
    5925             : 
    5926      324082 :     return;
    5927             : }
    5928             : 
    5929             : // -----------------------------------------------------------------------
    5930             : // Method to initialize the input frequency grid to change reference frame
    5931             : // -----------------------------------------------------------------------
    5932        1798 : void MSTransformManager::initFrequencyTransGrid(vi::VisBuffer2 *vb)
    5933             : {
    5934             :         // NOTE (jagonzal): According to dpetry the difference between times is negligible but he recommends to use TIME
    5935             :         //                  However it does not cross-validate unless we use timeMeas from the MS columns
    5936        1798 :         ScalarMeasColumn<MEpoch> mainTimeMeasCol = selectedInputMsCols_p->timeMeas();
    5937        1798 :         MEpoch currentRowTime = mainTimeMeasCol(vb->rowIds()(0));
    5938             : 
    5939             :         // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    5940        1798 :         MDoppler radVelCorr;
    5941        1798 :         MDirection inputFieldDirection;
    5942        1798 :         bool radVelSignificant = false;
    5943        1798 :         if (radialVelocityCorrection_p && inputMSFieldCols_p->needInterTime(vb->fieldId()(0)))
    5944             :         {
    5945         254 :                 MRadialVelocity mRV = inputMSFieldCols_p->radVelMeas(vb->fieldId()(0),vb->time()(0));
    5946         254 :                 Quantity mrv = mRV.get("m/s");
    5947         254 :                 Quantity offsetMrv = radialVelocity_p.get("m/s"); // the radvel by which the out SPW def was shifted
    5948         254 :                 radVelCorr =  MDoppler(mrv-(Quantity(2.)*offsetMrv));
    5949         254 :                 if (fabs(mrv.getValue()) > 1E-6) radVelSignificant = true;
    5950             : 
    5951         254 :                 inputFieldDirection = inputMSFieldCols_p->phaseDirMeas(vb->fieldId()(0), vb->time()(0));
    5952         254 :         }
    5953             :         else
    5954             :         {
    5955        1544 :                 inputFieldDirection = vb->phaseCenter();
    5956             :         }
    5957             : 
    5958        1798 :         MFrequency::Ref inputFrameRef = MFrequency::Ref(inputReferenceFrame_p,
    5959        1798 :                                                                                                         MeasFrame(inputFieldDirection, observatoryPosition_p, currentRowTime));
    5960             : 
    5961        1798 :         MFrequency::Ref outputFrameRef;
    5962        3596 :         outputFrameRef = MFrequency::Ref(outputReferenceFrame_p,
    5963        5394 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    5964             : 
    5965        1798 :         freqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    5966             : 
    5967        1798 :         Int spwIndex = 0;
    5968        1798 :         if (not combinespws_p)
    5969             :         {
    5970             :                 // jagonzal : It is not necessary to map spwIndex because we
    5971             :                 // pass the original SPWId down to the interpol1D method
    5972         879 :                 spwIndex = vb->spectralWindows()(0);
    5973             :         }
    5974             : 
    5975             : 
    5976        1798 :         if (fftShiftEnabled_p)
    5977             :         {
    5978         425 :                 uInt centralChan = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size()/2;
    5979             : 
    5980         425 :                 Double oldCentralFrequencyBeforeRegridding = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[centralChan];
    5981             :                 Double newCentralFrequencyBeforeRegriddingAtCurrentTime =
    5982         425 :                                 freqTransEngine_p(oldCentralFrequencyBeforeRegridding).get(MSTransformations::Hz).getValue();
    5983             : 
    5984             :                 // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    5985         425 :                 if (radVelSignificant)
    5986             :                 {
    5987           0 :                         Vector<Double> tmp(1,newCentralFrequencyBeforeRegriddingAtCurrentTime);
    5988           0 :                         newCentralFrequencyBeforeRegriddingAtCurrentTime = radVelCorr.shiftFrequency(tmp)(0);
    5989           0 :                 }
    5990             : 
    5991         425 :                 Double newCentralFrequencyBeforeRegriddingAtReferenceTime = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[centralChan];
    5992         425 :                 Double absoluteShift = newCentralFrequencyBeforeRegriddingAtCurrentTime - newCentralFrequencyBeforeRegriddingAtReferenceTime;
    5993             : 
    5994         425 :                 Double chanWidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
    5995         425 :                 Double bandwidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[inputOutputSpwMap_p[spwIndex].second.NUM_CHAN-1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
    5996         425 :                 bandwidth += chanWidth;
    5997             : 
    5998         425 :                 fftShift_p = - absoluteShift / bandwidth;
    5999             : 
    6000         425 :                 ostringstream current;
    6001         425 :                 current << setprecision(numeric_limits<double>::max_digits10)
    6002         425 :                         << newCentralFrequencyBeforeRegriddingAtCurrentTime;
    6003         425 :                 ostringstream reference;
    6004         425 :                 reference << setprecision(numeric_limits<double>::max_digits10)
    6005         425 :                           << newCentralFrequencyBeforeRegriddingAtReferenceTime;
    6006         850 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    6007             :                          << "Using fftshift interpolation. The absolute shift is the "
    6008             :                          << "new central frequency at current (input SPW) time - new "
    6009             :                          << "central frequency "
    6010             :                          << "at reference (output SPW) time\nAbsolute shift: "
    6011             :                          << current
    6012             :                          << " - " << reference
    6013             :                          << " = " << absoluteShift << ", bandwidth " << bandwidth
    6014         850 :                          << ", relative shift: " << fftShift_p << LogIO::POST;
    6015             : 
    6016         425 :         }
    6017             :         else
    6018             :         {
    6019      486559 :             for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size(); chan_idx++)
    6020             :             {
    6021      485186 :                 inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[chan_idx] =
    6022      970372 :                 freqTransEngine_p(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[chan_idx]).get(MSTransformations::Hz).getValue();
    6023             :             }
    6024             : 
    6025             :             /*
    6026             :                 ostringstream oss;
    6027             :                 oss.precision(30);
    6028             :                 oss << " field direction input frame=" << inputFieldDirection << endl;
    6029             :                 oss << " input frame=" << inputFrameRef << endl;
    6030             :                 oss << " field direction output frame=" << phaseCenter_p << endl;
    6031             :                 oss << " output frame=" << outputFrameRef << endl;
    6032             :                 oss << " transformation engine=" << freqTransEngine_p << endl;
    6033             :                 oss << " before transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[0] << endl;
    6034             :                 oss << " after transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
    6035             :                 */
    6036             : 
    6037             : 
    6038        1373 :         if (radVelSignificant)
    6039             :         {
    6040         254 :                 inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux =
    6041         508 :                                 radVelCorr.shiftFrequency(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux);
    6042             : 
    6043             :                 /*
    6044             :                 oss << " correction engine=" << radVelCorr << endl;
    6045             :                 oss << " after radial velocity correction=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
    6046             :                         */
    6047             :         }
    6048             : 
    6049             :                 //logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
    6050             :         }
    6051             : 
    6052        3596 :         return;
    6053        1798 : }
    6054             : 
    6055             : // ----------------------------------------------------------------------------------------
    6056             : // Fill auxiliary (meta data) columns which don't depend on the SPW (merely consist of Ids)
    6057             : // ----------------------------------------------------------------------------------------
    6058      325918 : void MSTransformManager::fillIdCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6059             : {
    6060             :     // Declare common auxiliary variables
    6061      325918 :     RefRows absoluteRefRows(rowRef.firstRow(),rowRef.firstRow()+nRowsToAdd_p-1);
    6062      325918 :     Vector<Int> tmpVectorInt(nRowsToAdd_p,0);
    6063      325918 :     Vector<Double> tmpVectorDouble(nRowsToAdd_p,0.0);
    6064      325918 :     Vector<bool> tmpVectorbool(nRowsToAdd_p,false);
    6065             : 
    6066             :     // Special case for Data description Id
    6067      325918 :     if (transformDDIVector(vb->dataDescriptionIds(),tmpVectorInt))
    6068             :     {
    6069      322188 :         outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,tmpVectorInt);
    6070             :     }
    6071             :     else
    6072             :     {
    6073        3730 :         outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,vb->dataDescriptionIds());
    6074             :     }
    6075             : 
    6076             :     // Re-indexable Columns
    6077      325918 :     transformAndWriteReindexableVector(vb->observationId(),tmpVectorInt,true,
    6078      325918 :                                        inputOutputObservationIndexMap_p,
    6079      325918 :                                        outputMsCols_p->observationId(),absoluteRefRows);
    6080      325918 :     transformAndWriteReindexableVector(vb->arrayId(),tmpVectorInt,true,
    6081      325918 :                                        inputOutputArrayIndexMap_p,
    6082      325918 :                                        outputMsCols_p->arrayId(),absoluteRefRows);
    6083      325918 :     transformAndWriteReindexableVector(vb->fieldId(),tmpVectorInt,!timespan_p.contains("field"),
    6084      325918 :                                        inputOutputFieldIndexMap_p,
    6085      325918 :                                        outputMsCols_p->fieldId(),absoluteRefRows);
    6086      325918 :     transformAndWriteReindexableVector(vb->stateId(),tmpVectorInt,!timespan_p.contains("state"),
    6087      325918 :                                        inputOutputScanIntentIndexMap_p,
    6088      325918 :                                        outputMsCols_p->stateId(),absoluteRefRows);
    6089      325918 :     transformAndWriteReindexableVector(vb->antenna1(),tmpVectorInt,false,
    6090      325918 :                                        inputOutputAntennaIndexMap_p,
    6091      325918 :                                        outputMsCols_p->antenna1(),absoluteRefRows);
    6092      325918 :     transformAndWriteReindexableVector(vb->antenna2(),tmpVectorInt,false,
    6093      325918 :                                        inputOutputAntennaIndexMap_p,
    6094      325918 :                                        outputMsCols_p->antenna2(),absoluteRefRows);
    6095             : 
    6096             :     // Not Re-indexable Columns
    6097      325918 :     transformAndWriteNotReindexableVector(vb->scan(),tmpVectorInt,!timespan_p.contains("scan"),outputMsCols_p->scanNumber(),absoluteRefRows);
    6098      325918 :     transformAndWriteNotReindexableVector(vb->processorId(),tmpVectorInt,false,outputMsCols_p->processorId(),absoluteRefRows);
    6099      325918 :     transformAndWriteNotReindexableVector(vb->feed1(),tmpVectorInt,false,outputMsCols_p->feed1(),absoluteRefRows);
    6100      325918 :     transformAndWriteNotReindexableVector(vb->feed2(),tmpVectorInt,false,outputMsCols_p->feed2(),absoluteRefRows);
    6101      325918 :     transformAndWriteNotReindexableVector(vb->time(),tmpVectorDouble,false,outputMsCols_p->time(),absoluteRefRows);
    6102      325918 :     transformAndWriteNotReindexableVector(vb->timeCentroid(),tmpVectorDouble,false,outputMsCols_p->timeCentroid(),absoluteRefRows);
    6103      325918 :     transformAndWriteNotReindexableVector(vb->timeInterval(),tmpVectorDouble,false,outputMsCols_p->interval(),absoluteRefRows);
    6104             : 
    6105             :     // Special case for vectors that have to be averaged
    6106      325918 :     if (combinespws_p)
    6107             :     {
    6108        7234 :         mapAndAverageVector(vb->flagRow(),tmpVectorbool);
    6109        7234 :         outputMsCols_p->flagRow().putColumnCells(absoluteRefRows, tmpVectorbool);
    6110             : 
    6111             :         // jagonzal: We average exposures by default, if they are the same we obtain the same results
    6112        7234 :         mapAndAverageVector(vb->exposure(),tmpVectorDouble);
    6113        7234 :         outputMsCols_p->exposure().putColumnCells(absoluteRefRows, tmpVectorDouble);
    6114             :     }
    6115             :     else
    6116             :     {
    6117      318684 :         transformAndWriteNotReindexableVector(vb->flagRow(),tmpVectorbool,false,outputMsCols_p->flagRow(),absoluteRefRows);
    6118      318684 :         transformAndWriteNotReindexableVector(vb->exposure(),tmpVectorDouble,false,outputMsCols_p->exposure(),absoluteRefRows);
    6119             :     }
    6120             : 
    6121      325918 :     if (combinespws_p)
    6122             :     {
    6123        7234 :         Matrix<Double> tmpUvw(IPosition(2,3,rowRef.nrows()),0.0);
    6124        7234 :         Matrix<Float> tmpMatrixFloat(IPosition(2,vb->nCorrelations(),rowRef.nrows()),0.0);
    6125             : 
    6126        7234 :         mapMatrix(vb->uvw(),tmpUvw);
    6127        7234 :         writeMatrix(tmpUvw,outputMsCols_p->uvw(),rowRef,nspws_p);
    6128             : 
    6129             :         // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
    6130        7234 :         if (not spectrumTransformation_p)
    6131             :         {
    6132           0 :             if (newWeightFactorMap_p.size() > 0)
    6133             :             {
    6134           0 :                 mapAndScaleMatrix(vb->weight(),tmpMatrixFloat,newWeightFactorMap_p,vb->spectralWindows());
    6135           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
    6136             :             }
    6137             :             else
    6138             :             {
    6139             :                 // jagonzal: According to dpetry we have to copy weights from the first SPW
    6140             :                 // This is justified since the rows to be combined _must_ be from the
    6141             :                 // same baseline and therefore have the same UVW coordinates in the MS (in meters).
    6142             :                 // They could therefore be regarded to also have the same WEIGHT, at least to
    6143             :                 // a good approximation.
    6144           0 :                 mapMatrix(vb->weight(),tmpMatrixFloat);
    6145           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
    6146             :             }
    6147             : 
    6148             : 
    6149             :             // Sigma must be redefined to 1/weight when corrected data becomes data
    6150           0 :             if (correctedToData_p)
    6151             :             {
    6152           0 :                 arrayTransformInPlace(tmpMatrixFloat, vi::AveragingTvi2::weightToSigma);
    6153           0 :                 outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
    6154           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6155             :             }
    6156             :             else
    6157             :             {
    6158           0 :                 if (newSigmaFactorMap_p.size() > 0)
    6159             :                 {
    6160           0 :                     mapAndScaleMatrix(vb->sigma(),tmpMatrixFloat,newSigmaFactorMap_p,vb->spectralWindows());
    6161           0 :                     outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
    6162           0 :                     writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6163             :                 }
    6164             :                 else
    6165             :                 {
    6166             :                     // jagonzal: According to dpetry we have to copy weights from the first SPW
    6167             :                     // This is justified since the rows to be combined _must_ be from the
    6168             :                     // same baseline and therefore have the same UVW coordinates in the MS (in meters).
    6169             :                     // They could therefore be regarded to also have the same WEIGHT, at least to
    6170             :                     // a good approximation.
    6171           0 :                     mapMatrix(vb->sigma(),tmpMatrixFloat);
    6172           0 :                     writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6173             :                 }
    6174             :             }
    6175             :         }
    6176             : 
    6177        7234 :     }
    6178             :     else
    6179             :     {
    6180      318684 :         writeMatrix(vb->uvw(),outputMsCols_p->uvw(),rowRef,nspws_p);
    6181             : 
    6182             :         // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
    6183      318684 :         if (not spectrumTransformation_p)
    6184             :         {
    6185      175819 :             if (correctedToData_p) {
    6186             : 
    6187             :               // weight -> weight
    6188       28211 :                 Matrix<Float> weights = vb->weight();
    6189       28211 :                 if (newWeightFactorMap_p.size() > 0)
    6190             :                 {
    6191           0 :                     if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6192           0 :                             (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6193             :                     {
    6194           0 :                          weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
    6195             :                     }
    6196             :                 }
    6197       28211 :                 writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
    6198             : 
    6199             :                 // weight -> sigma
    6200       28211 :                 arrayTransformInPlace(weights, vi::AveragingTvi2::weightToSigma);
    6201       28211 :                 writeMatrix(weights,outputMsCols_p->sigma(),rowRef,nspws_p);
    6202             : 
    6203       28211 :             }
    6204      147608 :             else if(!bothDataColumnsAreOutput_p)
    6205             :             {
    6206             :                 // sigma -> sigma
    6207      134308 :                 Matrix<Float> sigma = vb->sigma();
    6208      134308 :                 if (newSigmaFactorMap_p.size() > 0)
    6209             :                 {
    6210           0 :                     if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
    6211           0 :                             (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6212             :                     {
    6213           0 :                         sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6214             :                     }
    6215             :                 }
    6216      134308 :                 writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
    6217             : 
    6218             :                 // sigma -> weight
    6219      134308 :                 arrayTransformInPlace(sigma, vi::AveragingTvi2::sigmaToWeight);
    6220      134308 :                 writeMatrix(sigma, outputMsCols_p->weight(), rowRef, nspws_p);
    6221      134308 :             }
    6222             :             // If both DATA and DATA_CORRECTED are input and output then
    6223             :             // SIGMA(_SPECTRUM) and WEIGHT(_SPECTRUM) should maintain their alignment
    6224             :             // with DATA and CORRECTED_DATA, respectively and nothing is done. See CAS-11139
    6225             :             else
    6226             :             {
    6227             :                 // weight -> weight
    6228       13300 :                 Matrix<Float> weights = vb->weight();
    6229       13300 :                 if (newWeightFactorMap_p.size() > 0)
    6230             :                 {
    6231           0 :                     if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6232           0 :                             (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6233             :                     {
    6234           0 :                          weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
    6235             :                     }
    6236             :                 }
    6237       13300 :                 writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
    6238             : 
    6239             :                 // sigma -> sigma
    6240       13300 :                 Matrix<Float> sigma = vb->sigma();
    6241       13300 :                 if (newSigmaFactorMap_p.size() > 0)
    6242             :                 {
    6243           0 :                     if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
    6244           0 :                             (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6245             :                     {
    6246           0 :                         sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6247             :                     }
    6248             :                 }
    6249       13300 :                 writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
    6250       13300 :             }
    6251             :         }
    6252             :     }
    6253             : 
    6254      651836 :     return;
    6255      325918 : }
    6256             : 
    6257             : // ------------------------------------------------------------------------------------
    6258             : //
    6259             : // ------------------------------------------------------------------------------------
    6260     2918794 : template <class T> void MSTransformManager::transformAndWriteNotReindexableVector(        const Vector<T> &inputVector,
    6261             :                                                                                                                                                                         Vector<T> &outputVector,
    6262             :                                                                                                                                                                         bool constant,
    6263             :                                                                                                                                                                         ScalarColumn<T> &outputCol,
    6264             :                                                                                                                                                                         RefRows &rowReference)
    6265             : {
    6266     2918794 :         bool transformed = transformNotReindexableVector(inputVector,outputVector,constant);
    6267             : 
    6268     2918794 :         if (transformed)
    6269             :         {
    6270       57100 :                 outputCol.putColumnCells(rowReference, outputVector);
    6271             :         }
    6272             :         else
    6273             :         {
    6274     2861694 :                 outputCol.putColumnCells(rowReference, inputVector);
    6275             :         }
    6276             : 
    6277     2918794 :         return;
    6278             : };
    6279             : 
    6280             : // ------------------------------------------------------------------------------------
    6281             : //
    6282             : // ------------------------------------------------------------------------------------
    6283     1955508 : template <class T> void MSTransformManager::transformAndWriteReindexableVector(   const Vector<T> &inputVector,
    6284             :                                                                                                                         Vector<T> &outputVector,
    6285             :                                                                                                                         bool constant,
    6286             :                                                                                                                         map<uInt,uInt> &inputOutputIndexMap,
    6287             :                                                                                                                         ScalarColumn<T> &outputCol,
    6288             :                                                                                                                         RefRows &rowReference)
    6289             : {
    6290     1955508 :         bool transformed = transformReindexableVector(inputVector,outputVector,constant,inputOutputIndexMap);
    6291             : 
    6292     1955508 :         if (transformed)
    6293             :         {
    6294       70402 :                 outputCol.putColumnCells(rowReference, outputVector);
    6295             :         }
    6296             :         else
    6297             :         {
    6298     1885106 :                 outputCol.putColumnCells(rowReference, inputVector);
    6299             :         }
    6300             : 
    6301     1955508 :         return;
    6302             : };
    6303             : 
    6304             : // ------------------------------------------------------------------------------------
    6305             : //
    6306             : // ------------------------------------------------------------------------------------
    6307      325918 : bool MSTransformManager::transformDDIVector(const Vector<Int> &inputVector,Vector<Int> &outputVector)
    6308             : {
    6309      325918 :         bool transformed = true;
    6310             : 
    6311      325918 :         if ((combinespws_p) or (nspws_p > 1))
    6312             :         {
    6313        7952 :                 if (nspws_p > 1)
    6314             :                 {
    6315        1971 :                         uInt absoluteIndex = 0;
    6316       14664 :                         for (uInt index=0; index<rowIndex_p.size();index++)
    6317             :                         {
    6318       72429 :                                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6319             :                                 {
    6320       59736 :                                         outputVector(absoluteIndex) = ddiStart_p + spwIndex;
    6321       59736 :                                         absoluteIndex += 1;
    6322             :                                 }
    6323             :                         }
    6324             :                 }
    6325             :                 else
    6326             :                 {
    6327        5981 :                         outputVector = ddiStart_p;
    6328             :                 }
    6329        7952 :         }
    6330             :         else
    6331             :         {
    6332      317966 :                 transformed = transformReindexableVector(inputVector,outputVector,true,inputOutputDDIndexMap_p);
    6333             :         }
    6334             : 
    6335      325918 :         return transformed;
    6336             : }
    6337             : 
    6338             : // ------------------------------------------------------------------------------------
    6339             : //
    6340             : // ------------------------------------------------------------------------------------
    6341        7234 : void MSTransformManager::mapAndAverageVector(   const Vector<Double> &inputVector,
    6342             :                                                                                                 Vector<Double> &outputVector)
    6343             : {
    6344        7234 :         Double vec_average = 0;
    6345        7234 :         vector<uInt> baselineRows;
    6346        7234 :         uInt row, counts, absoluteIndex = 0;
    6347      518402 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6348             :         {
    6349             :                 // Get baseline rows vector
    6350      511168 :                 baselineRows = iter->second;
    6351             : 
    6352             :                 // Compute combined value from each SPW
    6353      511168 :                 counts = 0;
    6354             : 
    6355     1689866 :                 for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6356             :                 {
    6357     1178698 :                         row = *iter_row;
    6358     1178698 :                         if (counts == 0)
    6359             :                         {
    6360      511168 :                                 vec_average = inputVector(row);
    6361             :                         }
    6362             :                         else
    6363             :                         {
    6364      667530 :                                 vec_average += inputVector(row);
    6365             :                         }
    6366             : 
    6367     1178698 :                         counts += 1;
    6368             :                 }
    6369             : 
    6370             :                 // Normalize value
    6371      511168 :                 if (counts) vec_average /= counts;
    6372             : 
    6373             :                 // Set value in output vector
    6374     1042742 :                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6375             :                 {
    6376      531574 :                         outputVector(absoluteIndex) = vec_average;
    6377      531574 :                         absoluteIndex += 1;
    6378             :                 }
    6379             :         }
    6380             : 
    6381       14468 :         return;
    6382        7234 : }
    6383             : 
    6384             : // ------------------------------------------------------------------------------------
    6385             : //
    6386             : // ------------------------------------------------------------------------------------
    6387        7234 : void MSTransformManager::mapAndAverageVector(   const Vector<bool> &inputVector,
    6388             :                                                                                                 Vector<bool> &outputVector)
    6389             : {
    6390        7234 :         bool vec_average = false;
    6391        7234 :         vector<uInt> baselineRows;
    6392        7234 :         uInt row, counts, absoluteIndex = 0;
    6393      518402 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6394             :         {
    6395             :                 // Get baseline rows vector
    6396      511168 :                 baselineRows = iter->second;
    6397             : 
    6398             :                 // Compute combined value from each SPW
    6399      511168 :                 counts = 0;
    6400             : 
    6401     1689866 :                 for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6402             :                 {
    6403     1178698 :                         row = *iter_row;
    6404     1178698 :                         if (counts == 0)
    6405             :                         {
    6406     1178698 :                                 vec_average = inputVector(row);
    6407             :                         }
    6408             :                         else
    6409             :                         {
    6410           0 :                                 vec_average &= inputVector(row);
    6411             :                         }
    6412             :                 }
    6413             : 
    6414             :                 // Set value in output vector
    6415     1042742 :                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6416             :                 {
    6417      531574 :                         outputVector(absoluteIndex) = vec_average;
    6418      531574 :                         absoluteIndex += 1;
    6419             :                 }
    6420             :         }
    6421             : 
    6422       14468 :         return;
    6423        7234 : }
    6424             : 
    6425             : 
    6426             : // -----------------------------------------------------------------------------------
    6427             : // Fill the data from an input matrix with shape [nCol,nBaselinesxnSPWs] into an
    6428             : // output matrix with shape [nCol,nBaselines] accumulating the averaging from all SPWS
    6429             : // -----------------------------------------------------------------------------------
    6430             : template <class T> void MSTransformManager::mapAndAverageMatrix(  const Matrix<T> &inputMatrix,
    6431             :                                                                                                                                                 Matrix<T> &outputMatrix,
    6432             :                                                                                                                                                 bool convolveFlags,
    6433             :                                                                                                                                                 vi::VisBuffer2 *vb)
    6434             : {
    6435             :         // Get number of columns
    6436             :         uInt nCols = outputMatrix.shape()(0);
    6437             : 
    6438             :     // Access FLAG_ROW in case we need to convolute the average
    6439             :         Vector<bool> flags;
    6440             :         if (convolveFlags) flags = vb->flagRow();
    6441             : 
    6442             :     // Fill output array with the combined data from each SPW
    6443             :         uInt row;
    6444             :         uInt baseline_index = 0;
    6445             :         Double normalizingFactor = 0;
    6446             :         Double contributionFactor = 0;
    6447             :         vector<uInt> baselineRows;
    6448             :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6449             :         {
    6450             :                 // Get baseline rows vector
    6451             :                 baselineRows = iter->second;
    6452             : 
    6453             :                 // Reset normalizing factor
    6454             :                 normalizingFactor = 0;
    6455             : 
    6456             :                 // Compute combined value from each SPW
    6457             :                 for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6458             :                 {
    6459             :                         row = *iter_row;
    6460             :                         if (convolveFlags)
    6461             :                         {
    6462             :                                 contributionFactor = !flags(row);
    6463             :                         }
    6464             :                         else
    6465             :                         {
    6466             :                                 contributionFactor = 1;
    6467             :                         }
    6468             : 
    6469             :                         for (uInt col = 0; col < nCols; col++)
    6470             :                         {
    6471             :                                 outputMatrix(col,baseline_index) += contributionFactor*inputMatrix(col,row);
    6472             :                         }
    6473             : 
    6474             :                         normalizingFactor += contributionFactor;
    6475             :                 }
    6476             : 
    6477             :                 // Normalize accumulated value
    6478             :                 if (normalizingFactor>0)
    6479             :                 {
    6480             :                         for (uInt col = 0; col < nCols; col++)
    6481             :                         {
    6482             :                                 outputMatrix(col,baseline_index) /= normalizingFactor;
    6483             :                         }
    6484             :                 }
    6485             : 
    6486             :                 baseline_index += 1;
    6487             :         }
    6488             : 
    6489             :         return;
    6490             : }
    6491             : 
    6492             : // -----------------------------------------------------------------------
    6493             : //
    6494             : // -----------------------------------------------------------------------
    6495           0 : template <class T> void MSTransformManager::mapAndScaleMatrix(    const Matrix<T> &inputMatrix,
    6496             :                                                                                                                                                 Matrix<T> &outputMatrix,
    6497             :                                                                                                                                                 map<uInt,T> scaleMap,
    6498             :                                                                                                                                                 Vector<Int> spws)
    6499             : {
    6500             :         // Reset output Matrix
    6501           0 :         outputMatrix = 0;
    6502             : 
    6503             :         // Get number of columns
    6504           0 :         uInt nCols = outputMatrix.shape()(0);
    6505             : 
    6506             :     // Fill output array with the combined data from each SPW
    6507             :         Int spw;
    6508             :         uInt row;
    6509           0 :         uInt baseline_index = 0;
    6510           0 :         vector<uInt> baselineRows;
    6511             :         T contributionFactor;
    6512           0 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6513             :         {
    6514             :                 // Get baseline rows vector
    6515           0 :                 baselineRows = iter->second;
    6516             : 
    6517             :                 // Reset normalizing factor
    6518             : 
    6519             :                 // Get value from first SPW (this is for Weight and Sigma and cvel is doing it so)
    6520           0 :                 row = baselineRows.at(0);
    6521           0 :                 spw = spws(row);
    6522           0 :                 if (scaleMap.find(spw) != scaleMap.end())
    6523             :                 {
    6524           0 :                         contributionFactor = scaleMap[spw];
    6525             :                 }
    6526             :                 else
    6527             :                 {
    6528           0 :                         contributionFactor = 1;
    6529             :                 }
    6530             : 
    6531           0 :                 for (uInt col = 0; col < nCols; col++)
    6532             :                 {
    6533           0 :                         outputMatrix(col,baseline_index) = contributionFactor*inputMatrix(col,row);
    6534             :                 }
    6535             : 
    6536           0 :                 baseline_index += 1;
    6537             :         }
    6538             : 
    6539           0 :         return;
    6540           0 : }
    6541             : 
    6542             : 
    6543             : // ----------------------------------------------------------------------------------------
    6544             : // Fill main (data) columns which have to be combined together to produce bigger SPWs
    6545             : // ----------------------------------------------------------------------------------------
    6546      324082 : void MSTransformManager::fillDataCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6547             : {
    6548      324082 :         ArrayColumn<bool> *outputFlagCol=NULL;
    6549      737232 :         for (dataColMap::iterator iter = dataColMap_p.begin();iter != dataColMap_p.end();iter++)
    6550             :         {
    6551             :                 // Get applicable *_SPECTRUM (copy constructor uses reference semantics)
    6552             :                 // If channel average or combine, otherwise no need to copy
    6553      413150 :                 const Cube<Float> &applicableSpectrum = getApplicableSpectrum(vb,iter->first);
    6554             : 
    6555             :                 // Apply transformations
    6556      413150 :                 switch (iter->first)
    6557             :                 {
    6558      204983 :                         case MS::DATA:
    6559             :                         {
    6560      204983 :                                 if (mainColumn_p == MS::DATA)
    6561             :                                 {
    6562      204983 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6563      204983 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6564             :                                 }
    6565             :                                 else
    6566             :                                 {
    6567           0 :                                         outputFlagCol = NULL;
    6568             :                                 }
    6569             : 
    6570      204983 :                                 setTileShape(rowRef,outputMsCols_p->data());
    6571      204983 :                                 transformCubeOfData(vb,rowRef,vb->visCube(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6572             : 
    6573      204983 :                                 break;
    6574             :                         }
    6575      110817 :                         case MS::CORRECTED_DATA:
    6576             :                         {
    6577      110817 :                                 if (mainColumn_p == MS::CORRECTED_DATA)
    6578             :                                 {
    6579       67772 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6580       67772 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6581             :                                 }
    6582             :                                 else
    6583             :                                 {
    6584       43045 :                                         outputFlagCol = NULL;
    6585             :                                 }
    6586             : 
    6587      110817 :                                 if (iter->second == MS::DATA)
    6588             :                                 {
    6589       66172 :                                         setTileShape(rowRef,outputMsCols_p->data());
    6590       66172 :                                         transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6591             :                                 }
    6592             :                                 else
    6593             :                                 {
    6594       44645 :                                         setTileShape(rowRef,outputMsCols_p->correctedData());
    6595       44645 :                                         transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->correctedData(), outputFlagCol,applicableSpectrum);
    6596             :                                 }
    6597             : 
    6598      110817 :                                 break;
    6599             :                         }
    6600       78450 :                         case MS::MODEL_DATA:
    6601             :                         {
    6602       78450 :                                 if (mainColumn_p == MS::MODEL_DATA)
    6603             :                                 {
    6604       34027 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6605       34027 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6606             :                                 }
    6607             :                                 else
    6608             :                                 {
    6609       44423 :                                         outputFlagCol = NULL;
    6610             :                                 }
    6611             : 
    6612       78450 :                                 if (produceModel_p)
    6613             :                                 {
    6614             :                                     // irrespective of wheter iter->second == MS::DATA
    6615             :                                     // or iter->second == MS::CORRECTED_DATA
    6616          53 :                                     setTileShape(rowRef,outputMsCols_p->modelData());
    6617          53 :                                     transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
    6618       78397 :                                 } else if (iter->second == MS::DATA) {
    6619       34027 :                                         setTileShape(rowRef,outputMsCols_p->data());
    6620       34027 :                                         transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6621             :                                 }
    6622             :                                 else
    6623             :                                 {
    6624       44370 :                                         setTileShape(rowRef,outputMsCols_p->modelData());
    6625       44370 :                                         transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
    6626             :                                 }
    6627       78450 :                                 break;
    6628             :                         }
    6629       18900 :                         case MS::FLOAT_DATA:
    6630             :                         {
    6631       18900 :                                 if (mainColumn_p == MS::FLOAT_DATA)
    6632             :                                 {
    6633       17300 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6634       17300 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6635             :                                 }
    6636             :                                 else
    6637             :                                 {
    6638        1600 :                                         outputFlagCol = NULL;
    6639             :                                 }
    6640             : 
    6641       18900 :                                 setTileShape(rowRef,outputMsCols_p->floatData());
    6642       18900 :                                 transformCubeOfData(vb,rowRef,vb->visCubeFloat(),outputMsCols_p->floatData(), outputFlagCol,applicableSpectrum);
    6643             : 
    6644       18900 :                                 break;
    6645             :                         }
    6646           0 :                         case MS::LAG_DATA:
    6647             :                         {
    6648             :                                 // jagonzal: TODO
    6649           0 :                                 break;
    6650             :                         }
    6651           0 :                         default:
    6652             :                         {
    6653             :                                 // jagonzal: TODO
    6654           0 :                                 break;
    6655             :                         }
    6656             :                 }
    6657             :         }
    6658             : 
    6659             :     // Special case for flag category
    6660      324082 :     if (inputFlagCategoryAvailable_p)
    6661             :     {
    6662           0 :         if (spectrumReshape_p)
    6663             :         {
    6664           0 :                 IPosition transformedCubeShape = getShape(); //[nC,nF,nR]
    6665           0 :                 IPosition inputFlagCategoryShape = vb->flagCategory().shape(); // [nC,nF,nCategories,nR]
    6666           0 :                 IPosition flagCategoryShape(4,  inputFlagCategoryShape(1),
    6667           0 :                                                                                 transformedCubeShape(2),
    6668           0 :                                                                                 inputFlagCategoryShape(2),
    6669           0 :                                                                                 transformedCubeShape(2));
    6670           0 :                 Array<bool> flagCategory(flagCategoryShape,false);
    6671             : 
    6672           0 :                 outputMsCols_p->flagCategory().putColumnCells(rowRef, flagCategory);
    6673           0 :         }
    6674             :         else
    6675             :         {
    6676           0 :                 outputMsCols_p->flagCategory().putColumnCells(rowRef, vb->flagCategory());
    6677             :         }
    6678             :     }
    6679             : 
    6680      324082 :         return;
    6681             : }
    6682             : 
    6683             : // ----------------------------------------------------------------------------------------
    6684             : // Fill weight cols (WEIGHT_SPECTRUM and SIGMA_SPECTRUM) as well as WEIGHT/SIGMA which have to be derived from it using median
    6685             : // ----------------------------------------------------------------------------------------
    6686      325881 : void MSTransformManager::fillWeightCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6687             : {
    6688             :         // WEIGHT_SPECTRUM and SIGMA_SPECTRUM are only filled if requested or when WEIGHT_SPECTRUM is present in the input MS
    6689             :         // But WEIGHT/SIGMA have always to be derived from in-memory WEIGHT_SPECTRUM/SIGMA_SPECTRUM
    6690      325881 :         if (flushWeightSpectrum_p or spectrumTransformation_p or userBufferMode_p)
    6691             :         {
    6692             :                 // Switch aux Weight propagation off
    6693      171491 :                 propagateWeights(false);
    6694             : 
    6695             :                 // Switch average and smooth kernels
    6696      171491 :                 setChannelAverageKernel(MSTransformations::flagCumSumNonZero);
    6697      171491 :                 setSmoothingKernel(MSTransformations::plainSmoothSpectrum);
    6698      171491 :                 setSmoothingFourierKernel(MSTransformations::plainSmoothSpectrum);
    6699             : 
    6700             :                 // Dummy auxiliary weightSpectrum
    6701      171491 :                 const Cube<Float> applicableSpectrum;
    6702             : 
    6703      171491 :                 if (spectrumTransformation_p)
    6704             :                 {
    6705             :                         // For SPW separation:
    6706             :                         // Prepare RowReference for spectrum transformations
    6707             :                         // (all data is flushed at once instead of blocks)
    6708      150099 :                         RefRows rowRefSpectrum(rowRef.firstRow(), rowRef.firstRow() + nRowsToAdd_p-1);
    6709             : 
    6710             :                         // Switch on buffer mode
    6711      150099 :                         Cube<Float> transformedSpectrum;
    6712      150099 :                         Cube<bool> transformedFlag;
    6713      150099 :                         if (not userBufferMode_p)
    6714             :                         {
    6715      150099 :                                 setBufferMode(true);
    6716      150099 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6717      150099 :                                 transformedSpectrum.resize(getShape(),false);
    6718      150099 :                                 weightSpectrum_p = &transformedSpectrum;
    6719      150099 :                                 transformedFlag.resize(getShape(),false);
    6720      150099 :                                 flagCube_p = &transformedFlag; // Not used for the output but to extract the average/median
    6721             :                         }
    6722             : 
    6723             : 
    6724             :                         // Multiple column operation
    6725      150099 :                         if (doingData_p and doingCorrected_p)
    6726             :                         {
    6727             :                                 // Transform WEIGHT_SPECTRUM but don't derive SIGMA_SPECTRUM from it
    6728       29745 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6729             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6730             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6731       29745 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6732             : 
    6733             :                                 // Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
    6734       29745 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
    6735             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6736             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6737       29745 :                                                                                         MSTransformations::transformWeightIntoSigma,flushWeightSpectrum_p);
    6738             :                         }
    6739             :                         // In case of time average we can use directly WEIGHT_SPECTRUM because
    6740             :                         // AveragingTvi2 derives it from the input SIGMA_SPECTRUM or WEIGHT_SPECTRUM
    6741             :                         // depending on the selected DATA column
    6742      120354 :                         else if (timeAverage_p)
    6743             :                         {
    6744             :                                 // Transform WEIGHT_SPECTRUM
    6745        9244 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6746             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6747             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6748        9244 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6749             : 
    6750             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6751        9244 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6752             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6753             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6754        9244 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6755             :                         }
    6756             :                         // DATA to DATA: Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
    6757      111110 :                         else if (doingData_p)
    6758             :                         {
    6759             :                                 // Transform WEIGHT_SPECTRUM
    6760       46823 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
    6761             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6762             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6763       46823 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6764             : 
    6765             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6766       46823 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6767             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6768             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6769       46823 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6770             :                         }
    6771             :                         // CORRECTED to DATA: Transform WEIGHT_SPECTRUM and derive SIGMA_SPECTRUM from it
    6772       64287 :                         else if (doingCorrected_p) // CORRECTED to DATA
    6773             :                         {
    6774             :                                 // Transform WEIGHT_SPECTRUM
    6775       35381 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6776             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6777             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6778       35381 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6779             : 
    6780             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6781       35381 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6782             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6783             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6784       35381 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6785             :                         }
    6786             :                         // MODEL to DATA: Calculate WEIGHT_SPECTRUM using FLAG and derive SIGMA_SPECTRUM from it
    6787       28906 :                         else if (doingModel_p)
    6788             :                         {
    6789             :                                 // Transform WEIGHT_SPECTRUM
    6790       28864 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFlat(vb),
    6791             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6792             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6793       28864 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6794             : 
    6795             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6796       28864 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6797             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6798             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6799       28864 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6800             :                         }
    6801             : 
    6802             :                         // Switch off buffer mode
    6803      150099 :                         if (not userBufferMode_p)
    6804             :                         {
    6805      150099 :                                 setBufferMode(false);
    6806      150099 :                                 weightSpectrum_p = NULL;
    6807             :                         }
    6808      150099 :                 }
    6809             :                 // Within AveragingTvi2 SIGMA_SPECTRUM is already re-defined to 1/sqrt(WEIGHT_SPECTRUM) if CORRECTED->DATA
    6810             :                 // or obtained from the input SIGMA_SPECTRUM in the case of DATA->DATA or multiple column operation
    6811       21392 :                 else if (timeAverage_p)
    6812             :                 {
    6813             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6814       11840 :                         if (userBufferMode_p)
    6815             :                         {
    6816           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6817             :                         }
    6818             :                         else
    6819             :                         {
    6820       11840 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6821             :                         }
    6822       11840 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6823             : 
    6824       11840 :                         if (userBufferMode_p)
    6825             :                         {
    6826           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6827             :                         }
    6828             :                         else
    6829             :                         {
    6830       11840 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6831             :                         }
    6832       11840 :                         transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6833             :                 }
    6834             :                 // When CORRECTED becomes DATA, then SIGMA_SPECTRUM has to be re-defined to 1/sqrt(WEIGHT_SPECTRUM)
    6835        9552 :                 else if (correctedToData_p)
    6836             :                 {
    6837             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6838         389 :                         if (userBufferMode_p)
    6839             :                         {
    6840           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6841             :                         }
    6842             :                         else
    6843             :                         {
    6844         389 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6845             :                         }
    6846         389 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6847             : 
    6848         389 :                         if (userBufferMode_p)
    6849             :                         {
    6850           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6851             :                         }
    6852             :                         else
    6853             :                         {
    6854         389 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6855             :                         }
    6856             :                         // VI/VB only allocates and populates sigmaSpectrum on request
    6857             :                         // But its contents are not usable for this case
    6858             :                         // So we should just create a local storage
    6859         389 :                         Cube<Float> sigmaSpectrum;
    6860         389 :                         sigmaSpectrum = vb->weightSpectrum(); // Copy constructor does not use reference semantics, but deep copy
    6861             :                         // Apply transformation
    6862         389 :                         arrayTransformInPlace(sigmaSpectrum, vi::AveragingTvi2::weightToSigma);
    6863             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6864         389 :                         transformCubeOfData(vb,rowRef,sigmaSpectrum,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6865         389 :                 }
    6866             :                 // Pure split operation
    6867             :                 else
    6868             :                 {
    6869             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6870        9163 :                         if (userBufferMode_p)
    6871             :                         {
    6872           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6873             :                         }
    6874             :                         else
    6875             :                         {
    6876        9163 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6877             :                         }
    6878        9163 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6879             : 
    6880        9163 :                         if (userBufferMode_p)
    6881             :                         {
    6882           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6883             :                         }
    6884             :                         else
    6885             :                         {
    6886        9163 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6887             :                         }
    6888        9163 :                         transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6889             :                 }
    6890             : 
    6891             :                 // Switch aux Weight propagation on
    6892      171491 :                 propagateWeights(propagateWeights_p);
    6893             : 
    6894             :                 // Reset average and smooth kernels
    6895      171491 :                 setChannelAverageKernel(weightmode_p);
    6896      171491 :                 setSmoothingKernel(smoothmode_p);
    6897      171491 :     setSmoothingFourierKernel(MSTransformations::plainSmooth);
    6898      171491 :         }
    6899             : 
    6900      325881 :         return;
    6901             : }
    6902             : 
    6903             : 
    6904             : // ----------------------------------------------------------------------------------------
    6905             : // Set tile shape
    6906             : // ----------------------------------------------------------------------------------------
    6907     1015006 : template <class T> void MSTransformManager::setTileShape( RefRows &rowRef,
    6908             :                                                                                                                         ArrayColumn<T> &outputDataCol)
    6909             : {
    6910     1015006 :         IPosition outputCubeShape = getShape();
    6911     1015006 :         size_t nCorr = outputCubeShape(0);
    6912     1015006 :         size_t nChan = outputCubeShape(1);
    6913     1015006 :         ssize_t nRows = 1048576 / (sizeof(T)*nCorr*nChan);
    6914     1015006 :         IPosition outputPlaneShape(2,nCorr,nChan);
    6915     1015006 :         IPosition tileShape(3,nCorr,nChan,nRows);
    6916             : 
    6917     1015006 :         outputDataCol.setShape(rowRef.firstRow(),outputPlaneShape,tileShape);
    6918             : 
    6919     2030012 :         return;
    6920     1015006 : }
    6921             : 
    6922             : // explicit instatiation for the use from SDMSManager
    6923             : template void MSTransformManager::setTileShape<Float>(RefRows &, ArrayColumn<Float> &);
    6924             : template void MSTransformManager::setTileShape<bool>(RefRows &, ArrayColumn<bool> &);
    6925             : template void MSTransformManager::setTileShape<Complex>(RefRows &, ArrayColumn<Complex> &);
    6926             : 
    6927             : // ----------------------------------------------------------------------------------------
    6928             : //
    6929             : // ----------------------------------------------------------------------------------------
    6930      300114 : void MSTransformManager::transformAndWriteSpectrum(     vi::VisBuffer2 *vb,
    6931             :                                                                                                         RefRows &rowRef,
    6932             :                                                                                                         const Cube<Float> &inputSpectrum,
    6933             :                                                                                                         ArrayColumn<Float> &outputCubeCol,
    6934             :                                                                                                         ArrayColumn<Float> &outputMatrixCol,
    6935             :                                                                                                         MSTransformations::weightTransformation weightTransformation,
    6936             :                                                                                                         bool  /* flushSpectrumCube */)
    6937             : {
    6938             :         // Dummy auxiliary weightSpectrum
    6939      300114 :         const Cube<Float> applicableSpectrum;
    6940             : 
    6941             :         // Check if weight scaling has to be applied
    6942      300114 :         Float weightScale = 0, sigmaScale = 0;
    6943      300114 :         if (refFrameTransformation_p)
    6944             :         {
    6945        7180 :                 if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6946        7180 :                                 (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6947             :                 {
    6948        1392 :                         weightScale = newWeightFactorMap_p[vb->spectralWindows()(0)];
    6949             :                 }
    6950             : 
    6951        7180 :                 if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0))  != newSigmaFactorMap_p.end()) and
    6952        7180 :                                 (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6953             :                 {
    6954        1392 :                         sigmaScale = newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6955             :                 }
    6956             :         }
    6957             : 
    6958             :         // Apply transformations
    6959      300114 :         switch (weightTransformation)
    6960             :         {
    6961      150057 :                 case MSTransformations::transformWeight:
    6962             :                 {
    6963      150057 :                         dataBuffer_p = MSTransformations::weightSpectrum;
    6964      150057 :                         transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6965             : 
    6966      150057 :                         if (weightScale > 0) *weightSpectrum_p *= weightScale;
    6967             : 
    6968      150057 :                         break;
    6969             :                 }
    6970       29745 :                 case MSTransformations::transformWeightIntoSigma:
    6971             :                 {
    6972       29745 :                         if (userBufferMode_p)
    6973             :                         {
    6974           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6975           0 :                                 transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6976           0 :                                 arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
    6977             : 
    6978           0 :                                 if (sigmaScale > 0) *sigmaSpectrum_p *= sigmaScale;
    6979             :                         }
    6980             :                         else
    6981             :                         {
    6982       29745 :                                 transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6983       29745 :                                 arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
    6984             : 
    6985       29745 :                                 if (sigmaScale > 0) *weightSpectrum_p *= sigmaScale;
    6986             :                         }
    6987             : 
    6988       29745 :                         break;
    6989             :                 }
    6990      120312 :                 case MSTransformations::weightIntoSigma:
    6991             :                 {
    6992      120312 :                         if (userBufferMode_p)
    6993             :                         {
    6994             :                                 // WeightSpectrum is always transformed before sigmaSpectrum
    6995             :                                 // so copy weightSpectrum into sigmaSpectrum
    6996           0 :                                 sigmaSpectrum_p->operator =(*weightSpectrum_p);
    6997           0 :                                 arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
    6998             : 
    6999             :                                 // No need to scale in this case as it already happened before
    7000             :                         }
    7001             :                         else
    7002             :                         {
    7003             :                                 // WeightSpectrum is always transformed before sigmaSpectrum
    7004             :                                 // so transform directly weightSpectrum into sigmaSpectrum
    7005      120312 :                                 arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
    7006             : 
    7007             :                                 // No need to scale in this case as it already happened before
    7008             :                         }
    7009      120312 :                         break;
    7010             :                 }
    7011             :         }
    7012             : 
    7013             :         // Write resulting cube
    7014      300114 :         if ( (not userBufferMode_p) and flushWeightSpectrum_p)
    7015             :         {
    7016      229482 :                 setTileShape(rowRef,outputCubeCol);
    7017      229482 :                 writeCube(*weightSpectrum_p,outputCubeCol,rowRef);
    7018             :         }
    7019             : 
    7020             :         // Extract median matrix (nCorr x nRow)
    7021             :         // When separating SPWs this procedure computes the mean of each separated SPW
    7022             :         // Matrix<Float> medians = partialMedians(*weightSpectrum_p,IPosition(1,1),true);
    7023      300114 :         if (userBufferMode_p)
    7024             :         {
    7025           0 :                 switch (weightTransformation)
    7026             :                 {
    7027           0 :                         case MSTransformations::transformWeight:
    7028             :                         {
    7029           0 :                                 weight_p->operator =(vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p));
    7030           0 :                                 break;
    7031             :                         }
    7032           0 :                         case MSTransformations::transformWeightIntoSigma:
    7033             :                         {
    7034           0 :                                 sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
    7035           0 :                                 break;
    7036             :                         }
    7037           0 :                         case MSTransformations::weightIntoSigma:
    7038             :                         {
    7039           0 :                                 sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
    7040           0 :                                 break;
    7041             :                         }
    7042             :                 }
    7043             :         }
    7044             :         else
    7045             :         {
    7046      300114 :                 Matrix<Float> means = vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p);
    7047      300114 :                 writeMatrix(means,outputMatrixCol,rowRef,1);
    7048      300114 :         }
    7049             : 
    7050      600228 :         return;
    7051      300114 : }
    7052             : 
    7053             : // -----------------------------------------------------------------------
    7054             : // Get *_SPECTRUM column to use depending on the input col
    7055             : // -----------------------------------------------------------------------
    7056      414986 : const Cube<Float>& MSTransformManager::getApplicableSpectrum(vi::VisBuffer2 *vb, MS::PredefinedColumns datacol)
    7057             : {
    7058      414986 :         if (propagateWeights_p)
    7059             :         {
    7060       29887 :                 switch (datacol)
    7061             :                 {
    7062       17679 :                         case MS::DATA:
    7063             :                         {
    7064             :                                 // NOTE: There is room for optimization here if in the case of
    7065             :                                 // A.- Time average and single column operation
    7066             :                                 // B.- Single column in the input (George denied this)
    7067             :                                 // C.- Time average should not convert SIGMA_SPECTRUM to WEIGHT format if there is chan.avg downstream
    7068             :                                 // D.- SIGMA_SPECTRUM should be in WEIGHT format
    7069       17679 :                                 return getWeightSpectrumFromSigmaSpectrum(vb);
    7070             :                                 break;
    7071             :                         }
    7072        6662 :                         case MS::CORRECTED_DATA:
    7073             :                         {
    7074        6662 :                                 return vb->weightSpectrum();
    7075             :                                 break;
    7076             :                         }
    7077        5546 :                         case MS::MODEL_DATA:
    7078             :                         {
    7079             :                                 // Return either WEIGHT_SPECTRUM or SIGMA_SPECTRUM depending on the other accompany col
    7080        5546 :                                 if (doingCorrected_p)
    7081             :                                 {
    7082        3242 :                                         return vb->weightSpectrum();
    7083             :                                 }
    7084        2304 :                                 else if (doingData_p)
    7085             :                                 {
    7086           0 :                                         return getWeightSpectrumFromSigmaSpectrum(vb);
    7087             :                                 }
    7088             :                                 // When doing only MODEL_DATA only FLAG cube is used, and applicable weightSpectrum must be flat unit
    7089             :                                 // The same convention is applied in VbAvg::accumulateElementForCubes for time average
    7090             :                                 else
    7091             :                                 {
    7092        2304 :                                         return getWeightSpectrumFlat(vb);
    7093             :                                 }
    7094             : 
    7095             :                                 break;
    7096             :                         }
    7097           0 :                         default:
    7098             :                         {
    7099           0 :                                 return vb->weightSpectrum();
    7100             :                                 break;
    7101             :                         }
    7102             :                 }
    7103             :         }
    7104             :         else
    7105             :         {
    7106      385099 :                 return weightSpectrumCubeDummy_p;
    7107             :         }
    7108             : }
    7109             : 
    7110             : // -----------------------------------------------------------------------
    7111             : // Get output weight column
    7112             : // -----------------------------------------------------------------------
    7113      685796 : ArrayColumn<Float>&  MSTransformManager::getOutputWeightColumn(vi::VisBuffer2 *, MS::PredefinedColumns datacol)
    7114             : {
    7115      685796 :         if (userBufferMode_p)
    7116             :         {
    7117           0 :                 return dummyWeightCol_p;
    7118             :         }
    7119             :         else
    7120             :         {
    7121      685796 :                 switch (datacol)
    7122             :                 {
    7123      192841 :                         case MS::WEIGHT_SPECTRUM:
    7124             :                         {
    7125      192841 :                                 return outputMsCols_p->weightSpectrum();
    7126             :                                 break;
    7127             :                         }
    7128      192841 :                         case MS::SIGMA_SPECTRUM:
    7129             :                         {
    7130      192841 :                                 return outputMsCols_p->sigmaSpectrum();
    7131             :                                 break;
    7132             :                         }
    7133      150057 :                         case MS::WEIGHT:
    7134             :                         {
    7135      150057 :                                 return outputMsCols_p->weight();
    7136             :                                 break;
    7137             :                         }
    7138      150057 :                         case MS::SIGMA:
    7139             :                         {
    7140      150057 :                                 return outputMsCols_p->sigma();
    7141             :                                 break;
    7142             :                         }
    7143           0 :                         default:
    7144             :                         {
    7145           0 :                                 return outputMsCols_p->weight();
    7146             :                                 break;
    7147             :                         }
    7148             :                 }
    7149             :         }
    7150             : }
    7151             : 
    7152             : 
    7153             : // -----------------------------------------------------------------------
    7154             : // Pupulate weightSpectrum derived from sigmaSpectrum
    7155             : // -----------------------------------------------------------------------
    7156       94247 : const Cube<Float>& MSTransformManager::getWeightSpectrumFromSigmaSpectrum(vi::VisBuffer2 *vb)
    7157             : {
    7158       94247 :         if (weightSpectrumFromSigmaFilled_p)
    7159             :         {
    7160       13331 :                 return weightSpectrumCube_p;
    7161             :         }
    7162             :         else
    7163             :         {
    7164       80916 :                 weightSpectrumCube_p.resize(vb->getShape(),false);
    7165       80916 :                 weightSpectrumCube_p = vb->sigmaSpectrum(); // = Operator makes a copy
    7166       80916 :                 arrayTransformInPlace (weightSpectrumCube_p,vi::AveragingTvi2::sigmaToWeight);
    7167       80916 :                 weightSpectrumFromSigmaFilled_p = true;
    7168       80916 :                 return weightSpectrumCube_p;
    7169             :         }
    7170             : }
    7171             : 
    7172             : // -----------------------------------------------------------------------
    7173             : // Populate a synthetic flat unit weightSpectrum to be use for MODEL_DATA
    7174             : // -----------------------------------------------------------------------
    7175       31168 : const Cube<Float>& MSTransformManager::getWeightSpectrumFlat(vi::VisBuffer2 *vb)
    7176             : {
    7177       31168 :         if (weightSpectrumFlatFilled_p)
    7178             :         {
    7179           0 :                 return weightSpectrumCubeFlat_p;
    7180             :         }
    7181       31168 :         else if (weightSpectrumCubeFlat_p.shape().isEqual(vb->getShape()))
    7182             :         {
    7183       31148 :                 weightSpectrumFlatFilled_p = true;
    7184       31148 :                 return weightSpectrumCubeFlat_p;
    7185             :         }
    7186             :         else
    7187             :         {
    7188          20 :                 weightSpectrumCubeFlat_p.resize(vb->getShape(),false);
    7189          20 :                 weightSpectrumCubeFlat_p = 1.0f;
    7190          20 :                 weightSpectrumFlatFilled_p = true;
    7191          20 :                 return weightSpectrumCubeFlat_p;
    7192             :         }
    7193             : }
    7194             : 
    7195             : // -----------------------------------------------------------------------
    7196             : // Generic method to write a Matrix from a VisBuffer into a ArrayColumn
    7197             : // -----------------------------------------------------------------------
    7198      977670 : template <class T> void MSTransformManager::writeMatrix(  const Matrix<T> &inputMatrix,
    7199             :                                                                                                                                 ArrayColumn<T> &outputCol,
    7200             :                                                                                                                                 RefRows &rowRef,
    7201             :                                                                                                                                 uInt nBlocks)
    7202             : {
    7203      977670 :         if (nBlocks == 1)
    7204             :         {
    7205      975699 :                  outputCol.putColumnCells(rowRef, inputMatrix);
    7206             :         }
    7207             :         else
    7208             :         {
    7209             :                 // jagonzal (CAS-8492): Huge bug, each input row must
    7210             :                 // be copied n times not the whole matrix n times
    7211        1971 :                 uInt outRowIdx = 0;
    7212        1971 :                 size_t nInputRows = inputMatrix.shape()(1);
    7213        1971 :                 Matrix<T> outputMatrix(IPosition(2,3,nInputRows*nBlocks));
    7214       14664 :                 for (size_t inputRowIdx = 0; inputRowIdx<nInputRows; inputRowIdx++)
    7215             :                 {
    7216       72429 :                         for (uInt blockIdx = 0; blockIdx<nBlocks; blockIdx++)
    7217             :                         {
    7218       59736 :                                 outputMatrix.column(outRowIdx) = inputMatrix.column(inputRowIdx);
    7219       59736 :                                 outRowIdx += 1;
    7220             :                         }
    7221             :                 }
    7222             : 
    7223        1971 :                 RefRows outRowRef(rowRef.firstRow(),rowRef.firstRow()+nInputRows*nBlocks-1);
    7224        1971 :                 outputCol.putColumnCells(outRowRef, outputMatrix);
    7225             : 
    7226             :                 /*
    7227             :                 uInt offset = 0;
    7228             :                 for (uInt block_i=0;block_i<nBlocks;block_i++)
    7229             :                 {
    7230             :                         uInt startRow_i = rowRef.firstRow()+offset;
    7231             :                         RefRows rowRef_i(startRow_i, startRow_i+inputMatrix.shape()(1)-1);
    7232             :                     outputCol.putColumnCells(rowRef_i, inputMatrix);
    7233             :                     offset += inputMatrix.shape()(1);
    7234             :                 }
    7235             :                 */
    7236        1971 :         }
    7237      977670 :         return;
    7238             : }
    7239             : 
    7240             : // -----------------------------------------------------------------------
    7241             : // Generic method to write a Cube from a VisBuffer into a ArrayColumn
    7242             : // -----------------------------------------------------------------------
    7243      655327 : template <class T> void MSTransformManager::writeCube(    const Cube<T> &inputCube,
    7244             :                                                                                                                         ArrayColumn<T> &outputCol,
    7245             :                                                                                                                         RefRows &rowRef)
    7246             : {
    7247      655327 :         IPosition shape = inputCube.shape();
    7248      655327 :         shape(2) = rowRef.nrows();
    7249             :         bool deleteIt;
    7250      655327 :     Array<T> outputArray(shape,const_cast<T*>(inputCube.getStorage(deleteIt)),SHARE);
    7251      655327 :     outputCol.putColumnCells(rowRef, outputArray);
    7252             : 
    7253     1310654 :         return;
    7254      655327 : }
    7255             : 
    7256             : // explicit instatiation for the use from SDMSManager
    7257             : template void MSTransformManager::writeCube<bool>(const Cube<bool> &, ArrayColumn<bool> &, RefRows &);
    7258             : 
    7259             : // -----------------------------------------------------------------------
    7260             : //
    7261             : // -----------------------------------------------------------------------
    7262      395204 : void MSTransformManager::transformCubeOfData(   vi::VisBuffer2 *vb,
    7263             :                                                                                                         RefRows &rowRef,
    7264             :                                                                                                         const Cube<Complex> &inputDataCube,
    7265             :                                                                                                         ArrayColumn<Complex> &outputDataCol,
    7266             :                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7267             :                                                                                                         const Cube<Float> &inputWeightCube)
    7268             : {
    7269      395204 :         (*this.*transformCubeOfDataComplex_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
    7270      395204 :         return;
    7271             : }
    7272             : 
    7273             : // -----------------------------------------------------------------------
    7274             : //
    7275             : // -----------------------------------------------------------------------
    7276      242368 : void MSTransformManager::transformCubeOfData(   vi::VisBuffer2 *vb,
    7277             :                                                                                                         RefRows &rowRef,
    7278             :                                                                                                         const Cube<Float> &inputDataCube,
    7279             :                                                                                                         ArrayColumn<Float> &outputDataCol,
    7280             :                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7281             :                                                                                                         const Cube<Float> &inputWeightCube)
    7282             : {
    7283      242368 :         (*this.*transformCubeOfDataFloat_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
    7284      242368 :         return;
    7285             : }
    7286             : 
    7287             : // -----------------------------------------------------------------------
    7288             : //
    7289             : // -----------------------------------------------------------------------
    7290      248190 : template <class T> void MSTransformManager::copyCubeOfData(       vi::VisBuffer2 *vb,
    7291             :                                                                                                                                 RefRows &rowRef,
    7292             :                                                                                                                                 const Cube<T> &inputDataCube,
    7293             :                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7294             :                                                                                                                                 ArrayColumn<bool> *outputFlagCol,
    7295             :                                                                                                                                 const Cube<Float> & /* inputWeightCube */)
    7296             : {
    7297      248190 :         writeCube(inputDataCube,outputDataCol,rowRef);
    7298      248190 :         if (outputFlagCol != NULL)
    7299             :         {
    7300      175819 :                 writeCube(vb->flagCube(),*outputFlagCol,rowRef);
    7301             :         }
    7302             : 
    7303      248190 :         return;
    7304             : }
    7305             : 
    7306             : // -----------------------------------------------------------------------
    7307             : // combine - for combinespws=True
    7308             : // -----------------------------------------------------------------------
    7309       16655 : template <class T> void MSTransformManager::combineCubeOfData(    vi::VisBuffer2 *vb,
    7310             :                                                                                                                                         RefRows &rowRef,
    7311             :                                                                                                                                         const Cube<T> &inputDataCube,
    7312             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7313             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7314             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7315             : {
    7316             :         // Write flag column too?
    7317       16655 :         if (outputFlagCol != NULL)
    7318             :         {
    7319        7234 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7320        7234 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7321        7234 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7322             :         }
    7323             :         else
    7324             :         {
    7325        9421 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7326        9421 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7327        9421 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7328             :         }
    7329             : 
    7330             :         // Get input flag cube
    7331       16655 :         const Cube<bool> inputFlagCube = vb->flagCube();
    7332             : 
    7333             :         // Get input SPWs and exposures
    7334       16655 :         Vector<Int> spws = vb->spectralWindows();
    7335       16655 :         Vector<Double> exposures = vb->exposure();
    7336             : 
    7337             :         // Get input cube shape
    7338       16655 :         IPosition inputCubeShape = inputDataCube.shape();
    7339       16655 :         uInt nInputCorrelations = inputCubeShape(0);
    7340             : 
    7341             :         // Initialize input planes
    7342       16655 :         IPosition inputPlaneShape(2,nInputCorrelations, numOfCombInputChanMap_p[0]);
    7343       16655 :         Matrix<Double> normalizingFactorPlane(inputPlaneShape);
    7344       16655 :         Matrix<T> inputPlaneData(inputPlaneShape);
    7345       16655 :         Matrix<bool> inputPlaneFlags(inputPlaneShape,false);
    7346       16655 :         Matrix<Float> inputPlaneWeights(inputPlaneShape);
    7347             : 
    7348             :         // Initialize output planes
    7349       16655 :         IPosition outputPlaneShape(2,nInputCorrelations, inputOutputSpwMap_p[0].second.NUM_CHAN);
    7350       16655 :         Matrix<T> outputPlaneData(outputPlaneShape);
    7351       16655 :         Matrix<bool> outputPlaneFlags(outputPlaneShape);
    7352             : 
    7353       16655 :         Int spw = 0;
    7354             :         Double weight;
    7355             :         uInt inputChannel;
    7356             :         bool inputChanelFlag;
    7357             :         Double normalizingFactor;
    7358       16655 :         uInt row = 0, baseline_index = 0;
    7359       16655 :         vector<uInt> baselineRows;
    7360       16655 :         map<Int, uInt> spwRowMap;
    7361       16655 :         map<Int, uInt>::iterator spwRowMapIter;
    7362       16655 :         map<Int, uInt> spwFractionCountsMap;
    7363       16655 :         bool unityContributors = false;
    7364       16655 :         vector< channelContribution > contributions;
    7365       16655 :         vector< channelContribution >::iterator contributionsIter;
    7366       16655 :         map < Int , map < uInt, bool > > removeContributionsMap;
    7367             : 
    7368       16655 :         bool combinationOfSPWsWithDifferentExposure = false;
    7369       16655 :         Double exposure = 0;
    7370             : 
    7371       16655 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7372     1060363 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    7373             :         {
    7374             :                 // Initialize input plane
    7375     1043708 :                 inputPlaneData = 0.0;
    7376             : 
    7377             :                 // Initialize weights plane
    7378     1043708 :                 inputPlaneWeights = 0.0;
    7379             : 
    7380             :                 // Initialize normalizing factor plane
    7381     1043708 :                 normalizingFactorPlane = 0.0;
    7382             : 
    7383             :                 // Fill input plane to benefit from contiguous access to the input cube
    7384     1043708 :                 baselineRows = iter->second;
    7385             : 
    7386             :                 // Create spw-row map for this baseline and initialize detection of SPWs with different exposure
    7387     1043708 :                 spwRowMap.clear();
    7388     1043708 :                 if (combinationOfSPWsWithDifferentExposure_p and (inputWeightCube.shape().isEqual(inputCubeShape)))
    7389             :                 {
    7390           0 :                         combinationOfSPWsWithDifferentExposure = true;
    7391           0 :                         addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
    7392           0 :                         for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    7393             :                         {
    7394           0 :                                 row = *iter_row;
    7395           0 :                                 spw = spws(row);
    7396           0 :                                 spwRowMap[spw]=row;
    7397             :                         }
    7398             :                 }
    7399             :                 else
    7400             :                 {
    7401     1043708 :                         exposure = exposures(*baselineRows.begin());
    7402     1043708 :                         combinationOfSPWsWithDifferentExposure = false;
    7403     3735430 :                         for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    7404             :                         {
    7405     2691722 :                                 row = *iter_row;
    7406     2691722 :                                 spw = spws(row);
    7407     2691722 :                                 spwRowMap[spw]=row;
    7408             : 
    7409             :                                 // In the case of *_SPECTRUM inputWeightCube is dummy
    7410     2691722 :                                 if ((abs(exposure - exposures(row)) > FLT_EPSILON) and (inputWeightCube.shape().isEqual(inputCubeShape)))
    7411             :                                 {
    7412           2 :                                         combinationOfSPWsWithDifferentExposure = true;
    7413             :                                 }
    7414             :                         }
    7415             : 
    7416     1043708 :                         if (combinationOfSPWsWithDifferentExposure)
    7417             :                         {
    7418           2 :                                 combinationOfSPWsWithDifferentExposure_p = true;
    7419           2 :                                 addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
    7420           2 :                                 if (inputWeightSpectrumAvailable_p)
    7421             :                                 {
    7422           4 :                                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    7423             :                                                                 << "Detected combination of SPWs with different EXPOSURE "<< endl
    7424             :                                                                 << "Will use WEIGHT_SPECTRUM to combine them "<< endl
    7425           4 :                                                                 << LogIO::POST;
    7426             :                                 }
    7427             :                                 else
    7428             :                                 {
    7429           0 :                                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    7430             :                                                                 << "Detected combination of SPWs with different EXPOSURE "<< endl
    7431             :                                                                 << "Will use WEIGHT to combine them (WEIGHT_SPECTRUM not available)"<< endl
    7432           0 :                                                                 << LogIO::POST;
    7433             :                                 }
    7434             :                         }
    7435             :                         else
    7436             :                         {
    7437     1043706 :                                 addWeightSpectrumContribution_p = &MSTransformManager::dontAddWeightSpectrumContribution;
    7438             :                         }
    7439             :                 }
    7440             : 
    7441             : 
    7442    91465149 :                 for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
    7443             :                 {
    7444    90421441 :                         contributions = inputOutputChanFactorMap_p[outputChannel];
    7445             : 
    7446   254016246 :                         for (uInt pol = 0; pol < inputDataCube.shape()(0); pol++)
    7447             :                         {
    7448   163594805 :                                 spwFractionCountsMap.clear();
    7449   163594805 :                                 unityContributors = false;
    7450             : 
    7451             :                                 // Go through list of contributors for this output channel and polarization and gather flags info
    7452   388946006 :                                 for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
    7453             :                                 {
    7454   225351201 :                                         inputChannel = contributionsIter->inpChannel;
    7455   225351201 :                                         weight = contributionsIter->weight;
    7456             : 
    7457             :                                         // Add WEIGHT_SPECTRUM to the contribution
    7458   225351201 :                                         (*this.*addWeightSpectrumContribution_p)(weight,pol,inputChannel,row,inputWeightCube);
    7459             : 
    7460             :                                         // Find row for this input channel
    7461   225351201 :                                         spw = contributionsIter->inpSpw;
    7462   225351201 :                                         spwRowMapIter = spwRowMap.find(spw);
    7463   225351201 :                                         if (spwRowMapIter != spwRowMap.end())
    7464             :                                         {
    7465   199526197 :                                                 row = spwRowMap[spw];
    7466             : 
    7467             :                                                 // Fill flags info
    7468   199526197 :                                                 inputChanelFlag = inputFlagCube(pol,inputChannel,row);
    7469   199526197 :                                                 contributionsIter->flag = inputChanelFlag;
    7470             : 
    7471             :                                                 // Count input channel if it is not flagged and has non-unity overlapping fraction
    7472   199526197 :                                                 if (weight<1.0)
    7473             :                                                 {
    7474    44188854 :                                                         if (!inputChanelFlag) spwFractionCountsMap[spw] += 1;
    7475             :                                                 }
    7476             :                                                 // Count if we have valid unity contributors, otherwise we don't discard non-unity contributors
    7477             :                                                 else
    7478             :                                                 {
    7479   155337343 :                                                         unityContributors = true;
    7480             :                                                 }
    7481             :                                         }
    7482             :                                         else
    7483             :                                         {
    7484             :                                                 // Fill flags info
    7485    25825004 :                                                 contributionsIter->flag = true;
    7486             :                                         }
    7487             :                                 }
    7488             : 
    7489             :                                 // Remove contributions from SPWs with odd numbers of contributors with non-unity
    7490             :                                 // overlap fraction which could influence the averaging asymmetrically
    7491   388946006 :                                 for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
    7492             :                                 {
    7493   225351201 :                                         inputChannel = contributionsIter->inpChannel;
    7494   225351201 :                                         weight = contributionsIter->weight;
    7495   225351201 :                                         spw = contributionsIter->inpSpw;
    7496             : 
    7497             :                                         // Find row for this input channel
    7498   225351201 :                                         if (!contributionsIter->flag)
    7499             :                                         {
    7500             :                                                 // jagonzal: Caution, accessing the map populates it!!!
    7501   180942367 :                                                 row = spwRowMap[spw];
    7502             : 
    7503   180942367 :                                                 if ((spwFractionCountsMap[spw] % 2 == 0) or (weight >= 1.0) or (!unityContributors))
    7504             :                                                 {
    7505   179910805 :                                                         inputPlaneData(pol,outputChannel) += weight*inputDataCube(pol,inputChannel,row);
    7506   179910805 :                                                         normalizingFactorPlane(pol,outputChannel) += weight;
    7507   179910805 :                                                         (*this.*fillWeightsPlane_p)(pol,inputChannel,outputChannel,row,inputWeightCube,inputPlaneWeights,weight);
    7508             :                                                 }
    7509             :                                         }
    7510             :                                 }
    7511             :                         }
    7512             :                 }
    7513             : 
    7514             :                 // Normalize combined data and determine input plane flags
    7515     1043708 :                 inputPlaneFlags = false;
    7516    91465149 :                 for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
    7517             :                 {
    7518   254016246 :                         for (uInt pol = 0; pol < nInputCorrelations; pol++)
    7519             :                         {
    7520   163594805 :                                 normalizingFactor = normalizingFactorPlane(pol,outputChannel);
    7521   163594805 :                                 if (normalizingFactor >= 0.999999) // we lose a couple significant digits in the subtractions
    7522             :                                 {
    7523   156582441 :                                         inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7524             : 
    7525             :                                         // Normalize weights plane
    7526   156582441 :                                         (*this.*normalizeWeightsPlane_p)(pol,outputChannel,inputPlaneWeights,normalizingFactorPlane);
    7527             :                                 }
    7528     7012364 :                                 else if (normalizingFactor > 0)
    7529             :                                 {
    7530       33846 :                                         inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7531       33846 :                                         inputPlaneFlags(pol,outputChannel) = true;
    7532             :                                 }
    7533             :                                 else
    7534             :                                 {
    7535     6978518 :                                         inputPlaneFlags(pol,outputChannel) = true;
    7536             :                                 }
    7537             :                         }
    7538             :                 }
    7539             : 
    7540             :                 // Initialize output flags plane
    7541     1043708 :                 outputPlaneFlags = false;
    7542             : 
    7543             :                 // Transform input planes and write them
    7544     1043708 :                 transformAndWritePlaneOfData(   0,rowRef.firstRow()+baseline_index*nspws_p,
    7545             :                                                                                 inputPlaneData,inputPlaneFlags,inputPlaneWeights,
    7546             :                                                                                 outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
    7547             : 
    7548             : 
    7549     1043708 :                 relativeRow_p += nspws_p;
    7550     1043708 :                 baseline_index += 1;
    7551             :         }
    7552             : 
    7553       33310 :         return;
    7554       16655 : }
    7555             : 
    7556             : // -----------------------------------------------------------------------
    7557             : //
    7558             : // -----------------------------------------------------------------------
    7559         138 : void MSTransformManager::addWeightSpectrumContribution( Double &weight,
    7560             :                                                                                                                         uInt &pol,
    7561             :                                                                                                                         uInt &inputChannel,
    7562             :                                                                                                                         uInt &row,
    7563             :                                                                                                                         const Cube<Float> &inputWeightsCube)
    7564             : {
    7565         138 :         weight *= inputWeightsCube(pol,inputChannel,row);
    7566             : 
    7567         138 :         return;
    7568             : }
    7569             : 
    7570             : // -----------------------------------------------------------------------
    7571             : //
    7572             : // -----------------------------------------------------------------------
    7573   225351063 : void MSTransformManager::dontAddWeightSpectrumContribution(     Double &,
    7574             :                                                                                                                                 uInt &,
    7575             :                                                                                                                                 uInt &,
    7576             :                                                                                                                                 uInt &,
    7577             :                                                                                                                                 const Cube<Float> &)
    7578             : {
    7579   225351063 :         return;
    7580             : }
    7581             : 
    7582             : // -----------------------------------------------------------------------
    7583             : //
    7584             : // -----------------------------------------------------------------------
    7585    47536734 : void MSTransformManager::fillWeightsPlane(      uInt pol,
    7586             :                                                                                                 uInt inputChannel,
    7587             :                                                                                                 uInt outputChannel,
    7588             :                                                                                                 uInt inputRow,
    7589             :                                                                                                 const Cube<Float> &inputWeightsCube,
    7590             :                                                                                                 Matrix<Float> &inputWeightsPlane,
    7591             :                                                                                                 Double factor)
    7592             : {
    7593    47536734 :         inputWeightsPlane(pol,outputChannel) += factor*inputWeightsCube(pol,inputChannel,inputRow);
    7594             : 
    7595    47536734 :         return;
    7596             : }
    7597             : 
    7598             : // -----------------------------------------------------------------------
    7599             : //
    7600             : // -----------------------------------------------------------------------
    7601    38844697 : void MSTransformManager::normalizeWeightsPlane( uInt pol,
    7602             :                                                                                                         uInt outputChannel,
    7603             :                                                                                                         Matrix<Float> &inputPlaneWeights,
    7604             :                                                                                                         Matrix<Double> &normalizingFactorPlane)
    7605             : {
    7606    38844697 :         inputPlaneWeights(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7607             : 
    7608    38844697 :         return;
    7609             : }
    7610             : 
    7611             : // -----------------------------------------------------------------------
    7612             : //
    7613             : // -----------------------------------------------------------------------
    7614      348183 : template <class T> void MSTransformManager::averageCubeOfData(    vi::VisBuffer2 *vb,
    7615             :                                                                                                                                         RefRows &rowRef,
    7616             :                                                                                                                                         const Cube<T> &inputDataCube,
    7617             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7618             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7619             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7620             : {
    7621             :         // Get input spw and flag and weight cubes
    7622      348183 :         Int inputSpw = vb->spectralWindows()(0);
    7623      348183 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7624             : 
    7625             :         // Define output plane shape
    7626      348183 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), numOfOutChanMap_p[inputSpw]);
    7627             : 
    7628      348183 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7629             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7630             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7631             : 
    7632      696366 :         return;
    7633      348183 : }
    7634             : 
    7635             : // -----------------------------------------------------------------------
    7636             : //
    7637             : // -----------------------------------------------------------------------
    7638        4781 : template <class T> void MSTransformManager::smoothCubeOfData(     vi::VisBuffer2 *vb,
    7639             :                                                                                                                                         RefRows &rowRef,
    7640             :                                                                                                                                         const Cube<T> &inputDataCube,
    7641             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7642             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7643             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7644             : {
    7645             :         // Get input spw and flag cube
    7646        4781 :         Int inputSpw = vb->spectralWindows()(0);
    7647        4781 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7648             : 
    7649             :         // Define output plane shape
    7650        4781 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputDataCube.shape()(1));
    7651             : 
    7652             :         // Transform cube
    7653        4781 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7654             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7655             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7656             : 
    7657        9562 :         return;
    7658        4781 : }
    7659             : 
    7660             : // -----------------------------------------------------------------------
    7661             : //
    7662             : // -----------------------------------------------------------------------
    7663       19763 : template <class T> void MSTransformManager::regridCubeOfData(     vi::VisBuffer2 *vb,
    7664             :                                                                                                                                         RefRows &rowRef,
    7665             :                                                                                                                                         const Cube<T> &inputDataCube,
    7666             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7667             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7668             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7669             : {
    7670             :         // Get input spw and flag cube
    7671       19763 :         Int inputSpw = vb->spectralWindows()(0);
    7672       19763 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7673             : 
    7674             :         // Define output plane shape
    7675       19763 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputOutputSpwMap_p[inputSpw].second.NUM_CHAN);
    7676             : 
    7677             :         // Transform cube
    7678       19763 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7679             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7680             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7681             : 
    7682       39526 :         return;
    7683       19763 : }
    7684             : 
    7685             : // -----------------------------------------------------------------------
    7686             : //
    7687             : // -----------------------------------------------------------------------
    7688      372727 : template <class T> void MSTransformManager::transformAndWriteCubeOfData(  Int inputSpw,
    7689             :                                                                                                                                                                 RefRows &rowRef,
    7690             :                                                                                                                                                                 const Cube<T> &inputDataCube,
    7691             :                                                                                                                                                                 const Cube<bool> &inputFlagsCube,
    7692             :                                                                                                                                                                 const Cube<Float> &inputWeightsCube,
    7693             :                                                                                                                                                                 IPosition &outputPlaneShape,
    7694             :                                                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7695             :                                                                                                                                                                 ArrayColumn<bool> *outputFlagCol)
    7696             : {
    7697      745454 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    7698             :                  << "Shape of input data cube: " << inputDataCube.shape()
    7699             :                  << ", output plane shape: " << outputPlaneShape
    7700      745454 :                  << LogIO::POST;
    7701             : 
    7702             :         // Write flag column too?
    7703      372727 :         if (outputFlagCol != NULL)
    7704             :         {
    7705      142865 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7706      142865 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7707      142865 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7708             :         }
    7709             :         else
    7710             :         {
    7711      229862 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7712      229862 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7713      229862 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7714             :         }
    7715             : 
    7716             :         // Get input number of rows
    7717      372727 :         uInt nInputRows = inputDataCube.shape()(2);
    7718             : 
    7719             :         // Initialize input planes
    7720      372727 :         Matrix<T> inputPlaneData;
    7721      372727 :         Matrix<bool> inputPlaneFlags;
    7722      372727 :         Matrix<Float> inputPlaneWeights;
    7723             : 
    7724             :         // Initialize output planes
    7725      372727 :         Matrix<T> outputPlaneData(outputPlaneShape);
    7726      372727 :         Matrix<bool> outputPlaneFlags(outputPlaneShape);
    7727             : 
    7728             :         // Iterate row by row in order to extract a plane
    7729      372727 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7730     4596299 :         for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
    7731             :         {
    7732             :                 // Initialize output flags plane
    7733     4223572 :                 outputPlaneFlags = false;
    7734             : 
    7735             :                 // Fill input planes by reference
    7736     4223572 :                 inputPlaneData = inputDataCube.xyPlane(rowIndex);
    7737     4223572 :                 inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
    7738     4223572 :                 (*this.*setWeightsPlaneByReference_p)(rowIndex,inputWeightsCube,inputPlaneWeights);
    7739             : 
    7740             :                 // Transform input planes and write them
    7741     4223572 :                 transformAndWritePlaneOfData(   inputSpw,rowRef.firstRow()+rowIndex*nspws_p,
    7742             :                                                                                 inputPlaneData,inputPlaneFlags,inputPlaneWeights,
    7743             :                                                                                 outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
    7744             : 
    7745     4223572 :                 relativeRow_p += nspws_p;
    7746             :         }
    7747             : 
    7748      745454 :         return;
    7749      372727 : }
    7750             : 
    7751             : // -----------------------------------------------------------------------
    7752             : //
    7753             : // -----------------------------------------------------------------------
    7754           0 : template <class T> void MSTransformManager::separateCubeOfData(   vi::VisBuffer2 *vb,
    7755             :                                                                                                                                         RefRows &rowRef,
    7756             :                                                                                                                                         const Cube<T> &inputDataCube,
    7757             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7758             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7759             :                                                                                                                                         const Cube<Float> & /* inputWeightCube */)
    7760             : {
    7761             :         // Write flag column too?
    7762           0 :         if (outputFlagCol != NULL)
    7763             :         {
    7764           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7765           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7766           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7767             :         }
    7768             :         else
    7769             :         {
    7770           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7771           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7772           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7773             :         }
    7774             : 
    7775             :         // Get input flags, spw and number of rows
    7776           0 :         uInt nInputRows = inputDataCube.shape()(2);
    7777           0 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7778             : 
    7779             :         // Initialize input planes
    7780           0 :         Matrix<T> inputPlaneData;
    7781           0 :         Matrix<bool> inputPlaneFlags;
    7782             : 
    7783             :         // Iterate row by row in order to extract a plane
    7784           0 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7785           0 :         for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
    7786             :         {
    7787             :                 // Fill input planes by reference
    7788           0 :                 inputPlaneData = inputDataCube.xyPlane(rowIndex);
    7789           0 :                 inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
    7790             : 
    7791             :                 // Directly write output plane
    7792           0 :                 writeOutputPlanes(      rowRef.firstRow()+rowIndex*nspws_p,
    7793             :                                                         inputPlaneData,inputPlaneFlags,
    7794             :                                                         outputDataCol,*outputFlagCol);
    7795             : 
    7796           0 :                 relativeRow_p += nspws_p;
    7797             :         }
    7798             : 
    7799           0 :         return;
    7800           0 : }
    7801             : 
    7802             : // -----------------------------------------------------------------------
    7803             : //
    7804             : // -----------------------------------------------------------------------
    7805      400146 : void MSTransformManager::setWeightsPlaneByReference(    uInt inputRow,
    7806             :                                                                                                                         const Cube<Float> &inputWeightsCube,
    7807             :                                                                                                                         Matrix<Float> &inputWeightsPlane)
    7808             : {
    7809      400146 :         inputWeightsPlane = inputWeightsCube.xyPlane(inputRow);
    7810      400146 : }
    7811             : 
    7812             : // -----------------------------------------------------------------------
    7813             : //
    7814             : // -----------------------------------------------------------------------
    7815     5267280 : template <class T> void MSTransformManager::transformAndWritePlaneOfData( Int inputSpw,
    7816             :                                                                                                                                                                 uInt row,
    7817             :                                                                                                                                                                 Matrix<T> &inputDataPlane,
    7818             :                                                                                                                                                                 Matrix<bool> &inputFlagsPlane,
    7819             :                                                                                                                                                                 Matrix<Float> &inputWeightsPlane,
    7820             :                                                                                                                                                                 Matrix<T> &outputDataPlane,
    7821             :                                                                                                                                                                 Matrix<bool> &outputFlagsPlane,
    7822             :                                                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7823             :                                                                                                                                                                 ArrayColumn<bool> *outputFlagCol)
    7824             : {
    7825             :         // Get input number of correlations
    7826     5267280 :         uInt nCorrs = inputDataPlane.shape()(0);
    7827             : 
    7828             :         // Get output plane shape
    7829     5267280 :         IPosition outputPlaneShape = outputDataPlane.shape();
    7830             : 
    7831             :         // Initialize vectors
    7832     5267280 :         Vector<T> inputDataStripe;
    7833     5267280 :         Vector<bool> inputFlagsStripe;
    7834     5267280 :         Vector<Float> inputWeightsStripe;
    7835     5267280 :         Vector<T> outputDataStripe;
    7836     5267280 :         Vector<bool> outputFlagsStripe;
    7837             : 
    7838             :         // Iterate correlation by correlation in order to extract a vector
    7839    20576443 :         for (uInt corrIndex=0; corrIndex < nCorrs; corrIndex++)
    7840             :         {
    7841             :                 // Fill input stripes by reference
    7842    15309163 :                 inputDataStripe.reference(inputDataPlane.row(corrIndex));
    7843    15309163 :                 inputFlagsStripe.reference(inputFlagsPlane.row(corrIndex));
    7844    15309163 :                 (*this.*setWeightStripeByReference_p)(corrIndex,inputWeightsPlane,inputWeightsStripe);
    7845             : 
    7846             :                 // Fill output stripes by reference
    7847    15309163 :                 outputDataStripe.reference(outputDataPlane.row(corrIndex));
    7848    15309163 :                 outputFlagsStripe.reference(outputFlagsPlane.row(corrIndex));
    7849             : 
    7850    15309163 :                 transformStripeOfData(inputSpw,inputDataStripe,inputFlagsStripe,
    7851             :                                 inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    7852             :         }
    7853             : 
    7854             :         // Write output planes
    7855     5267280 :         writeOutputPlanes(row,outputDataPlane,outputFlagsPlane,outputDataCol,*outputFlagCol);
    7856     5267280 : }
    7857             : 
    7858             : // -----------------------------------------------------------------------
    7859             : //
    7860             : // -----------------------------------------------------------------------
    7861     2724566 : void MSTransformManager::writeOutputPlanes(     uInt row,
    7862             :                                                                                         Matrix<Complex> &outputDataPlane,
    7863             :                                                                                         Matrix<bool> &outputFlagsPlane,
    7864             :                                                                                         ArrayColumn<Complex> &outputDataCol,
    7865             :                                                                                         ArrayColumn<bool> &outputFlagCol)
    7866             : {
    7867     2724566 :         (*this.*writeOutputPlanesComplex_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
    7868     2724566 : }
    7869             : 
    7870             : // -----------------------------------------------------------------------
    7871             : //
    7872             : // -----------------------------------------------------------------------
    7873     2542714 : void MSTransformManager::writeOutputPlanes(     uInt row,
    7874             :                                                                                         Matrix<Float> &outputDataPlane,
    7875             :                                                                                         Matrix<bool> &outputFlagsPlane,
    7876             :                                                                                         ArrayColumn<Float> &outputDataCol,
    7877             :                                                                                         ArrayColumn<bool> &outputFlagCol)
    7878             : {
    7879     2542714 :         (*this.*writeOutputPlanesFloat_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
    7880     2542714 : }
    7881             : 
    7882             : // -----------------------------------------------------------------------
    7883             : //
    7884             : // -----------------------------------------------------------------------
    7885           0 : void MSTransformManager::setOutputbuffer(Cube<Complex> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
    7886             : {
    7887           0 :         switch (dataBuffer_p)
    7888             :         {
    7889           0 :                 case MSTransformations::visCube:
    7890             :                 {
    7891           0 :                         dataBufferPointer=visCube_p;
    7892           0 :                         if (userBufferMode_p)
    7893             :                         {
    7894           0 :                                 flagBufferPointer = flagCube_p;
    7895             :                         }
    7896             :                         else
    7897             :                         {
    7898           0 :                                 flagBufferPointer = NULL;
    7899             :                         }
    7900           0 :                         break;
    7901             :                 }
    7902           0 :                 case MSTransformations::visCubeCorrected:
    7903             :                 {
    7904           0 :                         dataBufferPointer=visCubeCorrected_p;
    7905           0 :                         if (userBufferMode_p)
    7906             :                         {
    7907           0 :                                 flagBufferPointer = flagCube_p;
    7908             :                         }
    7909             :                         else
    7910             :                         {
    7911           0 :                                 flagBufferPointer = NULL;
    7912             :                         }
    7913           0 :                         break;
    7914             :                 }
    7915           0 :                 case MSTransformations::visCubeModel:
    7916             :                 {
    7917           0 :                         dataBufferPointer=visCubeModel_p;
    7918           0 :                         if (userBufferMode_p)
    7919             :                         {
    7920           0 :                                 flagBufferPointer = flagCube_p;
    7921             :                         }
    7922             :                         else
    7923             :                         {
    7924           0 :                                 flagBufferPointer = NULL;
    7925             :                         };
    7926           0 :                         break;
    7927             :                 }
    7928           0 :                 default:
    7929             :                 {
    7930           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    7931             :                                         << " Data buffer not specified"
    7932           0 :                                         << LogIO::POST;
    7933           0 :                         dataBufferPointer=NULL;
    7934           0 :                         flagBufferPointer=NULL;
    7935           0 :                         break;
    7936             :                 }
    7937             :         }
    7938             : 
    7939           0 :         return;
    7940             : }
    7941             : 
    7942             : // -----------------------------------------------------------------------
    7943             : //
    7944             : // -----------------------------------------------------------------------
    7945     2542672 : void MSTransformManager::setOutputbuffer(Cube<Float> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
    7946             : {
    7947     2542672 :         switch (dataBuffer_p)
    7948             :         {
    7949           0 :                 case MSTransformations::visCubeFloat:
    7950             :                 {
    7951           0 :                         dataBufferPointer=visCubeFloat_p;
    7952           0 :                         if (userBufferMode_p)
    7953             :                         {
    7954           0 :                                 flagBufferPointer = flagCube_p;
    7955             :                         }
    7956             :                         else
    7957             :                         {
    7958           0 :                                 flagBufferPointer = NULL;
    7959             :                         };
    7960           0 :                         break;
    7961             :                 }
    7962     2542672 :                 case MSTransformations::weightSpectrum:
    7963             :                 {
    7964     2542672 :                         dataBufferPointer=weightSpectrum_p;
    7965             :                         // In buffer mode we already have a memory resident flagCube
    7966             :                         // And the vector transformations use vectors from a dynamically initialize matrixes
    7967     2542672 :                         if (userBufferMode_p)
    7968             :                         {
    7969           0 :                                 flagBufferPointer=NULL;
    7970             :                         }
    7971             :                         else
    7972             :                         {
    7973     2542672 :                                 flagBufferPointer = flagCube_p;
    7974             :                         }
    7975     2542672 :                         break;
    7976             :                 }
    7977           0 :                 case MSTransformations::sigmaSpectrum:
    7978             :                 {
    7979           0 :                         dataBufferPointer=sigmaSpectrum_p;
    7980             :                         // In buffer mode we already have a memory resident flagCube
    7981             :                         // And the vector transformations use vectors from a dynamically initialize matrixes
    7982           0 :                         if (userBufferMode_p)
    7983             :                         {
    7984           0 :                                 flagBufferPointer=NULL;
    7985             :                         }
    7986             :                         else
    7987             :                         {
    7988           0 :                                 flagBufferPointer = flagCube_p;
    7989             :                         }
    7990           0 :                         break;
    7991             :                 }
    7992           0 :                 default:
    7993             :                 {
    7994           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    7995             :                                         << " Data buffer not specified"
    7996           0 :                                         << LogIO::POST;
    7997           0 :                         dataBufferPointer=NULL;
    7998           0 :                         flagBufferPointer = NULL;
    7999           0 :                         break;
    8000             :                 }
    8001             :         }
    8002             : 
    8003     2542672 :         return;
    8004             : }
    8005             : 
    8006             : // -----------------------------------------------------------------------
    8007             : //
    8008             : // -----------------------------------------------------------------------
    8009     2528905 : template <class T> void  MSTransformManager::bufferOutputPlanes(  uInt ,
    8010             :                                                                                                                                         Matrix<T> &outputDataPlane,
    8011             :                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8012             :                                                                                                                                         ArrayColumn<T> &,
    8013             :                                                                                                                                         ArrayColumn<bool> &)
    8014             : {
    8015             :         // Get buffer pointers
    8016             :         Cube<T> *dataBufferPointer;
    8017             :         Cube<bool> *flagBufferPointer;
    8018     2528905 :         setOutputbuffer(dataBufferPointer,flagBufferPointer);
    8019             : 
    8020             :         // Copy data to buffer
    8021     2528905 :         dataBufferPointer->xyPlane(relativeRow_p) = outputDataPlane;
    8022             : 
    8023             :         // Copy flags to buffer
    8024     2528905 :         if (flagBufferPointer != NULL)
    8025             :         {
    8026     2528905 :                 flagBufferPointer->xyPlane(relativeRow_p) = outputFlagsPlane;
    8027             :         }
    8028             : 
    8029     5057810 :         return;
    8030             : }
    8031             : 
    8032             : // -----------------------------------------------------------------------
    8033             : //
    8034             : // -----------------------------------------------------------------------
    8035       13767 : template <class T> void MSTransformManager::bufferOutputPlanesInSlices(   uInt,
    8036             :                                                                                                                                                 Matrix<T> &outputDataPlane,
    8037             :                                                                                                                                                 Matrix<bool> &outputFlagsPlane,
    8038             :                                                                                                                                                 ArrayColumn<T> & /* outputDataCol */,
    8039             :                                                                                                                                                 ArrayColumn<bool> & /* outputFlagCol */)
    8040             : {
    8041             :         // Get buffer pointers
    8042             :         Cube<T> *dataBufferPointer;
    8043             :         Cube<bool> *flagBufferPointer;
    8044       13767 :         setOutputbuffer(dataBufferPointer,flagBufferPointer);
    8045             : 
    8046             :         // Copy data to buffer
    8047       13767 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8048       13767 :         uInt nCorrs = outputPlaneShape(0);
    8049       13767 :         IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
    8050       13767 :         Slice sliceX(0,nCorrs);
    8051             : 
    8052             :         uInt spw_i;
    8053       13767 :         uInt nspws = nspws_p-1;
    8054       64032 :         for (spw_i=0;spw_i<nspws;spw_i++)
    8055             :         {
    8056       50265 :                 uInt outRow = relativeRow_p+spw_i;
    8057       50265 :                 Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    8058       50265 :                 Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
    8059       50265 :                 dataBufferPointer->xyPlane(outRow) = outputPlane_i;
    8060             : 
    8061       50265 :                 if (flagBufferPointer != NULL)
    8062             :                 {
    8063       50265 :                         Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
    8064       50265 :                         flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
    8065       50265 :                 }
    8066             :         }
    8067             : 
    8068       13767 :         uInt outRow = relativeRow_p+spw_i;
    8069       13767 :         Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    8070       13767 :         Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
    8071       13767 :         outputPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
    8072             :         // jagonzal (CAS-7435): We have to set the new values to 0
    8073       13767 :         Slice sliceTail(tailOfChansforLastSpw_p,chansPerOutputSpw_p-tailOfChansforLastSpw_p);
    8074       13767 :         outputPlane_i(sliceX,sliceTail) = 0; // Slices use reference semantics.
    8075       13767 :         dataBufferPointer->xyPlane(outRow) = outputPlane_i;
    8076             : 
    8077       13767 :         if (flagBufferPointer != NULL)
    8078             :         {
    8079       13767 :                 Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
    8080       13767 :                 outputFlagPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
    8081             :                 // jagonzal (CAS-7435): We have to set the new values to 0
    8082       13767 :                 outputFlagPlane_i(sliceX,sliceTail) = true; // Slices use reference semantics.
    8083       13767 :                 flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
    8084       13767 :         }
    8085             : 
    8086       27534 :         return;
    8087       13767 : }
    8088             : 
    8089             : // -----------------------------------------------------------------------
    8090             : //
    8091             : // -----------------------------------------------------------------------
    8092     2709767 : template <class T> void MSTransformManager::writeOutputPlanesInBlock(     uInt row,
    8093             :                                                                                                                                                         Matrix<T> &outputDataPlane,
    8094             :                                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8095             :                                                                                                                                                         ArrayColumn<T> &outputDataCol,
    8096             :                                                                                                                                                         ArrayColumn<bool> &outputFlagCol)
    8097             : {
    8098     2709767 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8099     2709767 :         outputDataCol.setShape(row,outputPlaneShape);
    8100     2709767 :         outputDataCol.put(row, outputDataPlane);
    8101     2709767 :         (*this.*writeOutputFlagsPlane_p)(outputFlagsPlane,outputFlagCol, outputPlaneShape, row);
    8102     2709767 : }
    8103             : 
    8104             : 
    8105             : // -----------------------------------------------------------------------
    8106             : //
    8107             : // -----------------------------------------------------------------------
    8108     2348118 : void MSTransformManager::writeOutputFlagsPlane( Matrix<bool> &outputPlane,
    8109             :                                                                                                         ArrayColumn<bool> &outputCol,
    8110             :                                                                                                         IPosition &outputPlaneShape,
    8111             :                                                                                                         uInt &outputRow)
    8112             : {
    8113     2348118 :         outputCol.setShape(outputRow,outputPlaneShape);
    8114     2348118 :         outputCol.put(outputRow, outputPlane);
    8115     2348118 : }
    8116             : 
    8117             : // -----------------------------------------------------------------------
    8118             : //
    8119             : // -----------------------------------------------------------------------
    8120       14841 : template <class T> void MSTransformManager::writeOutputPlanesInSlices(    uInt row,
    8121             :                                                                                                                                                         Matrix<T> &outputDataPlane,
    8122             :                                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8123             :                                                                                                                                                         ArrayColumn<T> &outputDataCol,
    8124             :                                                                                                                                                         ArrayColumn<bool> &outputFlagCol)
    8125             : {
    8126       14841 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8127       14841 :         uInt nCorrs = outputPlaneShape(0);
    8128       14841 :         IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
    8129       14841 :         Slice sliceX(0,nCorrs);
    8130             : 
    8131             :         uInt spw_i;
    8132       14841 :         uInt nspws = nspws_p-1;
    8133       68328 :         for (spw_i=0;spw_i<nspws;spw_i++)
    8134             :         {
    8135       53487 :                 uInt outRow = row+spw_i;
    8136       53487 :                 Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    8137       53487 :                 writeOutputPlaneSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_i,outRow);
    8138       53487 :                 (*this.*writeOutputFlagsPlaneSlices_p)( outputFlagsPlane,outputFlagCol,
    8139             :                                                                                                 sliceX,sliceY,outputPlaneShape_i,outRow);
    8140             :         }
    8141             : 
    8142       14841 :         uInt outRow = row+spw_i;
    8143       14841 :         IPosition outputPlaneShape_tail(2,nCorrs,tailOfChansforLastSpw_p);
    8144       14841 :         Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    8145       14841 :         writeOutputPlaneReshapedSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_tail,outRow);
    8146       14841 :         (*this.*writeOutputFlagsPlaneReshapedSlices_p)( outputFlagsPlane,outputFlagCol,
    8147             :                                                                                                         sliceX,sliceY,outputPlaneShape_tail,outRow);
    8148       14841 : }
    8149             : 
    8150             : // -----------------------------------------------------------------------
    8151             : //
    8152             : // -----------------------------------------------------------------------
    8153       47043 : void MSTransformManager::writeOutputFlagsPlaneSlices(   Matrix<bool> &outputPlane,
    8154             :                                                                                                                         ArrayColumn<bool> &outputCol,
    8155             :                                                                                                                         Slice &sliceX,
    8156             :                                                                                                                         Slice &sliceY,
    8157             :                                                                                                                         IPosition &outputPlaneShape,
    8158             :                                                                                                                         uInt &outputRow)
    8159             : {
    8160       47043 :         writeOutputPlaneSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
    8161       47043 : }
    8162             : 
    8163             : // -----------------------------------------------------------------------
    8164             : //
    8165             : // -----------------------------------------------------------------------
    8166       12693 : void MSTransformManager::writeOutputFlagsPlaneReshapedSlices(   Matrix<bool> &outputPlane,
    8167             :                                                                                                                                         ArrayColumn<bool> &outputCol,
    8168             :                                                                                                                                         Slice &sliceX,
    8169             :                                                                                                                                         Slice &sliceY,
    8170             :                                                                                                                                         IPosition &outputPlaneShape,
    8171             :                                                                                                                                         uInt &outputRow)
    8172             : {
    8173       12693 :         writeOutputPlaneReshapedSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
    8174       12693 : }
    8175             : 
    8176             : // -----------------------------------------------------------------------
    8177             : //
    8178             : // -----------------------------------------------------------------------
    8179      100530 : template <class T> void MSTransformManager::writeOutputPlaneSlices(       Matrix<T> &outputPlane,
    8180             :                                                                                                                                                 ArrayColumn<T> &outputCol,
    8181             :                                                                                                                                                 Slice &sliceX,
    8182             :                                                                                                                                                 Slice &sliceY,
    8183             :                                                                                                                                                 IPosition &outputPlaneShape,
    8184             :                                                                                                                                                 uInt &outputRow)
    8185             : {
    8186      100530 :         Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
    8187      100530 :         outputCol.setShape(outputRow,outputPlaneShape);
    8188      100530 :         outputCol.put(outputRow, outputPlane_i);
    8189      100530 : }
    8190             : 
    8191             : // -----------------------------------------------------------------------
    8192             : //
    8193             : // -----------------------------------------------------------------------
    8194       27534 : template <class T> void MSTransformManager::writeOutputPlaneReshapedSlices(       Matrix<T> &outputPlane,
    8195             :                                                                                                                                                                 ArrayColumn<T> &outputCol,
    8196             :                                                                                                                                                                 Slice &sliceX,
    8197             :                                                                                                                                                                 Slice &sliceY,
    8198             :                                                                                                                                                                 IPosition &outputPlaneShape,
    8199             :                                                                                                                                                                 uInt &outputRow)
    8200             : {
    8201       27534 :         Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
    8202       27534 :         outputPlane_i.resize(outputPlaneShape,true);
    8203       27534 :         outputCol.setShape(outputRow,outputPlaneShape);
    8204       27534 :         outputCol.put(outputRow, outputPlane_i);
    8205       27534 : }
    8206             : 
    8207             : // -----------------------------------------------------------------------
    8208             : //
    8209             : // -----------------------------------------------------------------------
    8210     2802641 : void MSTransformManager::setWeightStripeByReference(    uInt corrIndex,
    8211             :                                                                                                                         Matrix<Float> &inputWeightsPlane,
    8212             :                                                                                                                         Vector<Float> &inputWeightsStripe)
    8213             : {
    8214     2802641 :         inputWeightsStripe.reference(inputWeightsPlane.row(corrIndex));
    8215     2802641 : }
    8216             : 
    8217             : // -----------------------------------------------------------------------
    8218             : //
    8219             : // -----------------------------------------------------------------------
    8220     8007365 : void MSTransformManager::transformStripeOfData(Int inputSpw,
    8221             :                                                const Vector<Complex> &inputDataStripe,
    8222             :                                                const Vector<bool> &inputFlagsStripe,
    8223             :                                                const Vector<Float> &inputWeightsStripe,
    8224             :                                                Vector<Complex> &outputDataStripe,
    8225             :                                                Vector<bool> &outputFlagsStripe)
    8226             : {
    8227     8007365 :     auto shapeBefore = outputDataStripe.shape();
    8228     8007365 :     (*this.*transformStripeOfDataComplex_p)(inputSpw, inputDataStripe, inputFlagsStripe,
    8229             :                                             inputWeightsStripe, outputDataStripe,
    8230             :                                             outputFlagsStripe);
    8231     8007365 :     auto shapeAfter = outputDataStripe.shape();
    8232     8007365 :     if (shapeAfter != shapeBefore) {
    8233           0 :         ostringstream msg;
    8234             :         msg << "Shape of output complex data stripe changed after applying "
    8235           0 :             << "transformation. Output shape expected before transformation: "
    8236           0 :             << shapeBefore
    8237           0 :             << ". Output shape produced by transformation: " << shapeAfter;
    8238           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    8239           0 :                  << LogIO::POST;
    8240           0 :         throw AipsError(msg.str());
    8241           0 :     }
    8242     8007365 : }
    8243             : 
    8244             : // -----------------------------------------------------------------------
    8245             : //
    8246             : // -----------------------------------------------------------------------
    8247     7301798 : void MSTransformManager::transformStripeOfData(Int inputSpw,
    8248             :                                                const Vector<Float> &inputDataStripe,
    8249             :                                                const Vector<bool> &inputFlagsStripe,
    8250             :                                                const Vector<Float> &inputWeightsStripe,
    8251             :                                                Vector<Float> &outputDataStripe,
    8252             :                                                Vector<bool> &outputFlagsStripe)
    8253             : {
    8254     7301798 :         (*this.*transformStripeOfDataFloat_p)(  inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8255             :                                                                                         outputDataStripe,outputFlagsStripe);
    8256     7301798 : }
    8257             : 
    8258             : // -----------------------------------------------------------------------
    8259             : //
    8260             : // -----------------------------------------------------------------------
    8261     8609202 : template <class T> void MSTransformManager::average(Int inputSpw,
    8262             :                                                     const Vector<T> &inputDataStripe,
    8263             :                                                     const Vector<bool> &inputFlagsStripe,
    8264             :                                                     const Vector<Float> &inputWeightsStripe,
    8265             :                                                     Vector<T> &outputDataStripe,
    8266             :                                                     Vector<bool> &outputFlagsStripe)
    8267             : {
    8268     8609202 :         uInt width = freqbinMap_p[inputSpw];
    8269     8609202 :         uInt startChan = 0;
    8270     8609202 :         uInt outChanIndex = 0;
    8271     8609202 :         uInt tail = inputDataStripe.size() % width;
    8272   272401874 :         while (outChanIndex < outputDataStripe.size())
    8273             :         {
    8274   263792672 :                 averageKernel(  inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8275             :                                                 outputDataStripe,outputFlagsStripe,startChan,outChanIndex,width);
    8276   263792672 :                 startChan += width;
    8277   263792672 :                 outChanIndex += 1;
    8278             :         }
    8279             : 
    8280             :         // jagonzal: The last channel is dropped when there are not enough input channels
    8281             :         //           to populate it only when there is no regridding afterwards
    8282     8609202 :         if (tail and (outChanIndex <= outputDataStripe.size()-1) )
    8283             :         {
    8284           0 :                 averageKernel(  inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8285             :                                                 outputDataStripe,outputFlagsStripe,startChan,outChanIndex,tail);
    8286             :         }
    8287             : 
    8288     8609202 :         return;
    8289             : }
    8290             : 
    8291             : // -----------------------------------------------------------------------
    8292             : //
    8293             : // -----------------------------------------------------------------------
    8294           4 : template <class T> void  MSTransformManager::simpleAverage(uInt width,
    8295             :                                                            const Vector<T> &inputData,
    8296             :                                                            Vector<T> &outputData)
    8297             : {
    8298             :         // Dummy variables
    8299           4 :         Vector<bool> inputFlags,outputFlags;
    8300           4 :         Vector<Float> inputWeights;
    8301             : 
    8302           4 :         uInt startChan = 0;
    8303           4 :         uInt outChanIndex = 0;
    8304           4 :         uInt tail = inputData.size() % width;
    8305           4 :         uInt limit = inputData.size() - tail;
    8306          56 :         while (startChan < limit)
    8307             :         {
    8308          52 :                 simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,width);
    8309          52 :                 startChan += width;
    8310          52 :                 outChanIndex += 1;
    8311             :         }
    8312             : 
    8313             :         // jagonzal: The last channel is dropped when there are not enough input channels
    8314             :         //           to populate it only when there is no regridding afterwards
    8315           4 :         if (tail and (outChanIndex <= outputData.size()-1) )
    8316             :         {
    8317           4 :                 simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,tail);
    8318             :         }
    8319             : 
    8320           8 :         return;
    8321           4 : }
    8322             : 
    8323             : // -----------------------------------------------------------------------
    8324             : //
    8325             : // -----------------------------------------------------------------------
    8326   142802536 : void MSTransformManager::averageKernel(const Vector<Complex> &inputData,
    8327             :                                        const Vector<bool> &inputFlags,
    8328             :                                        const Vector<Float> &inputWeights,
    8329             :                                        Vector<Complex> &outputData,
    8330             :                                        Vector<bool> &outputFlags,
    8331             :                                        uInt startInputPos,
    8332             :                                        uInt outputPos,
    8333             :                                        uInt width)
    8334             : {
    8335   142802536 :         (*this.*averageKernelComplex_p)(        inputData,inputFlags,inputWeights,
    8336             :                                                                                 outputData,outputFlags,startInputPos,outputPos,width);
    8337   142802536 :         return;
    8338             : }
    8339             : 
    8340             : // -----------------------------------------------------------------------
    8341             : //
    8342             : // -----------------------------------------------------------------------
    8343   120990136 : void MSTransformManager::averageKernel(const Vector<Float> &inputData,
    8344             :                                        const Vector<bool> &inputFlags,
    8345             :                                        const Vector<Float> &inputWeights,
    8346             :                                        Vector<Float> &outputData,
    8347             :                                        Vector<bool> &outputFlags,
    8348             :                                        uInt startInputPos,
    8349             :                                        uInt outputPos,
    8350             :                                                                                         uInt width)
    8351             : {
    8352   120990136 :         (*this.*averageKernelFloat_p)(  inputData,inputFlags,inputWeights,
    8353             :                                                                         outputData,outputFlags,startInputPos,outputPos,width);
    8354   120990136 :         return;
    8355             : }
    8356             : 
    8357             : // -----------------------------------------------------------------------
    8358             : //
    8359             : // -----------------------------------------------------------------------
    8360          56 : template <class T> void MSTransformManager::simpleAverageKernel(const Vector<T> &inputData,
    8361             :                                                                 const Vector<bool> &,
    8362             :                                                                 const Vector<Float> &,
    8363             :                                                                 Vector<T> &outputData,
    8364             :                                                                 Vector<bool> &,
    8365             :                                                                 uInt startInputPos,
    8366             :                                                                 uInt outputPos,
    8367             :                                                                                                                                         uInt width)
    8368             : {
    8369          56 :         uInt pos = startInputPos + 1;
    8370          56 :         uInt counts = 1;
    8371          56 :         T avg = inputData(startInputPos);
    8372         216 :         while (counts < width)
    8373             :         {
    8374         160 :                 avg += inputData(pos);
    8375         160 :                 counts += 1;
    8376         160 :                 pos += 1;
    8377             :         }
    8378             : 
    8379          56 :         if (counts > 0)
    8380             :         {
    8381          56 :                 avg /= counts;
    8382             :         }
    8383             : 
    8384          56 :         outputData(outputPos) = avg;
    8385             : 
    8386          56 :         return;
    8387             : }
    8388             : 
    8389             : // -----------------------------------------------------------------------
    8390             : //
    8391             : // -----------------------------------------------------------------------
    8392           0 : template <class T> void MSTransformManager::flagAverageKernel(const Vector<T> &inputData,
    8393             :                                                               const Vector<bool> &inputFlags,
    8394             :                                                               const Vector<Float> &,
    8395             :                                                               Vector<T> &outputData,
    8396             :                                                               Vector<bool> &outputFlags,
    8397             :                                                               uInt startInputPos,
    8398             :                                                               uInt outputPos,
    8399             :                                                               uInt width)
    8400             : {
    8401           0 :         uInt samples = 1;
    8402           0 :         uInt pos = startInputPos + 1;
    8403           0 :         uInt counts = !inputFlags(startInputPos);
    8404           0 :         T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
    8405           0 :         while (samples < width)
    8406             :         {
    8407           0 :                 avg += inputData(pos)*(!inputFlags(pos));
    8408           0 :                 counts += (!inputFlags(pos));
    8409           0 :                 samples += 1;
    8410           0 :                 pos += 1;
    8411             :         }
    8412             : 
    8413           0 :         if (counts > 0)
    8414             :         {
    8415           0 :                 avg /= counts;
    8416             :         }
    8417             :         else
    8418             :         {
    8419           0 :                 outputFlags(outputPos) = true;
    8420             :         }
    8421             : 
    8422           0 :         outputData(outputPos) = avg;
    8423             : 
    8424           0 :         return;
    8425             : }
    8426             : 
    8427             : // -----------------------------------------------------------------------
    8428             : //
    8429             : // -----------------------------------------------------------------------
    8430           0 : template <class T> void MSTransformManager::weightAverageKernel(const Vector<T> &inputData,
    8431             :                                                                 const Vector<bool> &,
    8432             :                                                                 const Vector<Float> &inputWeights,
    8433             :                                                                 Vector<T> &outputData,
    8434             :                                                                 Vector<bool> &outputFlags,
    8435             :                                                                 uInt startInputPos,
    8436             :                                                                 uInt outputPos,
    8437             :                                                                 uInt width)
    8438             : {
    8439           0 :         uInt samples = 1;
    8440           0 :         uInt pos = startInputPos + 1;
    8441           0 :         Float counts = inputWeights(startInputPos);
    8442           0 :         T avg = inputData(startInputPos)*inputWeights(startInputPos);
    8443           0 :         while (samples < width)
    8444             :         {
    8445           0 :                 avg += inputData(pos)*inputWeights(pos);
    8446           0 :                 counts += inputWeights(pos);
    8447           0 :                 samples += 1;
    8448           0 :                 pos += 1;
    8449             :         }
    8450             : 
    8451           0 :         if (counts > 0)
    8452             :         {
    8453           0 :                 avg /= counts;
    8454             :         }
    8455             :         else
    8456             :         {
    8457           0 :                 outputFlags(outputPos) = true;
    8458             :         }
    8459             : 
    8460           0 :         outputData(outputPos) = avg;
    8461             : 
    8462           0 :         return;
    8463             : }
    8464             : 
    8465             : // -----------------------------------------------------------------------
    8466             : //
    8467             : // -----------------------------------------------------------------------
    8468           0 : template <class T> void MSTransformManager::cumSumKernel(const Vector<T> &inputData,
    8469             :                                                          const Vector<bool> &,
    8470             :                                                          const Vector<Float> &,
    8471             :                                                          Vector<T> &outputData,
    8472             :                                                          Vector<bool> &,
    8473             :                                                          uInt startInputPos,
    8474             :                                                          uInt outputPos,
    8475             :                                                          uInt width)
    8476             : {
    8477           0 :         uInt pos = startInputPos + 1;
    8478           0 :         uInt counts = 1;
    8479           0 :         T avg = inputData(startInputPos);
    8480           0 :         while (counts < width)
    8481             :         {
    8482           0 :                 avg += inputData(pos);
    8483           0 :                 counts += 1;
    8484           0 :                 pos += 1;
    8485             :         }
    8486             : 
    8487           0 :         outputData(outputPos) = avg;
    8488             : 
    8489           0 :         return;
    8490             : }
    8491             : 
    8492             : // -----------------------------------------------------------------------
    8493             : //
    8494             : // -----------------------------------------------------------------------
    8495           0 : template <class T> void MSTransformManager::flagWeightAverageKernel(const Vector<T> &inputData,
    8496             :                                                                     const Vector<bool> &inputFlags,
    8497             :                                                                     const Vector<Float> &inputWeights,
    8498             :                                                                     Vector<T> &outputData,
    8499             :                                                                     Vector<bool> &outputFlags,
    8500             :                                                                     uInt startInputPos,
    8501             :                                                                     uInt outputPos,
    8502             :                                                                     uInt width)
    8503             : {
    8504           0 :         uInt samples = 1;
    8505           0 :         uInt pos = startInputPos + 1;
    8506           0 :         Float totalWeight = inputWeights(startInputPos)*(!inputFlags(startInputPos));
    8507           0 :         Float counts = totalWeight;
    8508           0 :         T avg = inputData(startInputPos)*totalWeight;
    8509           0 :         while (samples < width)
    8510             :         {
    8511           0 :                 totalWeight = inputWeights(pos)*(!inputFlags(pos));
    8512           0 :                 avg += inputData(pos)*totalWeight;
    8513           0 :                 counts += totalWeight;
    8514           0 :                 samples += 1;
    8515           0 :                 pos += 1;
    8516             :         }
    8517             : 
    8518           0 :         if (counts > 0)
    8519             :         {
    8520           0 :                 avg /= counts;
    8521             :         }
    8522             :         else
    8523             :         {
    8524           0 :                 outputFlags(outputPos) = true;
    8525             :         }
    8526             : 
    8527           0 :         outputData(outputPos) = avg;
    8528             : 
    8529           0 :         return;
    8530             : }
    8531             : 
    8532             : // -----------------------------------------------------------------------
    8533             : //
    8534             : // -----------------------------------------------------------------------
    8535           0 : template <class T> void MSTransformManager::flagCumSumKernel(const Vector<T> &inputData,
    8536             :                                                              const Vector<bool> &inputFlags,
    8537             :                                                              const Vector<Float> &,
    8538             :                                                              Vector<T> &outputData,
    8539             :                                                              Vector<bool> &,
    8540             :                                                              uInt startInputPos,
    8541             :                                                              uInt outputPos,
    8542             :                                                              uInt width)
    8543             : {
    8544           0 :         uInt samples = 1;
    8545           0 :         uInt pos = startInputPos + 1;
    8546           0 :         T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
    8547           0 :         while (samples < width)
    8548             :         {
    8549           0 :                 avg += inputData(pos)*(!inputFlags(pos));
    8550           0 :                 samples += 1;
    8551           0 :                 pos += 1;
    8552             :         }
    8553             : 
    8554           0 :         outputData(outputPos) = avg;
    8555             : 
    8556           0 :         return;
    8557             : }
    8558             : 
    8559             : // -----------------------------------------------------------------------
    8560             : //
    8561             : // -----------------------------------------------------------------------
    8562   128123966 : template <class T> void MSTransformManager::flagNonZeroAverageKernel(const Vector<T> &inputData,
    8563             :                                                                      const Vector<bool> &inputFlags,
    8564             :                                                                      const Vector<Float> & /* inputWeights */,
    8565             :                                                                      Vector<T> &outputData,
    8566             :                                                                      Vector<bool> &outputFlags,
    8567             :                                                                      uInt startInputPos,
    8568             :                                                                      uInt outputPos,
    8569             :                                                                      uInt width)
    8570             : {
    8571   128123966 :         T avg = 0;
    8572   128123966 :         uInt samples = 0;
    8573   128123966 :         uInt inputPos = 0;
    8574   128123966 :         bool accumulatorFlag = inputFlags(startInputPos);
    8575             : 
    8576   389210668 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8577             :         {
    8578             :                 // Get input index
    8579   261086702 :                 inputPos = startInputPos + sample_i;
    8580             : 
    8581             :                 // true/true or false/false
    8582   261086702 :                 if (accumulatorFlag == inputFlags(inputPos))
    8583             :                 {
    8584   256998271 :                         samples += 1;
    8585   256998271 :                         avg += inputData(inputPos);
    8586             :                 }
    8587             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8588     4088431 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8589             :                 {
    8590     1916304 :                         accumulatorFlag = false;
    8591     1916304 :                         samples = 1;
    8592     1916304 :                         avg = inputData(inputPos);
    8593             :                 }
    8594             :         }
    8595             : 
    8596             : 
    8597             :         // Apply normalization factor
    8598   128123966 :         if (samples > 0)
    8599             :         {
    8600   128123966 :                 avg /= samples;
    8601   128123966 :                 outputData(outputPos) = avg;
    8602             :         }
    8603             :         // This should never happen
    8604             :         else
    8605             :         {
    8606           0 :                 accumulatorFlag = true;
    8607           0 :                 outputData(outputPos) = 0; // this should be a code error
    8608             :         }
    8609             : 
    8610             : 
    8611             :         // Set output flag (it is initialized to false)
    8612   128123966 :         if (accumulatorFlag)
    8613             :         {
    8614    16120213 :                 outputFlags(outputPos) = true;
    8615             :         }
    8616             : 
    8617   256247932 :         return;
    8618             : }
    8619             : 
    8620             : 
    8621             : // -----------------------------------------------------------------------
    8622             : //
    8623             : // -----------------------------------------------------------------------
    8624    14678570 : template <class T> void MSTransformManager::flagWeightNonZeroAverageKernel(const Vector<T> &inputData,
    8625             :                                                                            const Vector<bool> &inputFlags,
    8626             :                                                                            const Vector<Float> &inputWeights,
    8627             :                                                                            Vector<T> &outputData,
    8628             :                                                                            Vector<bool> &outputFlags,
    8629             :                                                                            uInt startInputPos,
    8630             :                                                                            uInt outputPos,
    8631             :                                                                            uInt width)
    8632             : {
    8633    14678570 :         T avg = 0;
    8634    14678570 :         T normalization = 0;
    8635    14678570 :         uInt inputPos = 0;
    8636    14678570 :         bool accumulatorFlag = inputFlags(startInputPos);
    8637             : 
    8638    44695750 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8639             :         {
    8640             :                 // Get input index
    8641    30017180 :                 inputPos = startInputPos + sample_i;
    8642             : 
    8643             :                 // true/true or false/false
    8644    30017180 :                 if (accumulatorFlag == inputFlags(inputPos))
    8645             :                 {
    8646    29643488 :                         normalization += inputWeights(inputPos);
    8647    29643488 :                         avg += inputData(inputPos)*inputWeights(inputPos);
    8648             :                 }
    8649             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8650      373692 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8651             :                 {
    8652      172959 :                         accumulatorFlag = false;
    8653      172959 :                         normalization = inputWeights(inputPos);
    8654      172959 :                         avg = inputData(inputPos)*inputWeights(inputPos);
    8655             :                 }
    8656             :         }
    8657             : 
    8658             : 
    8659             :         // Apply normalization factor
    8660    14678570 :         if (normalization > 0)
    8661             :         {
    8662    14673974 :                 avg /= normalization;
    8663    14673974 :                 outputData(outputPos) = avg;
    8664             :         }
    8665             :         // If all weights are zero set accumulatorFlag to true
    8666             :         else
    8667             :         {
    8668        4596 :                 accumulatorFlag = true;
    8669        4596 :                 outputData(outputPos) = 0; // If all weights are zero then the avg is 0 too
    8670             :         }
    8671             : 
    8672             : 
    8673             :         // Set output flag (it is initialized to false)
    8674    14678570 :         if (accumulatorFlag)
    8675             :         {
    8676     1538381 :                 outputFlags(outputPos) = true;
    8677             :         }
    8678             : 
    8679    29357140 :         return;
    8680             : }
    8681             : 
    8682             : // -----------------------------------------------------------------------
    8683             : //
    8684             : // -----------------------------------------------------------------------
    8685   120990136 : template <class T> void MSTransformManager::flagCumSumNonZeroKernel(const Vector<T> &inputData,
    8686             :                                                                     const Vector<bool> &inputFlags,
    8687             :                                                                     const Vector<Float> & /* inputWeights */,
    8688             :                                                                     Vector<T> &outputData,
    8689             :                                                                     Vector<bool> &outputFlags,
    8690             :                                                                     uInt startInputPos,
    8691             :                                                                     uInt outputPos,
    8692             :                                                                     uInt width)
    8693             : {
    8694   120990136 :         T avg = 0;
    8695   120990136 :         uInt inputPos = 0;
    8696   120990136 :         bool accumulatorFlag = inputFlags(startInputPos);
    8697             : 
    8698   367695938 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8699             :         {
    8700             :                 // Get input index
    8701   246705802 :                 inputPos = startInputPos + sample_i;
    8702             : 
    8703             :                 // true/true or false/false
    8704   246705802 :                 if (accumulatorFlag == inputFlags(inputPos))
    8705             :                 {
    8706   242880186 :                         avg += inputData(inputPos);
    8707             :                 }
    8708             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8709     3825616 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8710             :                 {
    8711     1777595 :                         accumulatorFlag = false;
    8712     1777595 :                         avg = inputData(inputPos);
    8713             :                 }
    8714             :         }
    8715             : 
    8716   120990136 :         outputData(outputPos) = avg;
    8717             : 
    8718             :         // Set output flag (it is initialized to false)
    8719   120990136 :         if (accumulatorFlag)
    8720             :         {
    8721    14770980 :                 outputFlags(outputPos) = true;
    8722             :         }
    8723             : 
    8724   120990136 :         return;
    8725             : }
    8726             : 
    8727             : 
    8728             : // -----------------------------------------------------------------------
    8729             : //
    8730             : // -----------------------------------------------------------------------
    8731     1137386 : template <class T> void MSTransformManager::smooth(Int ,
    8732             :                                                    const Vector<T> &inputDataStripe,
    8733             :                                                    const Vector<bool> &inputFlagsStripe,
    8734             :                                                    const Vector<Float> &inputWeightsStripe,
    8735             :                                                    Vector<T> &outputDataStripe,
    8736             :                                                    Vector<bool> &outputFlagsStripe)
    8737             : {
    8738             :         // Calculate limits
    8739     1137386 :         uInt width = smoothBin_p;
    8740     1137386 :         uInt halfWidth = width / 2;
    8741     1137386 :         uInt outChanStart = halfWidth;
    8742     1137386 :         uInt outChanStop = inputDataStripe.size() - outChanStart;
    8743             : 
    8744             :         // Main loop
    8745    86378977 :         for (uInt outChan = outChanStart; outChan<outChanStop; outChan++)
    8746             :         {
    8747    85241591 :                 smoothKernel(   inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8748             :                                                 outputDataStripe,outputFlagsStripe,outChan);
    8749             :         }
    8750             : 
    8751             :         // Flag lower edge
    8752     2545552 :         for (uInt outChan = 0; outChan<outChanStart; outChan++)
    8753             :         {
    8754     1408166 :                 outputFlagsStripe(outChan) = true;
    8755     1408166 :                 outputDataStripe(outChan) = inputDataStripe(outChan);
    8756             :         }
    8757             : 
    8758             :         // Flag higher edge
    8759     2545552 :         for (uInt outChan = outChanStop; outChan<inputDataStripe.size(); outChan++)
    8760             :         {
    8761     1408166 :                 outputFlagsStripe(outChan) = true;
    8762     1408166 :                 outputDataStripe(outChan) = inputDataStripe(outChan);
    8763             :         }
    8764             : 
    8765     1137386 :         return;
    8766             : }
    8767             : 
    8768             : // -----------------------------------------------------------------------
    8769             : //
    8770             : // -----------------------------------------------------------------------
    8771    21771723 : void MSTransformManager::smoothKernel(const Vector<Complex> &inputData,
    8772             :                                       const Vector<bool> &inputFlags,
    8773             :                                       const Vector<Float> &inputWeights,
    8774             :                                       Vector<Complex> &outputData,
    8775             :                                       Vector<bool> &outputFlags,
    8776             :                                       uInt outputPos)
    8777             : {
    8778    21771723 :         (*this.*smoothKernelComplex_p)( inputData,inputFlags,inputWeights,
    8779             :                                                                                 outputData,outputFlags,outputPos);
    8780    21771723 :         return;
    8781             : }
    8782             : 
    8783             : // -----------------------------------------------------------------------
    8784             : //
    8785             : // -----------------------------------------------------------------------
    8786    63469868 : void MSTransformManager::smoothKernel(const Vector<Float> &inputData,
    8787             :                                       const Vector<bool> &inputFlags,
    8788             :                                       const Vector<Float> &inputWeights,
    8789             :                                       Vector<Float> &outputData,
    8790             :                                       Vector<bool> &outputFlags,
    8791             :                                       uInt outputPos)
    8792             : {
    8793    63469868 :         (*this.*smoothKernelFloat_p)(   inputData,inputFlags,inputWeights,
    8794             :                                                                         outputData,outputFlags,outputPos);
    8795    63469868 :         return;
    8796             : }
    8797             : 
    8798             : // -----------------------------------------------------------------------
    8799             : //
    8800             : // -----------------------------------------------------------------------
    8801    21771723 : template <class T> void  MSTransformManager::plainSmooth(const Vector<T> &inputData,
    8802             :                                                          const Vector<bool> &inputFlags,
    8803             :                                                          const Vector<Float> &,
    8804             :                                                          Vector<T> &outputData,
    8805             :                                                          Vector<bool> &outputFlags,
    8806             :                                                          uInt outputPos)
    8807             : {
    8808    21771723 :         uInt halfWidth = smoothBin_p / 2;
    8809             : 
    8810             :         // Initialization
    8811    21771723 :         outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
    8812    21771723 :         outputData(outputPos) = smoothCoeff_p(0)*inputData(outputPos-halfWidth);
    8813             : 
    8814             :         // Main loop
    8815    65315169 :         for (uInt i = 1; i<smoothBin_p;i++)
    8816             :         {
    8817    43543446 :                 outputData(outputPos) += smoothCoeff_p(i)*inputData(outputPos-halfWidth+i);
    8818             : 
    8819             :                 // Output sample is flagged if any of the contributors are flagged
    8820    43543446 :                 if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
    8821             :         }
    8822             : 
    8823    21771723 :         return;
    8824             : }
    8825             : 
    8826             : // -----------------------------------------------------------------------
    8827             : //
    8828             : // -----------------------------------------------------------------------
    8829    63469868 : template <class T> void  MSTransformManager::plainSmoothSpectrum(const Vector<T> &inputData,
    8830             :                                                                  const Vector<bool> &inputFlags,
    8831             :                                                                  const Vector<Float> &,
    8832             :                                                                  Vector<T> &outputData,
    8833             :                                                                  Vector<bool> &outputFlags,
    8834             :                                                                  uInt outputPos)
    8835             : {
    8836    63469868 :         uInt halfWidth = smoothBin_p / 2;
    8837             : 
    8838             :         // Initialization (mind for zeros as there is a division operation)
    8839    63469868 :         if (inputData(outputPos-halfWidth) <= FLT_MIN)
    8840             :         {
    8841      307472 :                 outputData(outputPos) = 0;
    8842      307472 :                 outputFlags(outputPos) = true;
    8843             :         }
    8844             :         else
    8845             :         {
    8846    63162396 :                 outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
    8847    63162396 :                 outputData(outputPos) = smoothCoeff_p(0)*smoothCoeff_p(0)/inputData(outputPos-halfWidth);
    8848             :         }
    8849             : 
    8850             :         // Main accumulation loop
    8851   265753316 :         for (uInt i = 1; i<smoothBin_p;i++)
    8852             :         {
    8853             :                 // Mind for zeros as there is a division operation
    8854   202283448 :                 if (inputData(outputPos-halfWidth+i) <= FLT_MIN)
    8855             :                 {
    8856      614944 :                         outputFlags(outputPos) = true;
    8857             :                 }
    8858             :                 else
    8859             :                 {
    8860   201668504 :                         outputData(outputPos) += smoothCoeff_p(i)*smoothCoeff_p(i)/inputData(outputPos-halfWidth+i);
    8861             : 
    8862             :                         // Output sample is flagged if any of the contributors are flagged
    8863   201668504 :                         if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
    8864             :                 }
    8865             :         }
    8866             : 
    8867             :         // Final propaged weight si the inverse of the accumulation
    8868    63469868 :         if (outputData(outputPos) > FLT_MIN)
    8869             :         {
    8870    63165146 :                 outputData(outputPos) = 1/outputData(outputPos);
    8871             :         }
    8872             : 
    8873    63469868 :         return;
    8874             : }
    8875             : 
    8876             : // -----------------------------------------------------------------------
    8877             : //
    8878             : // -----------------------------------------------------------------------
    8879     5214205 : template <class T> void MSTransformManager::regrid(Int inputSpw,
    8880             :                                                    const Vector<T> &inputDataStripe,
    8881             :                                                    const Vector<bool> &inputFlagsStripe,
    8882             :                                                    const Vector<Float> &inputWeightsStripe,
    8883             :                                                    Vector<T> &outputDataStripe,
    8884             :                                                    Vector<bool> &outputFlagsStripe)
    8885             : {
    8886             : 
    8887     5214205 :         regridCore(     inputSpw,
    8888             :                                 inputDataStripe,
    8889             :                                 inputFlagsStripe,
    8890             :                                 inputWeightsStripe,
    8891             :                                 outputDataStripe,
    8892             :                                 outputFlagsStripe);
    8893             : 
    8894     5214205 : }
    8895             : 
    8896             : // -----------------------------------------------------------------------
    8897             : //
    8898             : // -----------------------------------------------------------------------
    8899     2613064 : void MSTransformManager::regridCore(Int inputSpw,
    8900             :                                     const Vector<Complex> &inputDataStripe,
    8901             :                                     const Vector<bool> &inputFlagsStripe,
    8902             :                                     const Vector<Float> &inputWeightsStripe,
    8903             :                                     Vector<Complex> &outputDataStripe,
    8904             :                                     Vector<bool> &outputFlagsStripe)
    8905             : {
    8906             : 
    8907     2613064 :         (*this.*regridCoreComplex_p)(   inputSpw,
    8908             :                                                                         inputDataStripe,
    8909             :                                                                         inputFlagsStripe,
    8910             :                                                                         inputWeightsStripe,
    8911             :                                                                         outputDataStripe,
    8912             :                                                                         outputFlagsStripe);
    8913     2613064 : }
    8914             : 
    8915             : // -----------------------------------------------------------------------
    8916             : //
    8917             : // -----------------------------------------------------------------------
    8918     2601141 :   void MSTransformManager::regridCore(Int inputSpw,
    8919             :                                       const Vector<Float> &inputDataStripe,
    8920             :                                       const Vector<bool> &inputFlagsStripe,
    8921             :                                       const Vector<Float> &inputWeightsStripe,
    8922             :                                       Vector<Float> &outputDataStripe,
    8923             :                                       Vector<bool> &outputFlagsStripe)
    8924             : {
    8925     2601141 :         (*this.*regridCoreFloat_p)(     inputSpw,
    8926             :                                                                 inputDataStripe,
    8927             :                                                                 inputFlagsStripe,
    8928             :                                                                 inputWeightsStripe,
    8929             :                                                                 outputDataStripe,
    8930             :                                                                 outputFlagsStripe);
    8931     2601141 : }
    8932             : 
    8933             : // -----------------------------------------------------------------------
    8934             : //
    8935             : // -----------------------------------------------------------------------
    8936       53813 : void MSTransformManager::fftshift(Int ,
    8937             :                                   const Vector<Complex> &inputDataStripe,
    8938             :                                   const Vector<bool> &inputFlagsStripe,
    8939             :                                   const Vector<Float> &,
    8940             :                                   Vector<Complex> &outputDataStripe,
    8941             :                                   Vector<bool> &outputFlagsStripe)
    8942             : {
    8943       53813 :         fFFTServer_p.fftshift(outputDataStripe,
    8944             :                                         outputFlagsStripe,
    8945      107626 :                                         (const Vector<Complex>)inputDataStripe,
    8946       53813 :                                         (const Vector<bool>)inputFlagsStripe,
    8947           0 :                                         (const uInt)0, // In vectors axis 0 is the only dimension
    8948       53813 :                                         (const Double)fftShift_p,
    8949             :                                         false, // A good data point has its flag set to false
    8950             :                                         false);
    8951       53813 : }
    8952             : 
    8953             : // -----------------------------------------------------------------------
    8954             : //
    8955             : // -----------------------------------------------------------------------
    8956       52988 : void MSTransformManager::fftshift(Int ,
    8957             :                                   const Vector<Float> &inputDataStripe,
    8958             :                                   const Vector<bool> &inputFlagsStripe,
    8959             :                                   const Vector<Float> &,
    8960             :                                   Vector<Float> &outputDataStripe,
    8961             :                                   Vector<bool> &outputFlagsStripe)
    8962             : {
    8963       52988 :     fFFTServer_p.fftshift(outputDataStripe,
    8964             :                                         outputFlagsStripe,
    8965      105976 :                                         (const Vector<Float>)inputDataStripe,
    8966       52988 :                                         (const Vector<bool>)inputFlagsStripe,
    8967           0 :                                         (const uInt)0, // In vectors axis 0 is the only dimension
    8968       52988 :                                         (const Double)fftShift_p,
    8969             :                                         false); // A good data point has its flag set to false
    8970       52988 : }
    8971             : 
    8972             : // -----------------------------------------------------------------------
    8973             : //
    8974             : // -----------------------------------------------------------------------
    8975     5214205 : template <class T> void MSTransformManager::interpol1D(Int inputSpw,
    8976             :                                                        const Vector<T> &inputDataStripe,
    8977             :                                                        const Vector<bool> &inputFlagsStripe,
    8978             :                                                        const Vector<Float> &,
    8979             :                                                        Vector<T> &outputDataStripe,
    8980             :                                                        Vector<bool> &outputFlagsStripe)
    8981             : {
    8982     5214205 :   if (inputDataStripe.size() < 2) {
    8983      417808 :     outputDataStripe = inputDataStripe(0);
    8984      417808 :     outputFlagsStripe = true;
    8985      417808 :     return;
    8986             :   }
    8987             : 
    8988     4796397 :   if (!regridTClean_p) {
    8989     9405494 :     InterpolateArray1D<Double,T>::interpolate(outputDataStripe, // Output data
    8990             :                                               outputFlagsStripe, // Output flags
    8991     4702747 :                                               inputOutputSpwMap_p[inputSpw].second.CHAN_FREQ, // Out chan freq
    8992     9405494 :                                               inputOutputSpwMap_p[inputSpw].first.CHAN_FREQ_aux, // In chan freq
    8993             :                                               inputDataStripe, // Input data
    8994             :                                               inputFlagsStripe, // Input Flags
    8995     4702747 :                                               interpolationMethod_p, // Interpolation method
    8996             :                                               false, // A good data point has its flag set to false
    8997             :                                               false // If false extrapolated data points are set flagged
    8998             :                                               );
    8999             :   } else {
    9000       93650 :     interpolateByChannelMap(inputSpw,
    9001             :                             inputDataStripe, inputFlagsStripe,
    9002             :                             outputDataStripe, outputFlagsStripe);
    9003             :   }
    9004             : }
    9005             : 
    9006             : /**
    9007             :  * Introduced to mimic the way tclean regrids when the factor between
    9008             :  * the output channel width and the input channel width is > 2.
    9009             :  * Ref. TransformMachines2/FTMachine.cc
    9010             :  *
    9011             :  * Uses a map from original input channels => fake output channels,
    9012             :  * where the fake output channels have the (lower) width of the
    9013             :  * input channels but are projected/aligned with the output channel
    9014             :  * grid.
    9015             :  *
    9016             :  * @param spw spw index of the input channels, to fetch original
    9017             :  *        input channel freqs
    9018             :  * @param inputDataStripe input data coming from regridCubeOfData,
    9019             :  *        transformAndWriteCubeOfData, etc. and passed to the
    9020             :  *        regrid/interpolation kernels.
    9021             :  * @param inputFlagsStripe flags for the inputDataStripe
    9022             :  * @param outputDataStripe will be interpolated by aggregating
    9023             :  *        input visibilities into wider channels
    9024             :  * @param outputFlagsStripe flags for outputDataStripe
    9025             :  */
    9026       93650 : template <class T> void MSTransformManager::interpolateByChannelMap(Int spw,
    9027             :                                                                     const Vector<T> &inputDataStripe,
    9028             :                                                                     const Vector<bool> &inputFlagsStripe,
    9029             :                                                                     Vector<T> &outputDataStripe,
    9030             :                                                                     Vector<bool> &outputFlagsStripe)
    9031             : {
    9032       93650 :   Vector<T> intermDataStripe;
    9033       93650 :   Vector<bool> intermFlagsStripe;
    9034             :   // Bring frequencies from input grid to fake output grid ( the
    9035             :   // one with same widths as the original input channels).
    9036      187300 :   InterpolateArray1D<Double,T>::interpolate(intermDataStripe,
    9037             :                                             intermFlagsStripe,
    9038       93650 :                                             regridTCleanCHAN_FREQ_p, // Out channel freqs
    9039       93650 :                                             inputOutputSpwMap_p[spw].first.CHAN_FREQ_aux, // Input chan freqs
    9040             :                                             inputDataStripe,
    9041             :                                             inputFlagsStripe,
    9042       93650 :                                             interpolationMethod_p,
    9043             :                                             false, // flags
    9044             :                                             false // extrapolated data points are set flagged
    9045             :                                             );
    9046             : 
    9047             :   // Aggregate fine grain fake output channels into the final
    9048             :   // output channels
    9049       93650 :   outputDataStripe = 0;
    9050       93650 :   Vector<Double> outWeights;
    9051       93650 :   outWeights.resize(outputDataStripe.size());
    9052       93650 :   outWeights = 0.;
    9053    71743576 :   for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
    9054    71649926 :     Int outIdx = regridTCleanChanMap_p[mapIdx];
    9055    71649926 :     if (outIdx < 0)
    9056           0 :       continue;
    9057             : 
    9058    71649926 :     outputDataStripe[outIdx] = (outputDataStripe[outIdx] * outWeights[outIdx] +
    9059   109590384 :                                 intermDataStripe[mapIdx]) /
    9060    71649926 :       (1. + outWeights[outIdx]);
    9061    71649926 :     outWeights[outIdx] += 1;
    9062    71649926 :     outputFlagsStripe[outIdx] |= intermFlagsStripe[mapIdx];
    9063             :   }
    9064       93650 : }
    9065             : 
    9066             : // ------------------------------------------------------------------------
    9067             : // casacore::fftshift does not interpolate, it needs interpolation+fftshift
    9068             : // ------------------------------------------------------------------------
    9069      106801 : template <class T> void MSTransformManager::interpol1Dfftshift(Int inputSpw,
    9070             :                                                                const Vector<T> &inputDataStripe,
    9071             :                                                                const Vector<bool> &inputFlagsStripe,
    9072             :                                                                const Vector<Float> &inputWeightsStripe,
    9073             :                                                                Vector<T> &outputDataStripe,
    9074             :                                                                Vector<bool> &outputFlagsStripe)
    9075             : {
    9076      106801 :     Vector<T> regriddedDataStripe(outputDataStripe.shape(),T());
    9077      106801 :     Vector<bool> regriddedFlagsStripe(outputFlagsStripe.shape(),false);
    9078             : 
    9079             :     // This linear interpolation provides a uniform grid (pre-condition to apply fftshift)
    9080      106801 :     interpol1D(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,regriddedDataStripe,regriddedFlagsStripe);
    9081             : 
    9082             :     // fftshift takes care of time
    9083      106801 :     fftshift(inputSpw,regriddedDataStripe,regriddedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9084      106801 : }
    9085             : 
    9086             : // -----------------------------------------------------------------------
    9087             : //
    9088             : // -----------------------------------------------------------------------
    9089           4 : template <class T> void MSTransformManager::averageRegrid(Int inputSpw,
    9090             :                                                           const Vector<T> &inputDataStripe,
    9091             :                                                           const Vector<bool> &inputFlagsStripe,
    9092             :                                                           const Vector<Float> &inputWeightsStripe,
    9093             :                                                           Vector<T> &outputDataStripe,
    9094             :                                                           Vector<bool> &outputFlagsStripe)
    9095             : {
    9096           4 :         Vector<T> averagedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
    9097           4 :         Vector<bool> averagedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
    9098             : 
    9099           4 :         average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
    9100             : 
    9101           4 :         regrid(inputSpw,averagedDataStripe,averagedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9102             : 
    9103           8 :         return;
    9104           4 : }
    9105             : 
    9106             : // -----------------------------------------------------------------------
    9107             : //
    9108             : // -----------------------------------------------------------------------
    9109      184634 : template <class T> void MSTransformManager::smoothRegrid(Int inputSpw,
    9110             :                                                          const Vector<T> &inputDataStripe,
    9111             :                                                          const Vector<bool> &inputFlagsStripe,
    9112             :                                                          const Vector<Float> &inputWeightsStripe,
    9113             :                                                          Vector<T> &outputDataStripe,
    9114             :                                                          Vector<bool> &outputFlagsStripe)
    9115             : {
    9116      184634 :         Vector<T> smoothedDataStripe(inputDataStripe.shape(),T());
    9117      184634 :         Vector<bool> smoothedFlagsStripe(inputFlagsStripe.shape(),false);
    9118             : 
    9119      184634 :         smooth(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,smoothedDataStripe,smoothedFlagsStripe);
    9120             : 
    9121      184634 :         regrid(inputSpw,smoothedDataStripe,smoothedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9122             : 
    9123      369268 :         return;
    9124      184634 : }
    9125             : 
    9126             : // -----------------------------------------------------------------------
    9127             : //
    9128             : // -----------------------------------------------------------------------
    9129           0 : template <class T> void MSTransformManager::averageSmooth(Int inputSpw,
    9130             :                                                           const Vector<T> &inputDataStripe,
    9131             :                                                           const Vector<bool> &inputFlagsStripe,
    9132             :                                                           const Vector<Float> &inputWeightsStripe,
    9133             :                                                           Vector<T> &outputDataStripe,
    9134             :                                                           Vector<bool> &outputFlagsStripe)
    9135             : {
    9136           0 :         Vector<T> averagedDataStripe(outputDataStripe.shape(),T());
    9137           0 :         Vector<bool> averagedFlagsStripe(outputFlagsStripe.shape(),false);
    9138             : 
    9139           0 :         average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
    9140             : 
    9141           0 :         smooth(inputSpw,averagedDataStripe,averagedFlagsStripe, inputWeightsStripe, outputDataStripe,outputFlagsStripe);
    9142             : 
    9143           0 :         return;
    9144           0 : }
    9145             : 
    9146             : // -----------------------------------------------------------------------
    9147             : //
    9148             : // -----------------------------------------------------------------------
    9149           0 :   template <class T> void MSTransformManager::averageSmoothRegrid(Int inputSpw,
    9150             :                                                                   const Vector<T> &inputDataStripe,
    9151             :                                                                   const Vector<bool> &inputFlagsStripe,
    9152             :                                                                   const Vector<Float> &inputWeightsStripe,
    9153             :                                                                   Vector<T> &outputDataStripe,
    9154             :                                                                   Vector<bool> &outputFlagsStripe)
    9155             : {
    9156           0 :         Vector<T> averageSmoothedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
    9157           0 :         Vector<bool> averageSmoothedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
    9158             : 
    9159           0 :         averageSmooth(  inputSpw,inputDataStripe,inputFlagsStripe,
    9160             :                                         inputWeightsStripe,averageSmoothedDataStripe,averageSmoothedFlagsStripe);
    9161             : 
    9162           0 :         regrid( inputSpw,averageSmoothedDataStripe,averageSmoothedFlagsStripe,
    9163             :                         inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9164             : 
    9165           0 :         return;
    9166           0 : }
    9167             : 
    9168             : // -----------------------------------------------------------------------
    9169             : //
    9170             : // -----------------------------------------------------------------------
    9171      533008 : void MSTransformManager::smoothFourierFloat(Int,
    9172             :                                             const Vector<Float> &inputDataStripe,
    9173             :                                             const Vector<bool> &inputFlagStripe,
    9174             :                                             const Vector<Float> &,
    9175             :                                             Vector<Float> &outputDataStripe,
    9176             :                                             Vector<bool> &outputFlagStripe)
    9177             : {
    9178             :     // replace flagged channel data with zero
    9179      533008 :     auto mutableInputDataStripe = inputDataStripe;
    9180      533008 :     Int const numChan = mutableInputDataStripe.nelements();
    9181    44599088 :     for (Int ichan = 0; ichan < numChan; ++ichan) {
    9182    44066080 :         if (inputFlagStripe[ichan]) {
    9183    14365852 :             mutableInputDataStripe[ichan] = 0.0f;
    9184             :         }
    9185             :     }
    9186             : 
    9187             :     // execute convolution
    9188      533008 :     Convolver<Float> *convolver = getConvolver(numChan);
    9189      533008 :     convolver->linearConv(outputDataStripe, mutableInputDataStripe);
    9190             : 
    9191             :     // copy input flags
    9192      533008 :     outputFlagStripe = inputFlagStripe;
    9193      533008 : }
    9194             : 
    9195             : // -----------------------------------------------------------------------
    9196             : //
    9197             : // -----------------------------------------------------------------------
    9198      532932 : void MSTransformManager::smoothFourierComplex(Int n,
    9199             :                                               const Vector<Complex> &inputDataStripe,
    9200             :                                               const Vector<bool> &inputFlagStripe,
    9201             :                                               const Vector<Float> &inputWeightStripe,
    9202             :                                               Vector<Complex> &outputDataStripe, Vector<bool> &outputFlagStripe)
    9203             : {
    9204      532932 :     Vector<Float> inputDataStripeFloat = real(inputDataStripe);
    9205      532932 :     Vector<Float> outputDataStripeFloat(inputDataStripeFloat.nelements());
    9206      532932 :     smoothFourierFloat(n, inputDataStripeFloat, inputFlagStripe,
    9207             :             inputWeightStripe, outputDataStripeFloat, outputFlagStripe);
    9208      532932 :     convertArray(outputDataStripe, outputDataStripeFloat);
    9209      532932 : }
    9210             : 
    9211             : // -----------------------------------------------------------------------
    9212             : //
    9213             : // -----------------------------------------------------------------------
    9214      533008 : Convolver<Float> *MSTransformManager::getConvolver(Int const numChan) {
    9215      533008 :     if (convolverPool_.find(numChan) == convolverPool_.end()) {
    9216           0 :         throw AipsError("Failed to get convolver. Smoothing is not properly configured.");
    9217             :     }
    9218      533008 :     return &convolverPool_[numChan];
    9219             : }
    9220             : 
    9221             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16