LCOV - code coverage report
Current view: top level - mstransform/MSTransform - MSTransformManager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1371 4174 32.8 %
Date: 2025-08-21 08:01:32 Functions: 94 206 45.6 %

          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          35 : MSTransformManager::MSTransformManager()
      62             : {
      63          35 :         initialize();
      64          35 :         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          70 : MSTransformManager::~MSTransformManager()
      83             : {
      84             :         // Close the output MS in case the application layer does not do it
      85          35 :         close();
      86             : 
      87          35 :         if (channelSelector_p) delete channelSelector_p;
      88          35 :         if (visibilityIterator_p and !factory_p) delete visibilityIterator_p;
      89          35 :         if (dataHandler_p) delete dataHandler_p;
      90          35 :         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          35 :         if (userBufferMode_p)
      95             :         {
      96           0 :                 TableUtil::deleteTable(outMsName_p,true);
      97             :         }
      98             : 
      99          35 :         return;
     100          70 : }
     101             : 
     102             : // -----------------------------------------------------------------------
     103             : // Method to initialize members to default values
     104             : // -----------------------------------------------------------------------
     105          35 : void MSTransformManager::initialize()
     106             : {
     107             :         // MS specification parameters
     108          35 :         inpMsName_p = String("");
     109          35 :         outMsName_p = String("");
     110          35 :         datacolumn_p = String("CORRECTED");
     111          35 :         makeVirtualModelColReal_p = false; // MODEL_DATA should always be made real via the datacol param.
     112          35 :         makeVirtualCorrectedColReal_p = true; // TODO: CORRECTED_DATA should be made real on request
     113          35 :         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          35 :         tileShape_p(0) = 0;
     119             : 
     120             :         // Data selection parameters
     121          35 :         arraySelection_p = String("");
     122          35 :         fieldSelection_p = String("");
     123          35 :         scanSelection_p = String("");
     124          35 :         timeSelection_p = String("");
     125          35 :         spwSelection_p = String("");
     126          35 :         baselineSelection_p = String("");
     127          35 :         uvwSelection_p = String("");
     128          35 :         polarizationSelection_p = String("");
     129          35 :         scanIntentSelection_p = String("");
     130          35 :         observationSelection_p = String("");
     131          35 :         taqlSelection_p = String("");
     132          35 :         feedSelection_p = String("");
     133             : 
     134             :         // Input-Output index maps
     135          35 :         inputOutputObservationIndexMap_p.clear();
     136          35 :         inputOutputArrayIndexMap_p.clear();
     137          35 :         inputOutputScanIndexMap_p.clear();
     138          35 :         inputOutputScanIntentIndexMap_p.clear();
     139          35 :         inputOutputFieldIndexMap_p.clear();
     140          35 :         inputOutputSPWIndexMap_p.clear();
     141          35 :         inputOutputDDIndexMap_p.clear();
     142          35 :         inputOutputAntennaIndexMap_p.clear();
     143          35 :         outputInputSPWIndexMap_p.clear();
     144          35 :         inputOutputChanIndexMap_p.clear();
     145             : 
     146             :         // Frequency transformation parameters
     147          35 :         smoothCoeff_p.resize(3,false);
     148          35 :         smoothCoeff_p(0) = 0.25;
     149          35 :         smoothCoeff_p(1) = 0.5;
     150          35 :         smoothCoeff_p(2) = 0.25;
     151             : 
     152             :         // Frequency specification parameters
     153          35 :         mode_p = String("channel");                                   // Options are: channel, frequency, velocity
     154          35 :         start_p = String("0");
     155          35 :         width_p = String("1");
     156          35 :         nChan_p = -1;                                                                   // -1 means use all the input channels
     157          35 :         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          35 :         dx_p = 0;
     163          35 :         dy_p = 0;
     164          35 :         tviphaseshift_p = False;
     165          35 :         tviphaseshiftConfig_p = Record();
     166             : 
     167             :         // Time transformation parameters
     168          35 :         scalarAverage_p = false;
     169          35 :         timeAverage_p = false;
     170          35 :         timeBin_p = 0.0;
     171          35 :         timespan_p = String("");
     172          35 :         timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
     173          35 :         maxuvwdistance_p = 0;
     174             :         // minbaselines_p = 0;
     175             : 
     176             :         // Cal parameters
     177          35 :         calibrate_p = false;
     178          35 :         callib_p = "";
     179          35 :         callibRec_p = Record();
     180             : 
     181             :         // UVContSub parameters
     182          35 :         uvcontsub_p = False;
     183          35 :         uvcontsubRec_p = Record();
     184             : 
     185             :         // Spw averaging
     186          35 :         spwAverage_p = false;
     187             : 
     188             :         // Polarization transformation
     189          35 :         polAverage_p = false;
     190          35 :         polAverageConfig_p = Record();
     191             : 
     192             :         // Pointings interpolation
     193          35 :         pointingsInterpolation_p = false;
     194          35 :         pointingsInterpolationConfig_p = Record();
     195             : 
     196             :         // Weight Spectrum parameters
     197          35 :         usewtspectrum_p = false;
     198          35 :         spectrumTransformation_p = false;
     199          35 :         propagateWeights_p = false;
     200          35 :         flushWeightSpectrum_p = false;
     201             : 
     202             :         // MS-related members
     203          35 :         dataHandler_p = NULL;
     204          35 :         inputMs_p = NULL;
     205          35 :         selectedInputMs_p = NULL;
     206          35 :         outputMs_p = NULL;
     207          35 :         selectedInputMsCols_p = NULL;
     208          35 :         outputMsCols_p = NULL;
     209             : 
     210             :         // VI/VB related members
     211          35 :         sortColumns_p = Block<Int>(7);
     212          35 :         sortColumns_p[0] = MS::OBSERVATION_ID;
     213          35 :         sortColumns_p[1] = MS::ARRAY_ID;
     214          35 :         sortColumns_p[2] = MS::SCAN_NUMBER;
     215          35 :         sortColumns_p[3] = MS::STATE_ID;
     216          35 :         sortColumns_p[4] = MS::FIELD_ID;
     217          35 :         sortColumns_p[5] = MS::DATA_DESC_ID;
     218          35 :         sortColumns_p[6] = MS::TIME;
     219          35 :         visibilityIterator_p = NULL;
     220          35 :         channelSelector_p = NULL;
     221             : 
     222             :         // Output MS structure related members
     223          35 :         inputFlagCategoryAvailable_p = false;
     224          35 :         inputWeightSpectrumAvailable_p = false;
     225          35 :         weightSpectrumFromSigmaFilled_p = false;
     226          35 :         correctedToData_p = false;
     227          35 :         bothDataColumnsAreOutput_p = false;
     228          35 :         doingData_p = false;
     229          35 :         doingCorrected_p = false;
     230          35 :         doingModel_p = false;
     231          35 :         dataColMap_p.clear();
     232          35 :         mainColumn_p = MS::CORRECTED_DATA;
     233          35 :         nRowsToAdd_p = 0;
     234             : 
     235             :         // Frequency transformation members
     236          35 :         chansPerOutputSpw_p = 0;
     237          35 :         tailOfChansforLastSpw_p = 0;
     238          35 :         interpolationMethod_p = MSTransformations::linear;
     239          35 :         baselineMap_p.clear();
     240          35 :         rowIndex_p.clear();
     241          35 :         spwChannelMap_p.clear();
     242          35 :         inputOutputSpwMap_p.clear();
     243          35 :         inputOutputChanFactorMap_p.clear();
     244          35 :         freqbinMap_p.clear();
     245          35 :         numOfInpChanMap_p.clear();
     246          35 :         numOfSelChanMap_p.clear();
     247          35 :         numOfOutChanMap_p.clear();
     248          35 :         numOfCombInputChanMap_p.clear();
     249          35 :         numOfCombInterChanMap_p.clear();
     250          35 :         weightFactorMap_p.clear();
     251          35 :         sigmaFactorMap_p.clear();
     252          35 :         newWeightFactorMap_p.clear();
     253          35 :         newSigmaFactorMap_p.clear();
     254             : 
     255             :         // Reference frame transformation members
     256          35 :         fftShiftEnabled_p = false;
     257          35 :         fftShift_p = 0;
     258             : 
     259             :         // Weight Spectrum members
     260          35 :         inputWeightSpectrumAvailable_p = false;
     261          35 :         combinationOfSPWsWithDifferentExposure_p = false;
     262             : 
     263             :         // Transformations - related function pointers
     264          35 :         transformCubeOfDataComplex_p = NULL;
     265          35 :         transformCubeOfDataFloat_p = NULL;
     266          35 :         fillWeightsPlane_p = NULL;
     267          35 :         setWeightsPlaneByReference_p = NULL;
     268          35 :         setWeightStripeByReference_p = NULL;
     269          35 :         transformStripeOfDataComplex_p = NULL;
     270          35 :         transformStripeOfDataFloat_p = NULL;
     271          35 :         averageKernelComplex_p = NULL;
     272          35 :         averageKernelFloat_p = NULL;
     273          35 :         smoothKernelComplex_p = NULL;
     274          35 :         smoothKernelFloat_p = NULL;
     275             : 
     276             :         // I/O related function pointers
     277          35 :         writeOutputPlanesComplex_p = NULL;
     278          35 :         writeOutputPlanesFloat_p = NULL;
     279          35 :         writeOutputFlagsPlane_p = NULL;
     280          35 :         writeOutputFlagsPlaneSlices_p = NULL;
     281          35 :         writeOutputFlagsPlaneReshapedSlices_p = NULL;
     282             : 
     283             :         // Buffer handling members
     284          35 :         bufferMode_p = false;
     285          35 :         userBufferMode_p = false;
     286          35 :         reindex_p = true;
     287          35 :         factory_p = False;
     288          35 :         interactive_p = false;
     289          35 :         spectrumReshape_p = false;
     290          35 :         cubeTransformation_p = false;
     291          35 :         dataColumnAvailable_p = false;
     292          35 :         correctedDataColumnAvailable_p = false;
     293          35 :         modelDataColumnAvailable_p = false;
     294          35 :         floatDataColumnAvailable_p = false;
     295          35 :         flagCube_p = NULL;
     296          35 :         visCube_p = NULL;
     297          35 :         visCubeCorrected_p = NULL;
     298          35 :         visCubeModel_p = NULL;
     299          35 :         visCubeFloat_p = NULL;
     300          35 :         weightSpectrum_p = NULL;
     301          35 :         sigmaSpectrum_p = NULL;
     302          35 :         weight_p = NULL;
     303          35 :         sigma_p = NULL;
     304          35 :         relativeRow_p = 0;
     305             : 
     306             :         // single dish specific
     307          35 :         smoothFourier_p = false;
     308             : 
     309          35 :         return;
     310             : }
     311             : 
     312             : // -----------------------------------------------------------------------
     313             : // Method to parse the configuration parameters
     314             : // -----------------------------------------------------------------------
     315          35 : void MSTransformManager::configure(Record &configuration)
     316             : {
     317          35 :         parseMsSpecParams(configuration);
     318          35 :         parseDataSelParams(configuration);
     319          35 :         parseFreqTransParams(configuration);
     320          35 :         parseChanAvgParams(configuration);
     321          35 :         parseRefFrameTransParams(configuration);
     322          35 :         parseTimeAvgParams(configuration);
     323          35 :         parseCalParams(configuration);
     324          35 :         parseUVContSubParams(configuration);
     325          35 :         setSpwAvg(configuration);
     326          35 :         parsePolAvgParams(configuration);
     327          35 :         parsePointingsInterpolationParams(configuration);
     328          35 :         parsePhaseShiftParams(configuration);
     329          35 :         parseAtmCorrectionParams(configuration);
     330             : 
     331          35 :         return;
     332             : }
     333             : 
     334             : // -----------------------------------------------------------------------
     335             : // Method to parse input/output MS specification
     336             : // -----------------------------------------------------------------------
     337          35 : void MSTransformManager::parseMsSpecParams(Record &configuration)
     338             : {
     339          35 :         int exists = -1;
     340             : 
     341          35 :         exists = -1;
     342          35 :         exists = configuration.fieldNumber ("inputms");
     343          35 :         if (exists >= 0)
     344             :         {
     345          35 :                 configuration.get (exists, inpMsName_p);
     346          70 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     347          70 :                                 << "Input file name is " << inpMsName_p << LogIO::POST;
     348             :         }
     349             : 
     350          35 :         exists = -1;
     351          35 :         exists = configuration.fieldNumber ("buffermode");
     352          35 :         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          35 :         exists = -1;
     363          35 :         exists = configuration.fieldNumber ("datacolumn");
     364          35 :         if (exists >= 0)
     365             :         {
     366          35 :                 configuration.get (exists, datacolumn_p);
     367          70 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     368          70 :                                 << "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          35 :         exists = -1;
     373          35 :         exists = configuration.fieldNumber ("outputms");
     374          35 :         if (exists >= 0)
     375             :         {
     376          35 :                 configuration.get (exists, outMsName_p);
     377             : 
     378             :                 // Inform of filename only in normal mode, as in buffer mode is random generated
     379          35 :                 if (not bufferMode_p)
     380             :                 {
     381          70 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     382          70 :                                                 << "Output file name is " << outMsName_p << LogIO::POST;
     383             :                 }
     384             :         }
     385             : 
     386          35 :         exists = -1;
     387          35 :         exists = configuration.fieldNumber ("reindex");
     388          35 :         if (exists >= 0)
     389             :         {
     390          31 :                 configuration.get (exists, reindex_p);
     391             : 
     392          31 :                 if (reindex_p)
     393             :                 {
     394          62 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     395          62 :                                         << "Re-index is enabled " << LogIO::POST;
     396             :                 }
     397             :                 else
     398             :                 {
     399           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     400           0 :                                         << "Re-index is disabled " << LogIO::POST;
     401             :                 }
     402             :         }
     403             : 
     404          35 :         exists = -1;
     405          35 :         exists = configuration.fieldNumber ("factory");
     406          35 :         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          35 :         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          35 :                 interactive_p = false;
     442             : 
     443          35 :                 exists = -1;
     444          35 :                 exists = configuration.fieldNumber ("realmodelcol");
     445          35 :                 if (exists >= 0)
     446             :                 {
     447           3 :                         configuration.get (exists, makeVirtualModelColReal_p);
     448           3 :                         if (makeVirtualModelColReal_p)
     449             :                         {
     450           0 :                                 if (datacolumn_p.contains("ALL") or datacolumn_p.contains("MODEL"))
     451             :                                 {
     452           0 :                                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     453             :                                                         << "MODEL column will be made real in the output MS "
     454           0 :                                                         << 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          35 :                 exists = -1;
     469          35 :                 exists = configuration.fieldNumber ("usewtspectrum");
     470          35 :                 if (exists >= 0)
     471             :                 {
     472          31 :                         configuration.get (exists, usewtspectrum_p);
     473          31 :                         if (usewtspectrum_p)
     474             :                         {
     475           2 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     476           2 :                                                 << "WEIGHT_SPECTRUM will be written in output MS " << LogIO::POST;
     477             :                         }
     478             :                 }
     479             : 
     480          35 :                 exists = -1;
     481          35 :                 exists = configuration.fieldNumber ("tileshape");
     482          35 :                 if (exists >= 0)
     483             :                 {
     484          31 :                         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          31 :                         else if ( configuration.type(exists) == casacore::TpArrayInt)
     491             :                         {
     492          31 :                                 configuration.get (exists, tileShape_p);
     493             :                         }
     494             : 
     495          62 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     496          62 :                                         << "Tile shape is " << tileShape_p << LogIO::POST;
     497             :                 }
     498             :         }
     499             : 
     500          35 :         return;
     501             : }
     502             : 
     503             : // -----------------------------------------------------------------------
     504             : // Method to parse the data selection parameters
     505             : // -----------------------------------------------------------------------
     506          35 : void MSTransformManager::parseDataSelParams(Record &configuration)
     507             : {
     508          35 :         int exists = -1;
     509             : 
     510          35 :         exists = -1;
     511          35 :         exists = configuration.fieldNumber ("array");
     512          35 :         if (exists >= 0)
     513             :         {
     514           0 :                 configuration.get (exists, arraySelection_p);
     515           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     516           0 :                                 << "array selection is " << arraySelection_p << LogIO::POST;
     517             :         }
     518             : 
     519          35 :         exists = -1;
     520          35 :         exists = configuration.fieldNumber ("field");
     521          35 :         if (exists >= 0)
     522             :         {
     523           0 :                 configuration.get (exists, fieldSelection_p);
     524           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     525           0 :                                 << "field selection is " << fieldSelection_p << LogIO::POST;
     526             :         }
     527             : 
     528          35 :         exists = -1;
     529          35 :         exists = configuration.fieldNumber ("scan");
     530          35 :         if (exists >= 0)
     531             :         {
     532           1 :                 configuration.get (exists, scanSelection_p);
     533           2 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     534           2 :                                 << "scan selection is " << scanSelection_p << LogIO::POST;
     535             :         }
     536             : 
     537          35 :         exists = -1;
     538          35 :         exists = configuration.fieldNumber ("timerange");
     539          35 :         if (exists >= 0)
     540             :         {
     541           1 :                 configuration.get (exists, timeSelection_p);
     542           2 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     543           2 :                                 << "timerange selection is " << timeSelection_p << LogIO::POST;
     544             :         }
     545             : 
     546          35 :         exists = -1;
     547          35 :         exists = configuration.fieldNumber ("spw");
     548          35 :         if (exists >= 0)
     549             :         {
     550           3 :                 configuration.get (exists, spwSelection_p);
     551           6 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     552           6 :                                 << "spw selection is " << spwSelection_p << LogIO::POST;
     553             :         }
     554             : 
     555          35 :         exists = -1;
     556          35 :         exists = configuration.fieldNumber ("antenna");
     557          35 :         if (exists >= 0)
     558             :         {
     559           1 :                 configuration.get (exists, baselineSelection_p);
     560           2 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     561           2 :                                 << "antenna selection is " << baselineSelection_p << LogIO::POST;
     562             :         }
     563             : 
     564          35 :         exists = -1;
     565          35 :         exists = configuration.fieldNumber ("uvrange");
     566          35 :         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          35 :         exists = -1;
     574          35 :         exists = configuration.fieldNumber ("correlation");
     575          35 :         if (exists >= 0)
     576             :         {
     577           0 :                 configuration.get (exists, polarizationSelection_p);
     578           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     579           0 :                                 << "correlation selection is " << polarizationSelection_p << LogIO::POST;
     580             :         }
     581             : 
     582          35 :         exists = -1;
     583          35 :         exists = configuration.fieldNumber ("observation");
     584          35 :         if (exists >= 0)
     585             :         {
     586           0 :                 configuration.get (exists, observationSelection_p);
     587           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     588           0 :                                 <<"observation selection is " << observationSelection_p << LogIO::POST;
     589             :         }
     590             : 
     591          35 :         exists = -1;
     592          35 :         exists = configuration.fieldNumber ("intent");
     593          35 :         if (exists >= 0)
     594             :         {
     595           0 :                 configuration.get (exists, scanIntentSelection_p);
     596           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     597           0 :                                 << "scan intent selection is " << scanIntentSelection_p << LogIO::POST;
     598             :         }
     599             : 
     600          35 :         exists = -1;
     601          35 :         exists = configuration.fieldNumber ("taql");
     602          35 :         if (exists >= 0)
     603             :         {
     604           0 :                 configuration.get (exists, taqlSelection_p);
     605           0 :                 logger_p << LogIO::NORMAL2 << LogOrigin("MSTransformManager", __FUNCTION__)
     606           0 :                                 << "TaQL selection is " << taqlSelection_p << LogIO::POST;
     607             :         }
     608             : 
     609          35 :         exists = -1;
     610          35 :         exists = configuration.fieldNumber ("feed");
     611          35 :         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          35 :         return;
     619             : }
     620             : 
     621             : // -----------------------------------------------------------------------
     622             : // Method to parse the channel average parameters
     623             : // -----------------------------------------------------------------------
     624          35 : void MSTransformManager::parseChanAvgParams(Record &configuration)
     625             : {
     626          35 :     int exists = -1;
     627             : 
     628          35 :     exists = -1;
     629          35 :     exists = configuration.fieldNumber ("chanaverage");
     630          35 :     if (exists >= 0)
     631             :     {
     632          17 :         configuration.get (exists, channelAverage_p);
     633          17 :         if (channelAverage_p)
     634             :         {
     635          34 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     636          34 :                                                 << "Channel average is activated" << LogIO::POST;
     637             :         }
     638             :         else
     639             :         {
     640           0 :             return;
     641             :         }
     642             :     }
     643             :     else
     644             :     {
     645          18 :         return;
     646             :     }
     647             : 
     648          17 :     exists = -1;
     649          17 :     exists = configuration.fieldNumber ("chanbin");
     650          17 :     if (exists >= 0)
     651             :     {
     652          17 :         if ( configuration.type(exists) == casacore::TpInt )
     653             :         {
     654             :             Int freqbin;
     655          17 :             configuration.get (exists, freqbin);
     656             : 
     657          17 :             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          17 :                 freqbin_p = Vector<Int>(1,freqbin);
     666             : 
     667             :             }
     668             :         }
     669           0 :         else if ( configuration.type(exists) == casacore::TpArrayInt)
     670             :         {
     671           0 :             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           0 :             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          34 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     685          34 :                                         << "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          17 :     return;
     725             : }
     726             : 
     727             : // -----------------------------------------------------------------------
     728             : // Method to parse the frequency transformation parameters
     729             : // -----------------------------------------------------------------------
     730          35 : void MSTransformManager::parseFreqTransParams(Record &configuration)
     731             : {
     732          35 :         int exists = -1;
     733             : 
     734          35 :         exists = -1;
     735          35 :         exists = configuration.fieldNumber ("combinespws");
     736          35 :         if (exists >= 0)
     737             :         {
     738           0 :                 configuration.get (exists, combinespws_p);
     739             : 
     740           0 :                 if (combinespws_p)
     741             :                 {
     742           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     743           0 :                                         << "Combine Spectral Windows is activated" << LogIO::POST;
     744             :                 }
     745             :         }
     746             : 
     747          35 :         exists = -1;
     748          35 :         exists = configuration.fieldNumber ("ddistart");
     749          35 :         if (exists >= 0)
     750             :         {
     751          31 :                 configuration.get (exists, ddiStart_p);
     752          31 :                 if (ddiStart_p > 0)
     753             :                 {
     754           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     755           0 :                                         << "DDI start is " << ddiStart_p << LogIO::POST;
     756             :                 }
     757             :                 else
     758             :                 {
     759          31 :                         ddiStart_p = 0;
     760             :                 }
     761             : 
     762             :         }
     763             : 
     764          35 :         exists = -1;
     765          35 :         exists = configuration.fieldNumber ("hanning");
     766          35 :         if (exists >= 0)
     767             :         {
     768           0 :                 configuration.get (exists, hanningSmooth_p);
     769             : 
     770           0 :                 if (hanningSmooth_p)
     771             :                 {
     772           0 :                         smoothBin_p = 3;
     773           0 :                         smoothCoeff_p.resize(3,false);
     774           0 :                         smoothCoeff_p(0) = 0.25;
     775           0 :                         smoothCoeff_p(1) = 0.5;
     776           0 :                         smoothCoeff_p(2) = 0.25;
     777           0 :                         weightmode_p = MSTransformations::plainSmooth;
     778           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     779           0 :                                         << "Hanning Smooth is activated" << LogIO::POST;
     780           0 :                         exists = -1;
     781           0 :                         exists = configuration.fieldNumber ("smooth_spw");
     782           0 :                         if (exists >= 0)
     783             :                         {
     784           0 :                                 Array<int> smooth_spw;
     785           0 :                                 configuration.get (exists, smooth_spw);
     786           0 :                                 smooth_spw_p = smooth_spw.tovector();
     787           0 :                         }
     788             :                 }
     789             :         }
     790             : 
     791          35 :         exists = -1;
     792          35 :         exists = configuration.fieldNumber("smoothFourier");
     793          35 :         if (exists >= 0)
     794             :         {
     795           0 :             configuration.get(exists, smoothFourier_p);
     796           0 :             if (smoothFourier_p) {
     797           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     798           0 :                         << "Fourier smoothing (single dish specific) is activated" << LogIO::POST;
     799             :             }
     800             :         }
     801             : 
     802          35 :         return;
     803             : }
     804             : 
     805             : // -----------------------------------------------------------------------
     806             : // Method to parse the reference frame transformation parameters
     807             : // -----------------------------------------------------------------------
     808          35 : void MSTransformManager::parseRefFrameTransParams(Record &configuration)
     809             : {
     810          35 :         int exists = -1;
     811             : 
     812          35 :         exists = -1;
     813          35 :         exists = configuration.fieldNumber ("regridms");
     814          35 :         if (exists >= 0)
     815             :         {
     816           0 :                 configuration.get (exists, regridding_p);
     817             : 
     818           0 :                 if (regridding_p)
     819             :                 {
     820           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     821           0 :                                         << "Regrid MS is activated"<< LogIO::POST;
     822             :                 }
     823             :                 else
     824             :                 {
     825           0 :                         return;
     826             :                 }
     827             :         }
     828             : 
     829          35 :         exists = -1;
     830          35 :         exists = configuration.fieldNumber ("phasecenter");
     831          35 :         if (exists >= 0)
     832             :         {
     833             :                 //If phase center is a simple numeric value then it is taken
     834             :                 // as a FIELD_ID otherwise it is converted to a MDirection
     835           0 :         if( configuration.type(exists) == TpInt )
     836             :         {
     837           0 :                 int fieldIdForPhaseCenter = -1;
     838           0 :                 configuration.get (exists, fieldIdForPhaseCenter);
     839           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     840           0 :                                 << "Field Id for phase center is " << fieldIdForPhaseCenter << LogIO::POST;
     841           0 :                 if (phaseCenterPar_p) delete phaseCenterPar_p;
     842           0 :                 phaseCenterPar_p = new casac::variant((long)fieldIdForPhaseCenter);
     843             :         }
     844             :         else
     845             :         {
     846           0 :                 String phaseCenter("");
     847           0 :                 configuration.get (exists, phaseCenter);
     848           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     849           0 :                                 << "Phase center is " << phaseCenter << LogIO::POST;
     850           0 :                 if (phaseCenterPar_p) delete phaseCenterPar_p;
     851           0 :                 phaseCenterPar_p = new casac::variant(phaseCenter);
     852           0 :         }
     853             :         }
     854             : 
     855          35 :         exists = -1;
     856          35 :         exists = configuration.fieldNumber ("restfreq");
     857          35 :         if (exists >= 0)
     858             :         {
     859           0 :                 configuration.get (exists, restFrequency_p);
     860           0 :                 if (!restFrequency_p.empty())
     861             :                 {
     862           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     863           0 :                                         << "Rest frequency is " << restFrequency_p << LogIO::POST;
     864             :                 }
     865             :         }
     866             : 
     867          35 :         exists = -1;
     868          35 :         exists = configuration.fieldNumber ("outframe");
     869          35 :         if (exists >= 0)
     870             :         {
     871           0 :                 configuration.get (exists, outputReferenceFramePar_p);
     872           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     873           0 :                                 << "Output reference frame is " << outputReferenceFramePar_p << LogIO::POST;
     874             :         }
     875             : 
     876          35 :         exists = -1;
     877          35 :         exists = configuration.fieldNumber ("interpolation");
     878          35 :         if (exists >= 0)
     879             :         {
     880           0 :                 configuration.get (exists, interpolationMethodPar_p);
     881             : 
     882           0 :                 if (interpolationMethodPar_p.contains("nearest"))
     883             :                 {
     884           0 :                         interpolationMethod_p = MSTransformations::nearestNeighbour;
     885             :                 }
     886           0 :                 else if (interpolationMethodPar_p.contains("linear"))
     887             :                 {
     888           0 :                         interpolationMethod_p = MSTransformations::linear;
     889             :                 }
     890           0 :                 else if (interpolationMethodPar_p.contains("cubic"))
     891             :                 {
     892           0 :                         interpolationMethod_p = MSTransformations::cubic;
     893             :                 }
     894           0 :                 else if (interpolationMethodPar_p.contains("spline"))
     895             :                 {
     896           0 :                         interpolationMethod_p = MSTransformations::spline;
     897             :                 }
     898           0 :                 else if (interpolationMethodPar_p.contains("fftshift"))
     899             :                 {
     900           0 :                         fftShiftEnabled_p = true;
     901           0 :                         interpolationMethod_p = MSTransformations::linear;
     902             :                 }
     903             :                 else
     904             :                 {
     905           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
     906           0 :                                         << "Interpolation method " << interpolationMethodPar_p  << " not available " << LogIO::POST;
     907             :                 }
     908             : 
     909           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     910           0 :                                 << "Interpolation method is " << interpolationMethodPar_p  << LogIO::POST;
     911             :         }
     912             :         else
     913             :         {
     914          35 :                 interpolationMethod_p = MSTransformations::linear;
     915             :         }
     916             : 
     917          35 :         exists = -1;
     918          35 :         exists = configuration.fieldNumber ("nspw");
     919          35 :         if (exists >= 0)
     920             :         {
     921           0 :                 configuration.get (exists, nspws_p);
     922             : 
     923           0 :                 if (nspws_p > 1)
     924             :                 {
     925           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     926           0 :                                         << "Number of output SPWs is " << nspws_p << LogIO::POST;
     927           0 :                         combinespws_p = true;
     928             :                 }
     929             :                 else
     930             :                 {
     931           0 :                         nspws_p = 1;
     932             :                 }
     933             :         }
     934             : 
     935          35 :         parseFreqSpecParams(configuration);
     936             : 
     937          35 :         exists = configuration.fieldNumber ("preaverage");
     938          35 :         if (exists >= 0) {
     939           0 :           configuration.get (exists, enableChanPreAverage_p);
     940             : 
     941           0 :           if (combinespws_p) {
     942           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     943           0 :                      << "Enabling channel pre-averaging" << LogIO::POST;
     944             :           }
     945             :         }
     946             : 
     947          35 :         return;
     948             : }
     949             : 
     950             : // -----------------------------------------------------------------------
     951             : // Method to parse the frequency selection specification
     952             : // -----------------------------------------------------------------------
     953          35 : void MSTransformManager::parseFreqSpecParams(Record &configuration)
     954             : {
     955          35 :         int exists = -1;
     956             : 
     957          35 :         exists = -1;
     958          35 :         exists = configuration.fieldNumber ("mode");
     959          35 :         if (exists >= 0)
     960             :         {
     961           0 :                 configuration.get (exists, mode_p);
     962           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     963           0 :                                 << "Mode is " << mode_p<< LogIO::POST;
     964             : 
     965           0 :                 if ((mode_p == "frequency") or (mode_p == "velocity"))
     966             :                 {
     967           0 :                         start_p = String("");
     968           0 :                         width_p = String("");
     969             :                 }
     970             :         }
     971             : 
     972          35 :         exists = -1;
     973          35 :         exists = configuration.fieldNumber ("nchan");
     974          35 :         if (exists >= 0)
     975             :         {
     976           0 :                 configuration.get (exists, nChan_p);
     977           0 :                 if (nspws_p > 1)
     978             :                 {
     979           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     980           0 :                                         << "Number of output channels per output spw is " << nChan_p << LogIO::POST;
     981           0 :                         nChan_p *=  nspws_p;
     982             :                 }
     983             :                 else
     984             :                 {
     985           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     986           0 :                                         << "Number of output channels is " << nChan_p<< LogIO::POST;
     987             :                 }
     988             :         }
     989             : 
     990          35 :         exists = -1;
     991          35 :         exists = configuration.fieldNumber ("start");
     992          35 :         if (exists >= 0)
     993             :         {
     994           0 :                 configuration.get (exists, start_p);
     995           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
     996           0 :                                 << "Start is " << start_p << LogIO::POST;
     997             :         }
     998             : 
     999          35 :         exists = -1;
    1000          35 :         exists = configuration.fieldNumber ("width");
    1001          35 :         if (exists >= 0)
    1002             :         {
    1003           0 :                 configuration.get (exists, width_p);
    1004           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1005           0 :                                 << "Width is " << width_p << LogIO::POST;
    1006             :         }
    1007             : 
    1008          35 :         exists = -1;
    1009          35 :         exists = configuration.fieldNumber ("veltype");
    1010          35 :         if ((exists >= 0) and (mode_p == "velocity"))
    1011             :         {
    1012           0 :                 configuration.get (exists, velocityType_p);
    1013           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1014           0 :                                 << "Velocity type is " << velocityType_p << LogIO::POST;
    1015             :         }
    1016             : 
    1017          35 :         return;
    1018             : }
    1019             : 
    1020             : // -----------------------------------------------------------------------
    1021             : // Method to parse the phase shifting specification
    1022             : // -----------------------------------------------------------------------
    1023             : // CAS-12706 To run phase shift via a TVI which has
    1024             : // support for shifting across large offset/angles
    1025             : // -----------------------------------------------------------------------
    1026          35 : void MSTransformManager::parsePhaseShiftParams(Record &configuration)
    1027             : {
    1028          35 :         int exists = -1;
    1029             : 
    1030          35 :         exists = -1;
    1031          35 :         exists = configuration.fieldNumber("tviphaseshift");
    1032          35 :         if (exists >= 0)
    1033             :         {
    1034           0 :                 configuration.get (exists, tviphaseshift_p);
    1035             : 
    1036           0 :                 if (tviphaseshift_p)
    1037             :                 {
    1038             :                         // Extract the callib Record
    1039           0 :                         exists = -1;
    1040           0 :                         exists = configuration.fieldNumber("tviphaseshiftlib");
    1041           0 :                         if (configuration.type(exists) == TpRecord)
    1042             :                         {
    1043           0 :                                 tviphaseshiftConfig_p = configuration.subRecord(exists);
    1044             :                         }
    1045             : 
    1046           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    1047             :                                                 << "Phase shifting via TVI with support for large offset/angle "
    1048           0 :                                                 << LogIO::POST;
    1049             :                 }
    1050             :         }
    1051             : 
    1052          35 :         return;
    1053             : }
    1054             : 
    1055             : // -----------------------------------------------------------------------
    1056             : // Method to parse the time average specification
    1057             : // -----------------------------------------------------------------------
    1058          35 : void MSTransformManager::parseTimeAvgParams(Record &configuration)
    1059             : {
    1060          35 :         int exists = -1;
    1061             : 
    1062          35 :         exists = -1;
    1063          35 :         exists = configuration.fieldNumber ("timeaverage");
    1064          35 :         if (exists >= 0)
    1065             :         {
    1066          19 :                 configuration.get (exists, timeAverage_p);
    1067             : 
    1068          19 :                 if (timeAverage_p)
    1069             :                 {
    1070          38 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1071          38 :                                         << "Time average is activated" << LogIO::POST;
    1072             :                 }
    1073             :         }
    1074             : 
    1075          35 :     exists = -1;
    1076          35 :         exists = configuration.fieldNumber ("scalaraverage");
    1077          35 :         if (exists >= 0)
    1078             :         {
    1079           0 :                 configuration.get (exists, scalarAverage_p);
    1080             : 
    1081           0 :                 if (scalarAverage_p)
    1082             :                 {
    1083           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1084           0 :                                         << "Scalar average is activated" << LogIO::POST;
    1085             :                 }
    1086             :         }
    1087             : 
    1088          35 :         if (timeAverage_p || scalarAverage_p)
    1089             :         {
    1090          19 :                 exists = -1;
    1091          19 :                 exists = configuration.fieldNumber ("timebin");
    1092          19 :                 if (exists >= 0)
    1093             :                 {
    1094          19 :                         String timebin;
    1095          19 :                         configuration.get (exists, timebin);
    1096          19 :                         timeBin_p=casaQuantity(timebin).get("s").getValue();
    1097             : 
    1098          38 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1099          38 :                                         << "Time bin is " << timeBin_p << " seconds" << LogIO::POST;
    1100          19 :                 }
    1101             :                 else
    1102             :                 {
    1103           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1104           0 :                                         << "Time or scalar average is activated but no timebin parameter provided " << LogIO::POST;
    1105           0 :                         timeAverage_p = false;
    1106           0 :                         scalarAverage_p = false;
    1107           0 :                         return;
    1108             :                 }
    1109             : 
    1110          19 :                 exists = -1;
    1111          19 :                 exists = configuration.fieldNumber ("timespan");
    1112          19 :                 if (exists >= 0)
    1113             :                 {
    1114          19 :                         configuration.get (exists, timespan_p);
    1115             : 
    1116          19 :                         if (!timespan_p.contains("scan") and !timespan_p.contains("state") and !timespan_p.contains("field"))
    1117             :                         {
    1118          19 :                                 timespan_p = String("");
    1119             :                         }
    1120             :                         else
    1121             :                         {
    1122           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1123           0 :                                                 << "Time span is " << timespan_p << LogIO::POST;
    1124             :                         }
    1125             :                 }
    1126             : 
    1127             :                 // CAS-4850 (jagonzal): For ALMA each bdf is limited to 30s, so we need to combine across state (i.e. su-scan)
    1128          19 :                 if (timeAverage_p && (timeBin_p > 30.0) and !timespan_p.contains("state"))
    1129             :                 {
    1130           0 :                         MeasurementSet tmpMs(inpMsName_p,Table::Old);
    1131           0 :                         MSObservation observationTable = tmpMs.observation();
    1132           0 :                         MSObservationColumns observationCols(observationTable);
    1133           0 :                         String telescopeName = observationCols.telescopeName()(0);
    1134             : 
    1135           0 :                         if (telescopeName.contains("ALMA"))
    1136             :                         {
    1137           0 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1138             :                                                 << "Operating with ALMA data, automatically adding state to timespan "<< endl
    1139           0 :                                                 << "In order to remove sub-scan boundaries which limit time average to 30s "<< LogIO::POST;
    1140           0 :                                 timespan_p += String(",state");
    1141             :                         }
    1142           0 :                 }
    1143             : 
    1144          19 :                 exists = -1;
    1145          19 :                 exists = configuration.fieldNumber ("maxuvwdistance");
    1146          19 :                 if (exists >= 0)
    1147             :                 {
    1148          19 :                         configuration.get (exists, maxuvwdistance_p);
    1149             : 
    1150          19 :                         if (maxuvwdistance_p > 0)
    1151             :                         {
    1152           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1153             :                                                 << "Maximum UV distance for baseline-dependent time average is: "
    1154           0 :                                                 << maxuvwdistance_p << " meters" << LogIO::POST;
    1155             :                         }
    1156             :                 }
    1157             : 
    1158             :                 /*
    1159             :                 exists = configuration.fieldNumber ("minbaselines");
    1160             :                 if (exists >= 0)
    1161             :                 {
    1162             :                         configuration.get (exists, minbaselines_p);
    1163             : 
    1164             :                         if (minbaselines_p > 0)
    1165             :                         {
    1166             :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1167             :                                                 << "Minimum number of baselines for time average: " << minbaselines_p << LogIO::POST;
    1168             :                         }
    1169             :                 }
    1170             :                 */
    1171             :         }
    1172             : 
    1173          35 :         return;
    1174             : }
    1175             : 
    1176             : // -----------------------------------------------------------------------
    1177             : // Parameter parser for on-the-fly (OTF) calibration
    1178             : // -----------------------------------------------------------------------
    1179          35 : void MSTransformManager::parseCalParams(Record &configuration)
    1180             : {
    1181          35 :         int exists = configuration.fieldNumber("callib");
    1182          35 :         if (exists >= 0)
    1183             :         {
    1184             : 
    1185           0 :                 if (configuration.type(exists) == TpRecord)
    1186             :                 {
    1187             :                         // Extract the callib Record
    1188           0 :                         callibRec_p = configuration.subRecord(exists);
    1189           0 :                         callib_p="";
    1190             : 
    1191             :                         // If the Record is non-trivial, calibration is turned on
    1192           0 :                         calibrate_p = callibRec_p.nfields() > 0;
    1193             :                 }
    1194           0 :                 else if (configuration.type(exists) == TpString)
    1195             :                 {
    1196             :                         // Extract the callib String
    1197           0 :                         callib_p = configuration.asString(exists);
    1198           0 :                         callibRec_p = Record();
    1199             : 
    1200             :                         // If the callib_p String has non-trivial content, calibration in turned on
    1201           0 :                         calibrate_p = callib_p.length() > 0;
    1202             : 
    1203             :                 }
    1204             : 
    1205           0 :                 if (calibrate_p)
    1206             :                 {
    1207           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    1208           0 :                                                 << "Calibration is activated" << LogIO::POST;
    1209             :                 }
    1210             : 
    1211             :         }
    1212             : 
    1213          35 :         return;
    1214             : }
    1215             : 
    1216             : // -----------------------------------------------------------------------
    1217             : // Parameter parser for continuum subtraction
    1218             : // -----------------------------------------------------------------------
    1219          35 : void MSTransformManager::parseUVContSubParams(Record &configuration)
    1220             : {
    1221          35 :     int exists = -1;
    1222             : 
    1223          35 :     exists = -1;
    1224          35 :     exists = configuration.fieldNumber("uvcontsub");
    1225          35 :     if (exists >= 0)
    1226             :     {
    1227           0 :         configuration.get (exists, uvcontsub_p);
    1228             : 
    1229           0 :         if (uvcontsub_p)
    1230             :         {
    1231             :             // Extract the callib Record
    1232           0 :             exists = -1;
    1233           0 :             exists = configuration.fieldNumber("uvcontsublib");
    1234           0 :             if (configuration.type(exists) == TpRecord)
    1235             :             {
    1236           0 :                 uvcontsubRec_p = configuration.subRecord(exists);
    1237             :             }
    1238             : 
    1239           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",
    1240             :                                                    __FUNCTION__)
    1241             :                      << "Continuum subtraction is activated "
    1242           0 :                      << LogIO::POST;
    1243             : 
    1244             :             // not nice going into the subRec, perhaps a writemodel var
    1245             :             // could be put in the top level record
    1246           0 :             int writemodel = uvcontsubRec_p.fieldNumber("writemodel");
    1247           0 :             if (writemodel >= 0) {
    1248           0 :                 bool dowrite = false;
    1249           0 :                 uvcontsubRec_p.get(writemodel, dowrite);
    1250           0 :                 if (dowrite) {
    1251           0 :                     produceModel_p = true;
    1252             :                 }
    1253             :             }
    1254             :         }
    1255             :     }
    1256          35 : }
    1257             : 
    1258             : // -----------------------------------------------------------------------
    1259             : // Method to set spw averaging
    1260             : // -----------------------------------------------------------------------
    1261          35 : void MSTransformManager::setSpwAvg(Record &configuration)
    1262             : {
    1263          35 :         int exists = -1;
    1264             : 
    1265          35 :         exists = -1;
    1266          35 :         exists = configuration.fieldNumber ("spwaverage");
    1267          35 :         if (exists >= 0)
    1268             :         {
    1269           0 :                 configuration.get (exists, spwAverage_p);
    1270             : 
    1271           0 :                 if (spwAverage_p)
    1272             :                 {
    1273           0 :                         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1274           0 :                                         << "Spw average is activated" << LogIO::POST;
    1275             :                 }
    1276             :         }
    1277          35 : }
    1278             : 
    1279             : // -----------------------------------------------------------------------
    1280             : // Parameter parser for polarization transformation
    1281             : // -----------------------------------------------------------------------
    1282          35 : void MSTransformManager::parsePolAvgParams(Record &configuration)
    1283             : {
    1284          35 :   String key("polaverage");
    1285          35 :   bool exists = configuration.isDefined(key);
    1286          35 :   if (exists) {
    1287           0 :     polAverage_p = configuration.asBool(key);
    1288             :   }
    1289             : 
    1290          35 :   key = "polaveragemode";
    1291          35 :   if (polAverage_p) {
    1292           0 :     if (configuration.isDefined(key)) {
    1293           0 :       polAverageConfig_p.define("mode", configuration.asString(key));
    1294             :     } else {
    1295           0 :       polAverageConfig_p.define("mode", "default");
    1296             :     }
    1297             :   }
    1298          35 : }
    1299             : 
    1300          35 : void MSTransformManager::parsePointingsInterpolationParams(casacore::Record &configuration){
    1301          35 :         String key("pointingsinterpolation");
    1302          35 :         bool exists = configuration.isDefined(key);
    1303          35 :         if (exists) {
    1304           0 :                 pointingsInterpolation_p = configuration.asBool(key);
    1305             :         }
    1306          35 : }
    1307             : 
    1308          35 : void MSTransformManager::parseAtmCorrectionParams(casacore::Record &configuration) {
    1309          35 :     String key("atmCor");
    1310          35 :     if (configuration.isDefined(key)) {
    1311           0 :         doAtmCor_p = configuration.asBool(key);
    1312           0 :         atmCorConfig_p = configuration;
    1313             :     } else {
    1314          35 :         doAtmCor_p = False;
    1315             :     }
    1316          35 : }
    1317             : 
    1318             : // -----------------------------------------------------------------------
    1319             : // Method to open the input MS, select the data and create the
    1320             : // structure of the output MS filling the auxiliary tables.
    1321             : // -----------------------------------------------------------------------
    1322          35 : void MSTransformManager::open()
    1323             : {
    1324             :         // Initialize MSTransformDataHandler to open the MeasurementSet object
    1325          35 :         if (interactive_p)
    1326             :         {
    1327             :                 // In buffer mode we may have to modify the flags
    1328           0 :                 dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Update);
    1329             :         }
    1330             :         else
    1331             :         {
    1332          35 :                 dataHandler_p = new MSTransformDataHandler(inpMsName_p,Table::Old);
    1333             :         }
    1334             : 
    1335             : 
    1336             :         // WARNING: Input MS is re-set at the end of a successful MSTransformDataHandler::makeMSBasicStructure,
    1337             :         // call therefore we have to use the selected MS always
    1338          35 :         inputMs_p = dataHandler_p->getInputMS();
    1339             :         // Note: We always get the input number of channels because we don't know if pre-averaging will be necessary
    1340          35 :         getInputNumberOfChannels();
    1341             : 
    1342             :         // Check available data cols to pass this information on to MSTransformDataHandler which creates the MS structure
    1343          35 :         checkDataColumnsAvailable();
    1344          35 :         checkDataColumnsToFill();
    1345             : 
    1346             : 
    1347             :         // Check whether the MS has correlator pre-averaging and we are smoothing or averaging
    1348          35 :         checkCorrelatorPreaveraging();
    1349             : 
    1350             :         // Set virtual column operation
    1351          35 :         dataHandler_p->setVirtualModelCol(makeVirtualModelColReal_p);
    1352          35 :         dataHandler_p->setVirtualCorrectedCol(makeVirtualCorrectedColReal_p);
    1353             : 
    1354             :         // Once the input MS is opened we can get the selection indexes,
    1355             :         // in this way we also validate the selection parameters
    1356          35 :         dataHandler_p->setReindex(reindex_p);
    1357          35 :         initDataSelectionParams();
    1358             : 
    1359             :         // Once the selection parameters have been processed, check consistency in
    1360             :         // number of channels, if needed.
    1361          35 :         checkSPWChannelsKnownLimitation();
    1362             : 
    1363             :         // Determine channel specification for output MS
    1364          35 :         Vector<Int> chanSpec;
    1365          35 :         bool spectralRegridding = combinespws_p or regridding_p;
    1366          35 :         if (channelAverage_p and !spectralRegridding)
    1367             :         {
    1368          17 :                 chanSpec =  freqbin_p;
    1369             :         }
    1370             :         else
    1371             :         {
    1372          18 :                 chanSpec = Vector<Int>(1,1);
    1373             :         }
    1374             : 
    1375             :         // Set-up splitter object
    1376          35 :         const String dummyExpr = String("");
    1377          35 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << "Select data" << LogIO::POST;
    1378          35 :         dataHandler_p->setmsselect((const String)spwSelection_p,
    1379          70 :                                                         (const String)fieldSelection_p,
    1380          70 :                                                         (const String)baselineSelection_p,
    1381          70 :                                                         (const String)scanSelection_p,
    1382          70 :                                                         (const String)uvwSelection_p,
    1383          70 :                                                         (const String)taqlSelection_p,
    1384             :                                                         chanSpec,
    1385          70 :                                                         (const String)arraySelection_p,
    1386          70 :                                                         (const String)polarizationSelection_p,
    1387          70 :                                                         (const String)scanIntentSelection_p,
    1388          70 :                                                         (const String)observationSelection_p,
    1389          70 :                                                         (const String)feedSelection_p);
    1390             : 
    1391          35 :         dataHandler_p->selectTime(timeBin_p,timeSelection_p);
    1392             : 
    1393          35 :         createOutputMSStructure();
    1394             : 
    1395             :         // jagonzal (CAS-5076): Reindex state column when there is scan selection
    1396             :         // jagonzal (CAS-6351): Removing this fix as only implicit selection-based re-indexing has to be applied
    1397             :         /*
    1398             :         map<Int, Int> stateRemapper = dataHandler_p->getStateRemapper();
    1399             :     std::map<Int, Int>::iterator stateRemapperIter;
    1400             :     for (       stateRemapperIter = stateRemapper.begin();
    1401             :                 stateRemapperIter != stateRemapper.end();
    1402             :                 stateRemapperIter++)
    1403             :     {
    1404             :         inputOutputScanIntentIndexMap_p[stateRemapperIter->first] = stateRemapperIter->second;
    1405             : 
    1406             :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1407             :                         << "State " << stateRemapperIter->first << " mapped to " << stateRemapperIter->second << LogIO::POST;
    1408             :     }
    1409             :     */
    1410             : 
    1411             :     // jagonzal (CAS-5349): Reindex antenna columns when there is antenna selection
    1412          35 :     if (!baselineSelection_p.empty() and reindex_p)
    1413             :     {
    1414           1 :         Vector<Int> antennaRemapper = dataHandler_p->getAntennaRemapper();
    1415           4 :         for (uInt oldIndex=0;oldIndex<antennaRemapper.size();oldIndex++)
    1416             :         {
    1417           3 :                 inputOutputAntennaIndexMap_p[oldIndex] = antennaRemapper[oldIndex];
    1418             :         }
    1419           1 :     }
    1420             : 
    1421             : 
    1422          35 :         selectedInputMs_p = dataHandler_p->getSelectedInputMS();
    1423          35 :         outputMs_p = dataHandler_p->getOutputMS();
    1424          35 :         selectedInputMsCols_p = dataHandler_p->getSelectedInputMSColumns();
    1425          35 :         outputMsCols_p = dataHandler_p->getOutputMSColumns();
    1426             : 
    1427          70 :         return;
    1428          35 : }
    1429             : 
    1430             : /**
    1431             :  * Whether the WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
    1432             :  * This should be honored when creating the output MS structure (in
    1433             :  * createOutputMSStructure().
    1434             :  *
    1435             :  * The logic to say true is: if the WEIGHT/SIGMA_SPECTRUM are present in the input MS or
    1436             :  * the user has requested the creation of these columns in the output MS anyway via the
    1437             :  * parameter 'usewtspectrum'
    1438             :  * This requires that the input configuration be parsed here in MSTransformManager before
    1439             :  * calling this method, and passed as parameter.
    1440             :  *
    1441             :  * @param usewtspectrum value of the usewtspectrum input parameter of mstransform
    1442             :  *
    1443             :  * @return whether WEIGHT/SIGMA_SPECTRUM columns should be created in the output MS.
    1444             :  */
    1445          35 : bool MSTransformManager::shouldCreateOutputWtSpectrum(bool usewtspectrum)
    1446             : {
    1447          35 :     if (nullptr == inputMs_p) {
    1448           0 :         throw AipsError("When trying to guess if WEIGHT/SIGMA_SPECTRUM should be created "
    1449           0 :                         "in the output MS: the input MS has not been initialized.");
    1450             :     }
    1451             : 
    1452          35 :     auto wtSpec = MSColumns(*inputMs_p).weightSpectrum();
    1453          35 :     auto inputWeightSpectrumAvailable = !wtSpec.isNull() and wtSpec.isDefined(0);
    1454          70 :     return inputWeightSpectrumAvailable or usewtspectrum;
    1455          35 : }
    1456             : 
    1457             : /**
    1458             :  * Helper method for open() to create the structure of the output MS
    1459             :  * and check errors.
    1460             :  *
    1461             :  * @throws AipsError in case of errors creating the output MS
    1462             :  */
    1463          35 : void MSTransformManager::createOutputMSStructure()
    1464             : {
    1465             :         // Create output MS structure
    1466          35 :         if (not bufferMode_p)
    1467             :         {
    1468          70 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1469          70 :                                 << "Create output MS structure" << LogIO::POST;
    1470             :         }
    1471             :         else
    1472             :         {
    1473           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1474           0 :                                 << "Create transformed MS Subtables to be stored in memory" << LogIO::POST;
    1475             :         }
    1476             : 
    1477             : 
    1478             :         //jagonzal (CAS-5174)
    1479          35 :         bool outputMSStructureCreated = false;
    1480             :         try
    1481             :         {
    1482          35 :             Table::TableOption option = Table::New;
    1483          35 :             if (bufferMode_p) {
    1484           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    1485           0 :                          << "Create output MS structure" << LogIO::POST;
    1486           0 :                 option = Table::Scratch;
    1487             :             }
    1488             : 
    1489          35 :             auto createWeightSpectrum = shouldCreateOutputWtSpectrum(usewtspectrum_p);
    1490          70 :             outputMSStructureCreated = dataHandler_p->makeMSBasicStructure(outMsName_p,
    1491          35 :                                                                            datacolumn_p,
    1492          35 :                                                                            produceModel_p,
    1493             :                                                                            createWeightSpectrum,
    1494          35 :                                                                            tileShape_p,
    1495          35 :                                                                            timespan_p,
    1496             :                                                                            option);
    1497             :         }
    1498           0 :         catch (const AipsError &ex)
    1499             :         {
    1500           0 :                 outputMSStructureCreated = false;
    1501           0 :                 logger_p        << LogIO::DEBUG1
    1502             :                                         << "Exception creating output MS structure: " << ex.getMesg() << endl
    1503           0 :                                         << LogIO::POST;
    1504             : 
    1505           0 :                 throw AipsError(ex.getMesg());
    1506           0 :         }
    1507             : 
    1508             : 
    1509             : 
    1510          35 :         if (!outputMSStructureCreated)
    1511             :         {
    1512           0 :                 throw AipsError("Error creating output MS structure");
    1513             :         }
    1514          35 : }
    1515             : 
    1516             : // -----------------------------------------------------------------------
    1517             : // Method to close the output MS
    1518             : // -----------------------------------------------------------------------
    1519          70 : void MSTransformManager::close()
    1520             : {
    1521          70 :         if (outputMs_p)
    1522             :         {
    1523             :                 // unlock MS (the MS data handler will flush it when destroying it).
    1524          35 :                 outputMs_p->unlock();
    1525          35 :                 Table::relinquishAutoLocks(true);
    1526             : 
    1527             :                 // Unset the output MS
    1528          35 :                 outputMs_p = NULL;
    1529             :         }
    1530             : 
    1531          70 :         return;
    1532             : }
    1533             : 
    1534             : // -----------------------------------------------------------------------
    1535             : // Check configuration and input MS characteristics to determine run parameters
    1536             : // -----------------------------------------------------------------------
    1537          35 : void MSTransformManager::setup()
    1538             : {
    1539             :         // Check what columns have to filled
    1540             :         // CAS-5581 (jagonzal): Moving these methods here because we need to know if
    1541             :         // WEIGHT_SPECTRUM is available to configure the appropriate averaging kernel.
    1542             :         // - note also that the availability of WEIGHT_SPECTRUM in the input MS needs
    1543             :         // to be checked even before, as it is needed when doing
    1544             :         // dataHandler_p->makeMSBasicStructure() in createOutputMSStructure() - CAS-11269
    1545          35 :         checkFillFlagCategory();
    1546          35 :         checkFillWeightSpectrum();
    1547             : 
    1548             :         // Check if we really need to combine SPWs
    1549          35 :         if (combinespws_p)
    1550             :         {
    1551           0 :                 auto nInputSpws = outputMs_p->spectralWindow().nrow();
    1552           0 :                 if (nInputSpws < 2)
    1553             :                 {
    1554           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    1555           0 :                                         << "There is only one selected SPW, no need to combine " << LogIO::POST;
    1556           0 :                         combinespws_p = false;
    1557             :                 }
    1558             :         }
    1559             : 
    1560             :         // Regrid SPW subtable
    1561          35 :         if (combinespws_p)
    1562             :         {
    1563           0 :                 initRefFrameTransParams();
    1564           0 :                 regridAndCombineSpwSubtable();
    1565           0 :                 reindexDDISubTable();
    1566           0 :                 reindexSourceSubTable();
    1567             :                 //reindexFeedSubTable();
    1568             :                 //reindexSysCalSubTable();
    1569           0 :                 reindexFreqOffsetSubTable();
    1570           0 :                 reindexGenericTimeDependentSubTable("FEED");
    1571           0 :                 reindexGenericTimeDependentSubTable("SYSCAL");
    1572           0 :                 reindexGenericTimeDependentSubTable("CALDEVICE");
    1573           0 :                 reindexGenericTimeDependentSubTable("SYSPOWER");
    1574             :         }
    1575          35 :         else if (regridding_p)  // regrid as in the regridms option
    1576             :         {
    1577           0 :                 initRefFrameTransParams();
    1578           0 :                 regridSpwSubTable();
    1579             :         }
    1580             : 
    1581             :         // Subtable manipulation for polarization averaging
    1582          35 :         if (polAverage_p) {
    1583             : //        Int nInputPolarizations = outputMs_p->polarization().nrow();
    1584           0 :           Int averagedPolId = getAveragedPolarizationId();
    1585           0 :           reindexPolarizationIdInDataDesc(averagedPolId);
    1586             :         }
    1587             : 
    1588             :         //// Determine the frequency transformation methods to use ////
    1589             : 
    1590             : 
    1591             :         // Cube level
    1592          35 :         if (combinespws_p)
    1593             :         {
    1594           0 :                 transformCubeOfDataComplex_p = &MSTransformManager::combineCubeOfData;
    1595           0 :                 transformCubeOfDataFloat_p = &MSTransformManager::combineCubeOfData;
    1596           0 :                 spectrumTransformation_p = true;
    1597           0 :                 propagateWeights_p = true;
    1598           0 :                 spectrumReshape_p = true;
    1599           0 :                 cubeTransformation_p = true;
    1600             :         }
    1601          35 :         else if (regridding_p)
    1602             :         {
    1603           0 :                 transformCubeOfDataComplex_p = &MSTransformManager::regridCubeOfData;
    1604           0 :                 transformCubeOfDataFloat_p = &MSTransformManager::regridCubeOfData;
    1605           0 :                 spectrumTransformation_p = true;
    1606           0 :                 propagateWeights_p = true;
    1607           0 :                 spectrumReshape_p = true;
    1608           0 :                 cubeTransformation_p = true;
    1609             :         }
    1610          35 :         else if (channelAverage_p)
    1611             :         {
    1612          17 :                 transformCubeOfDataComplex_p = &MSTransformManager::averageCubeOfData;
    1613          17 :                 transformCubeOfDataFloat_p = &MSTransformManager::averageCubeOfData;
    1614          17 :                 spectrumTransformation_p = true;
    1615          17 :                 propagateWeights_p = true;
    1616          17 :                 spectrumReshape_p = true;
    1617          17 :                 cubeTransformation_p = true;
    1618             :         }
    1619          18 :         else if (hanningSmooth_p || smoothFourier_p)
    1620             :         {
    1621           0 :                 transformCubeOfDataComplex_p = &MSTransformManager::smoothCubeOfData;
    1622           0 :                 transformCubeOfDataFloat_p = &MSTransformManager::smoothCubeOfData;
    1623           0 :                 spectrumTransformation_p = true;
    1624           0 :                 cubeTransformation_p = true;
    1625             :         }
    1626          18 :         else if (nspws_p > 1)
    1627             :         {
    1628           0 :                 transformCubeOfDataComplex_p = &MSTransformManager::separateCubeOfData;
    1629           0 :                 transformCubeOfDataFloat_p = &MSTransformManager::separateCubeOfData;
    1630           0 :                 spectrumReshape_p = true;
    1631           0 :                 cubeTransformation_p = true;
    1632             :         }
    1633             :         else
    1634             :         {
    1635          18 :                 transformCubeOfDataComplex_p = &MSTransformManager::copyCubeOfData;
    1636          18 :                 transformCubeOfDataFloat_p = &MSTransformManager::copyCubeOfData;
    1637             :         }
    1638             : 
    1639          35 :         bool spectralRegridding = combinespws_p or regridding_p;
    1640             : 
    1641             :         // Vector level
    1642          35 :         if (channelAverage_p and !hanningSmooth_p and !spectralRegridding)
    1643             :         {
    1644          17 :                 transformStripeOfDataComplex_p = &MSTransformManager::average;
    1645          17 :                 transformStripeOfDataFloat_p = &MSTransformManager::average;
    1646             :         }
    1647          18 :         else if (!channelAverage_p and hanningSmooth_p and !spectralRegridding)
    1648             :         {
    1649           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::smooth;
    1650           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::smooth;
    1651             :         }
    1652          18 :         else if (!channelAverage_p and !hanningSmooth_p and spectralRegridding)
    1653             :         {
    1654           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::regrid;
    1655           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::regrid;
    1656             :         }
    1657          18 :         else if (channelAverage_p and hanningSmooth_p and !spectralRegridding)
    1658             :         {
    1659           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageSmooth;
    1660           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageSmooth;
    1661             :         }
    1662          18 :         else if (channelAverage_p and !hanningSmooth_p and spectralRegridding)
    1663             :         {
    1664           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageRegrid;
    1665           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageRegrid;
    1666             :         }
    1667          18 :         else if (!channelAverage_p and hanningSmooth_p and spectralRegridding)
    1668             :         {
    1669           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::smoothRegrid;
    1670           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::smoothRegrid;
    1671             :         }
    1672          18 :         else if (channelAverage_p and hanningSmooth_p and spectralRegridding)
    1673             :         {
    1674           0 :                 transformStripeOfDataComplex_p = &MSTransformManager::averageSmoothRegrid;
    1675           0 :                 transformStripeOfDataFloat_p = &MSTransformManager::averageSmoothRegrid;
    1676             :         }
    1677          18 :         else if (smoothFourier_p) {
    1678           0 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    1679           0 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    1680             :         }
    1681             : 
    1682             :         // If there is not inputWeightSpectrumAvailable_p and no time average then
    1683             :         // weightSpectrum is constant and has no effect in frequency avg./regridding
    1684          35 :         if ((not inputWeightSpectrumAvailable_p) and (not timeAverage_p))
    1685             :         {
    1686          16 :                 propagateWeights_p = false;
    1687          16 :                 weightmode_p = MSTransformations::flagsNonZero;
    1688             :         }
    1689             :         else
    1690             :         {
    1691             :                 // NOTE: It does not hurt to set the averaging kernel even if we are not going to use it
    1692          19 :                 weightmode_p = MSTransformations::flagSpectrumNonZero;
    1693             :         }
    1694             : 
    1695             :         // SPECTRUM columns have to be set when they exists in the input or the user specifies it via usewtspectrum_p
    1696          35 :         if (inputWeightSpectrumAvailable_p or usewtspectrum_p)
    1697             :         {
    1698           1 :                 flushWeightSpectrum_p = true;
    1699             :         }
    1700             :         else
    1701             :         {
    1702          34 :                 flushWeightSpectrum_p = false;
    1703             :         }
    1704             : 
    1705          35 :         propagateWeights(propagateWeights_p);
    1706          35 :         setChannelAverageKernel(weightmode_p);
    1707          35 :         setSmoothingKernel(smoothmode_p);
    1708             : 
    1709             : 
    1710             :         // Set Regridding kernel
    1711          35 :         if (fftShiftEnabled_p)
    1712             :         {
    1713           0 :                 regridCoreComplex_p = &MSTransformManager::interpol1Dfftshift;
    1714           0 :                 regridCoreFloat_p = &MSTransformManager::interpol1Dfftshift;
    1715             :         }
    1716             :         else
    1717             :         {
    1718          35 :                 regridCoreComplex_p = &MSTransformManager::interpol1D;
    1719          35 :                 regridCoreFloat_p = &MSTransformManager::interpol1D;
    1720             :         }
    1721             : 
    1722             :         //// Determine the frequency transformation methods to use ////
    1723             : 
    1724             :         // Drop channels with non-uniform width when doing only channel average
    1725          35 :         if (channelAverage_p and !regridding_p and !combinespws_p )
    1726             :         {
    1727          17 :                 dropNonUniformWidthChannels();
    1728             :         }
    1729             : 
    1730             :         // Get number of output channels (needed by chan avg and separate SPWs when there is only 1 selected SPW)
    1731          35 :         if (channelAverage_p or (nspws_p>1 and !combinespws_p))
    1732             :         {
    1733          17 :                 getOutputNumberOfChannels();
    1734             :         }
    1735             : 
    1736             :         // Determine weight and sigma factors when either auto or user channel average is set
    1737          35 :         if (channelAverage_p or combinespws_p or regridding_p)
    1738             :         {
    1739          17 :                 calculateNewWeightAndSigmaFactors();
    1740             :         }
    1741             : 
    1742             : 
    1743          35 :         if (nspws_p > 1)
    1744             :         {
    1745           0 :                 uInt totalNumberOfOutputChannels = 0;
    1746           0 :                 if (combinespws_p)
    1747             :                 {
    1748           0 :                         totalNumberOfOutputChannels = inputOutputSpwMap_p[0].second.NUM_CHAN;
    1749             :                 }
    1750             :                 // jagonzal: This is the case when there is only one input SPW and there is no need to combine
    1751             :                 else
    1752             :                 {
    1753           0 :                         uInt spwId = 0;
    1754           0 :                 if (outputInputSPWIndexMap_p.size()>0)
    1755             :                 {
    1756           0 :                         spwId = outputInputSPWIndexMap_p[0];
    1757             :                 }
    1758             :                 else
    1759             :                 {
    1760           0 :                         spwId = 0;
    1761             :                 }
    1762             : 
    1763           0 :                 totalNumberOfOutputChannels = numOfOutChanMap_p[spwId];
    1764             :                 }
    1765             : 
    1766             : 
    1767           0 :                 chansPerOutputSpw_p = totalNumberOfOutputChannels / nspws_p;
    1768           0 :                 if (totalNumberOfOutputChannels % nspws_p)
    1769             :                 {
    1770           0 :                         chansPerOutputSpw_p += 1;
    1771           0 :                         tailOfChansforLastSpw_p = totalNumberOfOutputChannels - chansPerOutputSpw_p*(nspws_p-1);
    1772             :                 }
    1773             :                 else
    1774             :                 {
    1775           0 :                         tailOfChansforLastSpw_p = chansPerOutputSpw_p;
    1776             :                 }
    1777             : 
    1778           0 :                 if (bufferMode_p)
    1779             :                 {
    1780           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1781           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1782             :                 }
    1783             :                 else
    1784             :                 {
    1785           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
    1786           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
    1787             :                 }
    1788             : 
    1789           0 :                 separateSpwSubtable();
    1790           0 :                 separateFeedSubtable();
    1791           0 :                 separateSourceSubtable();
    1792           0 :                 separateSyscalSubtable();
    1793           0 :                 separateFreqOffsetSubtable();
    1794           0 :                 separateCalDeviceSubtable();
    1795           0 :                 separateSysPowerSubtable();
    1796             : 
    1797             :                 // CAS-5404. DDI sub-table has to be re-indexed after separating SPW sub-table
    1798           0 :                 if (not combinespws_p) reindexDDISubTable();
    1799             :         }
    1800             :         else
    1801             :         {
    1802          35 :                 if (bufferMode_p)
    1803             :                 {
    1804           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
    1805           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
    1806             :                 }
    1807             :                 else
    1808             :                 {
    1809          35 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
    1810          35 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
    1811             :                 }
    1812             :         }
    1813             : 
    1814             :         // Generate Iterator
    1815          35 :         setIterationApproach();
    1816          35 :         generateIterator();
    1817             : 
    1818          35 :         return;
    1819             : }
    1820             : 
    1821             : 
    1822             : // -----------------------------------------------------------------------
    1823             : //
    1824             : // -----------------------------------------------------------------------
    1825        5942 : IPosition MSTransformManager::getShape()
    1826             : {
    1827        5942 :         return getTransformedShape(visibilityIterator_p->getVisBuffer());
    1828             : }
    1829             : 
    1830             : // -----------------------------------------------------------------------
    1831             : //
    1832             : // -----------------------------------------------------------------------
    1833        5942 : IPosition MSTransformManager::getTransformedShape(vi::VisBuffer2 *visBuffer)
    1834             : {
    1835        5942 :         IPosition outputCubeShape(3);
    1836             : 
    1837             :         // Correlations
    1838        5942 :         outputCubeShape(0) = visBuffer->nCorrelations();
    1839             : 
    1840             :         // Rows
    1841        5942 :         outputCubeShape(2) = nRowsToAdd_p;
    1842             : 
    1843             :         // Channels
    1844        5942 :         if (nspws_p > 1)
    1845             :         {
    1846           0 :                 outputCubeShape(1) = chansPerOutputSpw_p;
    1847             :         }
    1848        5942 :         else if (combinespws_p)
    1849             :         {
    1850           0 :                 outputCubeShape(1) = inputOutputSpwMap_p[0].second.NUM_CHAN;
    1851             :         }
    1852        5942 :         else if (regridding_p)
    1853             :         {
    1854           0 :                 Int inputSpw = visBuffer->spectralWindows()(0);
    1855           0 :                 outputCubeShape(1) = inputOutputSpwMap_p[inputSpw].second.NUM_CHAN;
    1856             :         }
    1857        5942 :         else if (channelAverage_p)
    1858             :         {
    1859        3430 :                 Int inputSpw = visBuffer->spectralWindows()(0);
    1860        3430 :                 outputCubeShape(1) = numOfOutChanMap_p[inputSpw];
    1861             :         }
    1862             :         else
    1863             :         {
    1864        2512 :                 outputCubeShape(1) = visBuffer->nChannels();
    1865             :         }
    1866             : 
    1867        5942 :         return outputCubeShape;
    1868           0 : }
    1869             : 
    1870             : // -----------------------------------------------------------------------
    1871             : //
    1872             : // -----------------------------------------------------------------------
    1873        1217 : void MSTransformManager::propagateWeights(bool on)
    1874             : {
    1875             : 
    1876        1217 :         if (on)
    1877             :         {
    1878             :                 // Used by SPW combination
    1879          18 :                 fillWeightsPlane_p = &MSTransformManager::fillWeightsPlane;
    1880          18 :                 normalizeWeightsPlane_p = &MSTransformManager::normalizeWeightsPlane;
    1881             : 
    1882             :                 // Used by channel average
    1883          18 :                 setWeightsPlaneByReference_p = &MSTransformManager::setWeightsPlaneByReference;
    1884          18 :                 setWeightStripeByReference_p = &MSTransformManager::setWeightStripeByReference;
    1885             :         }
    1886             :         else
    1887             :         {
    1888             :                 // Used by SPW combination
    1889        1199 :                 fillWeightsPlane_p = &MSTransformManager::dontfillWeightsPlane;
    1890        1199 :                 normalizeWeightsPlane_p = &MSTransformManager::dontNormalizeWeightsPlane;
    1891             : 
    1892             :                 // Used by channel average
    1893        1199 :                 setWeightsPlaneByReference_p = &MSTransformManager::dontsetWeightsPlaneByReference;
    1894        1199 :                 setWeightStripeByReference_p = &MSTransformManager::dontSetWeightStripeByReference;
    1895             :         }
    1896             : 
    1897        1217 :         return;
    1898             : }
    1899             : 
    1900             : // -----------------------------------------------------------------------
    1901             : //
    1902             : // -----------------------------------------------------------------------
    1903        1178 : void MSTransformManager::setBufferMode(bool on)
    1904             : {
    1905        1178 :         bufferMode_p = on;
    1906             : 
    1907        1178 :         if (nspws_p > 1)
    1908             :         {
    1909           0 :                 if (bufferMode_p)
    1910             :                 {
    1911           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1912           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanesInSlices;
    1913             :                 }
    1914             :                 else
    1915             :                 {
    1916           0 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInSlices;
    1917           0 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInSlices;
    1918             :                 }
    1919             :         }
    1920             :         else
    1921             :         {
    1922        1178 :                 if (bufferMode_p)
    1923             :                 {
    1924         589 :                         writeOutputPlanesComplex_p = &MSTransformManager::bufferOutputPlanes;
    1925         589 :                         writeOutputPlanesFloat_p = &MSTransformManager::bufferOutputPlanes;
    1926             :                 }
    1927             :                 else
    1928             :                 {
    1929         589 :                         writeOutputPlanesComplex_p = &MSTransformManager::writeOutputPlanesInBlock;
    1930         589 :                         writeOutputPlanesFloat_p = &MSTransformManager::writeOutputPlanesInBlock;
    1931             :                 }
    1932             :         }
    1933             : 
    1934        1178 :         return;
    1935             : }
    1936             : 
    1937             : // -----------------------------------------------------------------------
    1938             : //
    1939             : // -----------------------------------------------------------------------
    1940        1217 : void MSTransformManager::setChannelAverageKernel(uInt mode)
    1941             : {
    1942        1217 :         switch (mode)
    1943             :         {
    1944           0 :                 case MSTransformations::spectrum:
    1945             :                 {
    1946           0 :                         averageKernelComplex_p = &MSTransformManager::weightAverageKernel;
    1947           0 :                         averageKernelFloat_p = &MSTransformManager::weightAverageKernel;
    1948           0 :                         break;
    1949             :                 }
    1950           0 :                 case MSTransformations::flags:
    1951             :                 {
    1952           0 :                         averageKernelComplex_p = &MSTransformManager::flagAverageKernel;
    1953           0 :                         averageKernelFloat_p = &MSTransformManager::flagAverageKernel;
    1954           0 :                         break;
    1955             :                 }
    1956           0 :                 case MSTransformations::cumSum:
    1957             :                 {
    1958           0 :                         averageKernelComplex_p = &MSTransformManager::cumSumKernel;
    1959           0 :                         averageKernelFloat_p = &MSTransformManager::cumSumKernel;
    1960           0 :                         break;
    1961             :                 }
    1962           0 :                 case MSTransformations::flagSpectrum:
    1963             :                 {
    1964           0 :                         averageKernelComplex_p = &MSTransformManager::flagWeightAverageKernel;
    1965           0 :                         averageKernelFloat_p = &MSTransformManager::flagWeightAverageKernel;
    1966           0 :                         break;
    1967             :                 }
    1968           0 :                 case MSTransformations::flagCumSum:
    1969             :                 {
    1970           0 :                         averageKernelComplex_p = &MSTransformManager::flagCumSumKernel;
    1971           0 :                         averageKernelFloat_p = &MSTransformManager::flagCumSumKernel;
    1972           0 :                         break;
    1973             :                 }
    1974         595 :                 case MSTransformations::flagsNonZero:
    1975             :                 {
    1976         595 :                         averageKernelComplex_p = &MSTransformManager::flagNonZeroAverageKernel;
    1977         595 :                         averageKernelFloat_p = &MSTransformManager::flagNonZeroAverageKernel;
    1978         595 :                         break;
    1979             :                 }
    1980          31 :                 case MSTransformations::flagSpectrumNonZero:
    1981             :                 {
    1982          31 :                         averageKernelComplex_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
    1983          31 :                         averageKernelFloat_p = &MSTransformManager::flagWeightNonZeroAverageKernel;
    1984          31 :                         break;
    1985             :                 }
    1986         591 :                 case MSTransformations::flagCumSumNonZero:
    1987             :                 {
    1988         591 :                         averageKernelComplex_p = &MSTransformManager::flagCumSumNonZeroKernel;
    1989         591 :                         averageKernelFloat_p = &MSTransformManager::flagCumSumNonZeroKernel;
    1990         591 :                         break;
    1991             :                 }
    1992           0 :                 default:
    1993             :                 {
    1994           0 :                         averageKernelComplex_p = &MSTransformManager::simpleAverageKernel;
    1995           0 :                         averageKernelFloat_p = &MSTransformManager::simpleAverageKernel;
    1996           0 :                         break;
    1997             :                 }
    1998             :         }
    1999             : 
    2000        1217 :         return;
    2001             : }
    2002             : 
    2003             : // -----------------------------------------------------------------------
    2004             : //
    2005             : // -----------------------------------------------------------------------
    2006        1217 : void MSTransformManager::setSmoothingKernel(uInt mode)
    2007             : {
    2008        1217 :         switch (mode)
    2009             :         {
    2010         626 :                 case MSTransformations::plainSmooth:
    2011             :                 {
    2012         626 :                         smoothKernelComplex_p = &MSTransformManager::plainSmooth;
    2013         626 :                         smoothKernelFloat_p = &MSTransformManager::plainSmooth;
    2014         626 :                         break;
    2015             :                 }
    2016         591 :                 case MSTransformations::plainSmoothSpectrum:
    2017             :                 {
    2018         591 :                         smoothKernelComplex_p = &MSTransformManager::plainSmoothSpectrum;
    2019         591 :                         smoothKernelFloat_p = &MSTransformManager::plainSmoothSpectrum;
    2020         591 :                         break;
    2021             :                 }
    2022           0 :                 default:
    2023             :                 {
    2024           0 :                         smoothKernelComplex_p = &MSTransformManager::plainSmooth;
    2025           0 :                         smoothKernelFloat_p = &MSTransformManager::plainSmooth;
    2026           0 :                         break;
    2027             :                 }
    2028             :         }
    2029             : 
    2030        1217 :         return;
    2031             : }
    2032             : 
    2033             : // -----------------------------------------------------------------------
    2034             : //
    2035             : // -----------------------------------------------------------------------
    2036        1182 : void MSTransformManager::setSmoothingFourierKernel(uInt mode)
    2037             : {
    2038        1182 :   if (smoothFourier_p) {
    2039           0 :     switch (mode)
    2040             :     {
    2041           0 :       case MSTransformations::plainSmooth:
    2042             :       {
    2043             :         //logger_p << "Set smoothing kernel to smoothFourier" << LogIO::POST;
    2044           0 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    2045           0 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    2046           0 :         break;
    2047             :       }
    2048           0 :       case MSTransformations::plainSmoothSpectrum:
    2049             :       {
    2050             :         //logger_p << "Set smoothing kernel to smooth (for weight propagation)" << LogIO::POST;
    2051           0 :         transformStripeOfDataComplex_p = &MSTransformManager::smooth;
    2052           0 :         transformStripeOfDataFloat_p = &MSTransformManager::smooth;
    2053           0 :         break;
    2054             :       }
    2055           0 :       default:
    2056             :       {
    2057           0 :         transformStripeOfDataComplex_p = &MSTransformManager::smoothFourierComplex;
    2058           0 :         transformStripeOfDataFloat_p = &MSTransformManager::smoothFourierFloat;
    2059           0 :         break;
    2060             :       }
    2061             :     }
    2062             :   }
    2063             : 
    2064        1182 :   return;
    2065             : }
    2066             : 
    2067             : // -----------------------------------------------------------------------
    2068             : //
    2069             : // -----------------------------------------------------------------------
    2070          35 : void MSTransformManager::initDataSelectionParams()
    2071             : {
    2072          35 :     MSSelection mssel;
    2073             : 
    2074          35 :     if (reindex_p)
    2075             :     {
    2076          35 :         if (!observationSelection_p.empty())
    2077             :         {
    2078           0 :             mssel.setObservationExpr(observationSelection_p);
    2079           0 :             Vector<Int> observationList = mssel.getObservationList(inputMs_p);
    2080           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2081           0 :                                                 << "Selected Observations Ids are " << observationList << LogIO::POST;
    2082             : 
    2083           0 :             for (uInt index=0; index < observationList.size(); index++)
    2084             :             {
    2085           0 :                 inputOutputObservationIndexMap_p[observationList(index)] = index;
    2086             :             }
    2087           0 :         }
    2088             : 
    2089          35 :         if (!arraySelection_p.empty())
    2090             :         {
    2091           0 :             mssel.setArrayExpr(arraySelection_p);
    2092           0 :             Vector<Int> arrayList = mssel.getSubArrayList(inputMs_p);
    2093           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2094           0 :                                                 << "Selected Arrays Ids are " << arrayList << LogIO::POST;
    2095             : 
    2096           0 :             for (uInt index=0; index < arrayList.size(); index++)
    2097             :             {
    2098           0 :                 inputOutputArrayIndexMap_p[arrayList(index)] = index;
    2099             :             }
    2100           0 :         }
    2101             : 
    2102          35 :         if (!scanSelection_p.empty())
    2103             :         {
    2104           1 :             mssel.setScanExpr(scanSelection_p);
    2105           1 :             Vector<Int> scanList = mssel.getScanList(inputMs_p);
    2106           2 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2107           2 :                                                 << "Selected Scans Ids are " << scanList << LogIO::POST;
    2108             : 
    2109           2 :             for (uInt index=0; index < scanList.size(); index++)
    2110             :             {
    2111           1 :                 inputOutputScanIndexMap_p[scanList(index)] = index;
    2112             :             }
    2113           1 :         }
    2114             : 
    2115          35 :         if (!scanIntentSelection_p.empty())
    2116             :         {
    2117           0 :             mssel.setStateExpr(scanIntentSelection_p);
    2118           0 :             Vector<Int> scanIntentList = mssel.getStateObsModeList(inputMs_p);
    2119           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2120           0 :                                                 << "Selected Scans Intents Ids are " << scanIntentList << LogIO::POST;
    2121             : 
    2122           0 :             for (uInt index=0; index < scanIntentList.size(); index++)
    2123             :             {
    2124           0 :                 inputOutputScanIntentIndexMap_p[scanIntentList(index)] = index;
    2125             :             }
    2126           0 :         }
    2127             : 
    2128          35 :         if (!fieldSelection_p.empty())
    2129             :         {
    2130           0 :             mssel.setFieldExpr(fieldSelection_p);
    2131           0 :             Vector<Int> fieldList = mssel.getFieldList(inputMs_p);
    2132           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2133           0 :                                                 << "Selected Fields Ids are " << fieldList << LogIO::POST;
    2134             : 
    2135           0 :             for (uInt index=0; index < fieldList.size(); index++)
    2136             :             {
    2137           0 :                 inputOutputFieldIndexMap_p[fieldList(index)] = index;
    2138             :             }
    2139           0 :         }
    2140             :     }
    2141             : 
    2142             : 
    2143          35 :     if (!spwSelection_p.empty())
    2144             :     {
    2145           3 :         mssel.setSpwExpr(spwSelection_p);
    2146           3 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2147             : 
    2148             :         // Get the DD IDs of this spw selection
    2149           3 :         Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
    2150             : 
    2151             :         // Take into account the polarization selections
    2152           3 :         if (!polarizationSelection_p.empty()){
    2153           0 :             mssel.setPolnExpr(polarizationSelection_p.c_str());
    2154           0 :             Vector<Int> polddi = mssel.getDDIDList(inputMs_p);
    2155           0 :             if (polddi.size() > 0){
    2156             :                 // make an intersection
    2157           0 :                 Vector<Int> commonDDI = set_intersection(spwddi, polddi);
    2158           0 :                 uInt nddids = commonDDI.size();
    2159           0 :                 if (nddids > 0){
    2160           0 :                     spwddi.resize(nddids);
    2161           0 :                     for (uInt ii = 0; ii < nddids; ++ii){
    2162           0 :                         spwddi[ii] = commonDDI[ii];
    2163             :                     }
    2164             :                 }
    2165           0 :             }
    2166           0 :         }
    2167             : 
    2168           3 :         uInt nddi = spwddi.size();
    2169             :         Int ddid;
    2170           6 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2171           6 :                                         << "Selected SPWs Ids are " << spwchan << LogIO::POST;
    2172             :         // Example of MS with repeated SPW ID in DD table:
    2173             :         // DD   POL             SPW
    2174             :         //      0       0               0 (RR)
    2175             :         //      1       1               0 (LL)
    2176             :         //      2       2               1 (RR,LL)
    2177             :         //      3       3               2 (RR,LL,RL,LR)
    2178             :         // example of selection: spw=0,1 correlation=RR, so selected DDs are
    2179             :         //      DD      POL             SPW
    2180             :         //      0       0               0
    2181             :         //      2       2               1
    2182             : 
    2183             :         // Do the mapping of DD between input and output
    2184           3 :         if (reindex_p)
    2185             :         {
    2186          10 :             for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
    2187             :             {
    2188             :                 // Get dd id and set the input-output dd map
    2189             :                 // This will only be used to write the DD ids in the main table
    2190           7 :                 ddid = spwddi[selection_ii];
    2191           7 :                 inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
    2192             :             }
    2193             :         }
    2194             : 
    2195           3 :         IPosition shape = spwchan.shape();
    2196           3 :         uInt nSelections = shape[0];
    2197             :         Int spw,channelStart,channelStop,channelStep,channelWidth;
    2198           3 :         if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
    2199             : 
    2200             :         // Do the spw mapping between input and output
    2201           3 :         uInt outputSpwIndex = 0;
    2202          10 :         for(uInt selection_i=0;selection_i<nSelections;selection_i++)
    2203             :         {
    2204             :             // Get spw id and set the input-output spw map
    2205           7 :             spw = spwchan(selection_i,0);
    2206             : 
    2207             :             // Set the channel selection ()
    2208           7 :             channelStart = spwchan(selection_i,1);
    2209           7 :             channelStop = spwchan(selection_i,2);
    2210           7 :             channelStep = spwchan(selection_i,3);
    2211             :             // number of channels to select, starting with first selected channel:
    2212           7 :             channelWidth = 1 + floor(float(channelStop - channelStart) / float(channelStep));
    2213           7 :             channelSelector_p->add (spw, channelStart, channelWidth, channelStep);
    2214             : 
    2215           7 :             if (numOfSelChanMap_p.find(spw) == numOfSelChanMap_p.end())
    2216             :             {
    2217           7 :                 if (reindex_p)
    2218             :                 {
    2219           7 :                     inputOutputSPWIndexMap_p[spw] = outputSpwIndex + ddiStart_p;
    2220             : 
    2221           7 :                     outputInputSPWIndexMap_p[outputSpwIndex] = spw;
    2222             :                 }
    2223             : 
    2224           7 :                 numOfSelChanMap_p[spw] = channelWidth;
    2225             : 
    2226           7 :                 outputSpwIndex ++;
    2227             : 
    2228           7 :                 inputOutputChanIndexMap_p[spw].clear(); // Accesing the vector creates it
    2229             :             }
    2230             :             else
    2231             :             {
    2232           0 :                 numOfSelChanMap_p[spw] += channelWidth;
    2233             :             }
    2234             : 
    2235         455 :             for (Int inpChan=channelStart;inpChan<=channelStop;inpChan += channelStep)
    2236             :             {
    2237         448 :                 inputOutputChanIndexMap_p[spw].push_back(inpChan);
    2238             :             }
    2239             :         }
    2240           3 :     }
    2241             : 
    2242             :     // jagonzal: must fill numOfSelChanMap_p
    2243             :     else
    2244             :     {
    2245          32 :         spwSelection_p = "*";
    2246          32 :         mssel.setSpwExpr(spwSelection_p);
    2247          32 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2248             : 
    2249          32 :         IPosition shape = spwchan.shape();
    2250          32 :         uInt nSelections = shape[0];
    2251             :         Int spw,channelStart,channelStop,channelWidth;
    2252          65 :         for(uInt selection_i=0;selection_i<nSelections;selection_i++)
    2253             :         {
    2254             :             // Get spw id and set the input-output spw map
    2255          33 :             spw = spwchan(selection_i,0);
    2256             : 
    2257             :             // Set the channel selection ()
    2258          33 :             channelStart = spwchan(selection_i,1);
    2259          33 :             channelStop = spwchan(selection_i,2);
    2260          33 :             channelWidth = channelStop-channelStart+1;
    2261          33 :             numOfSelChanMap_p[spw] = channelWidth;
    2262             :         }
    2263             : 
    2264             :         // CAS-8631: Even w/o spw selection MSTransformDataHandler sets spws selection to *
    2265             :         //           in order to obtain the SPW-DDI list. It turns out that sometimes the
    2266             :         //           output DDI sub-table is resorted, for instance in case of non-monotonic
    2267             :         //           DDI-SPW relation,  therefore it is necessary to map input-output DDIS
    2268          32 :         if (reindex_p)
    2269             :         {
    2270          32 :             Vector<Int> spwddi = mssel.getSPWDDIDList(inputMs_p);
    2271             : 
    2272             :             Int ddid;
    2273          32 :             uInt nddi = spwddi.size();
    2274          65 :             for(uInt selection_ii=0;selection_ii<nddi;selection_ii++)
    2275             :             {
    2276             :                 // Get dd id and set the input-output dd map
    2277             :                 // This will only be used to write the DD ids in the main table
    2278          33 :                 ddid = spwddi[selection_ii];
    2279          33 :                 inputOutputDDIndexMap_p[ddid] = selection_ii + ddiStart_p;
    2280             :             }
    2281          32 :         }
    2282             : 
    2283          32 :         spwSelection_p = "";
    2284          32 :     }
    2285             : 
    2286             :     // If we have channel average we have to populate the freqbin map
    2287          35 :     if (channelAverage_p)
    2288             :     {
    2289          17 :         if (!spwSelection_p.empty())
    2290             :         {
    2291           1 :             mssel.setSpwExpr(spwSelection_p);
    2292             :         }
    2293             :         else
    2294             :         {
    2295          16 :             mssel.setSpwExpr("*");
    2296             :         }
    2297             : 
    2298             :         //Vector<Int> spwList = mssel.getSpwList(inputMs_p);
    2299          17 :         Matrix<Int> spwchan = mssel.getChanList(inputMs_p);
    2300             : 
    2301             :         // jagonzal (CAS-7149): Have to remove duplicates: With multiple pols per SPW
    2302             :         // each SPWId appears various (see times test_chanavg_spw_with_diff_pol_shape)
    2303          17 :         vector<Int> noDupSpwList;
    2304          36 :         for (size_t idx=0;idx < spwchan.nrow(); idx++)
    2305             :         {
    2306          19 :             if (find(noDupSpwList.begin(),noDupSpwList.end(),spwchan(idx,0)) == noDupSpwList.end())
    2307             :             {
    2308          19 :                 noDupSpwList.push_back(spwchan(idx,0));
    2309             :             }
    2310             :         }
    2311             : 
    2312             :         //spwList.resize(noDupSpwList.size());
    2313             :         //for (uInt idx=0;idx < noDupSpwList.size(); idx++) spwList(idx) = noDupSpwList[idx];
    2314          17 :         Vector<Int> spwList(noDupSpwList);
    2315             : 
    2316          17 :         if (freqbin_p.size() == 1)
    2317             :         {
    2318          17 :             if(combinespws_p)
    2319             :             {
    2320           0 :                 uInt spwAfterComb = 0;
    2321           0 :                 freqbinMap_p[spwAfterComb] = freqbin_p(spwAfterComb);
    2322             :             }
    2323             :             else
    2324             :             {
    2325             :                 // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2326          17 :                 Int freqbin = freqbin_p(0);
    2327          17 :                 freqbin_p.resize(spwList.size(),True);
    2328          17 :                 freqbin_p = freqbin;
    2329             : 
    2330          36 :                 for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
    2331             :                 {
    2332          19 :                     freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2333             : 
    2334             :                     // jagonzal (new WEIGHT/SIGMA convention)
    2335             :                     // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
    2336          19 :                     if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
    2337             :                     {
    2338           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    2339           0 :                                                                      << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
    2340           0 :                                                                                                                             << " for SPW " << spwList(spw_i)
    2341           0 :                                                                                                                             << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
    2342           0 :                                                                                                                             << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
    2343           0 :                                                                                                                                                                           << " for SPW " << spwList(spw_i)
    2344           0 :                                                                                                                                                                           << LogIO::POST;
    2345           0 :                         freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2346           0 :                         newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2347             :                         // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2348           0 :                         freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
    2349             :                     }
    2350             :                     else
    2351             :                     {
    2352          19 :                         newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2353             :                     }
    2354             :                 }
    2355             :             }
    2356             :         }
    2357             :         else
    2358             :         {
    2359           0 :             if (spwList.size() != freqbin_p.size())
    2360             :             {
    2361           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2362             :                                                         << "Number of frequency bins ( "
    2363             :                                                         << freqbin_p.size() << " ) different from number of selected spws ( "
    2364           0 :                                                         << spwList.size() << " )" << LogIO::POST;
    2365             :             }
    2366             :             else
    2367             :             {
    2368           0 :                 for (size_t spw_i=0;spw_i<spwList.size();spw_i++)
    2369             :                 {
    2370           0 :                     freqbinMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2371             :                     // jagonzal (new WEIGHT/SIGMA convention)
    2372             :                     // jagonzal (CAS-7149): Cut chanbin to not exceed n# selected channels
    2373           0 :                     if (freqbin_p(spw_i) > (Int)numOfSelChanMap_p[spwList(spw_i)])
    2374             :                     {
    2375           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    2376           0 :                                                                         << "Number of selected channels " << numOfSelChanMap_p[spwList(spw_i)]
    2377           0 :                                                                                                                                << " for SPW " << spwList(spw_i)
    2378           0 :                                                                                                                                << " is smaller than specified chanbin " << freqbin_p(spw_i) << endl
    2379           0 :                                                                                                                                << "Setting chanbin to " << numOfSelChanMap_p[spwList(spw_i)]
    2380           0 :                                                                                                                                                                              << " for SPW " << spwList(spw_i)
    2381           0 :                                                                                                                                                                              << LogIO::POST;
    2382           0 :                         freqbinMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2383           0 :                         newWeightFactorMap_p[spwList(spw_i)] = numOfSelChanMap_p[spwList(spw_i)];
    2384             :                         // jagonzal (CAS-8018): Update chanbin, otherwise there is a problem with dropped channels
    2385           0 :                         freqbin_p(spw_i) = numOfSelChanMap_p[spwList(spw_i)];
    2386             :                     }
    2387             :                     else
    2388             :                     {
    2389           0 :                         newWeightFactorMap_p[spwList(spw_i)] = freqbin_p(spw_i);
    2390             :                     }
    2391             :                 }
    2392             :             }
    2393             :         }
    2394          17 :     }
    2395             : 
    2396          35 :     if (!polarizationSelection_p.empty())
    2397             :     {
    2398           0 :         mssel.setPolnExpr(polarizationSelection_p.c_str());
    2399           0 :         Vector <Vector <Slice> > correlationSlices;
    2400           0 :         mssel.getCorrSlices(correlationSlices,inputMs_p);
    2401           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2402           0 :                                         << "Selected correlations are " << correlationSlices << LogIO::POST;
    2403             : 
    2404           0 :         if (channelSelector_p == NULL) channelSelector_p = new vi::FrequencySelectionUsingChannels();
    2405             : 
    2406           0 :         channelSelector_p->addCorrelationSlices(correlationSlices);
    2407             : 
    2408             :         // Get the DDs related to the polarization selection
    2409             :         // when there is no spw selection
    2410           0 :         if (spwSelection_p.empty() and reindex_p)
    2411             :         {
    2412           0 :             std::vector<Int> polddids = mssel.getDDIDList(inputMs_p).tovector();
    2413             :             // The output from MSSelection might not be sorted
    2414           0 :             std::sort(polddids.begin(), polddids.end());
    2415             : 
    2416             :             // Make the in/out DD mapping
    2417           0 :             size_t nddids = polddids.size();
    2418             :             Int dd;
    2419           0 :             for(size_t ii=0;ii<nddids;ii++)
    2420             :             {
    2421             :                 // Get dd id and set the input-output dd map
    2422           0 :                 dd = polddids[ii];
    2423           0 :                 inputOutputDDIndexMap_p[dd] = ii + ddiStart_p;
    2424             :             }
    2425             : 
    2426           0 :         }
    2427             : 
    2428           0 :     }
    2429             : 
    2430          70 :     return;
    2431          35 : }
    2432             : 
    2433             : // -----------------------------------------------------------------------
    2434             : // Method to initialize the reference frame transformation parameters
    2435             : // -----------------------------------------------------------------------
    2436           0 : void MSTransformManager::initRefFrameTransParams()
    2437             : {
    2438           0 :   inputReferenceFrame_p = determineInputRefFrame();
    2439             : 
    2440             :   // Parse output reference frame
    2441           0 :   refFrameTransformation_p = true;
    2442           0 :   radialVelocityCorrection_p = false;
    2443           0 :   if(outputReferenceFramePar_p.empty()) {
    2444           0 :     outputReferenceFrame_p = inputReferenceFrame_p;
    2445             :   }
    2446             :   // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2447           0 :   else if (outputReferenceFramePar_p == "SOURCE") {
    2448           0 :     outputReferenceFrame_p = MFrequency::GEO;
    2449           0 :     radialVelocityCorrection_p = true;
    2450           0 :   } else if(!MFrequency::getType(outputReferenceFrame_p, outputReferenceFramePar_p)) {
    2451           0 :     logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2452           0 :              << "Problem parsing output reference frame:" << outputReferenceFramePar_p
    2453           0 :              << LogIO::EXCEPTION;
    2454             :   }
    2455             : 
    2456           0 :   if (outputReferenceFrame_p == inputReferenceFrame_p) {
    2457           0 :     refFrameTransformation_p = false;
    2458             :   }
    2459             : 
    2460             :   // Determine observatory position from the first row in the observation sub-table of the output (selected) MS
    2461           0 :   MSObservation observationTable;
    2462           0 :   if (userBufferMode_p) {
    2463           0 :     observationTable = selectedInputMs_p->observation();
    2464             :   } else {
    2465           0 :     observationTable = outputMs_p->observation();
    2466             :   }
    2467           0 :   MSObservationColumns observationCols(observationTable);
    2468           0 :   String observatoryName = observationCols.telescopeName()(0);
    2469           0 :   MeasTable::Observatory(observatoryPosition_p,observatoryName);
    2470             : 
    2471             :   // jagonzal: This conversion is needed only for cosmetic reasons
    2472             :   // observatoryPosition_p=MPosition::Convert(observatoryPosition_p, MPosition::ITRF)();
    2473             : 
    2474             :   // Determine observation time from the first row in the selected MS
    2475           0 :   referenceTime_p = selectedInputMsCols_p->timeMeas()(0);
    2476             : 
    2477             :   // Access FIELD cols to get phase center and radial velocity
    2478           0 :   inputMSFieldCols_p = std::make_shared<MSFieldColumns>(selectedInputMs_p->field());
    2479             : 
    2480           0 :   phaseCenter_p = determinePhaseCenter();
    2481           0 : }
    2482             : 
    2483             : /**
    2484             :  * Determine input reference frame from the first row in the SPW 8
    2485             :  * sub-table of the output/selected MS.
    2486             :  * Helper for the initialization of the reference frame transformations
    2487             :  *
    2488             :  * @return Reference frame of output/selected MS.
    2489             :  */
    2490           0 : casacore::MFrequency::Types MSTransformManager::determineInputRefFrame() {
    2491           0 :   MSSpectralWindow spwTable;
    2492           0 :   if (userBufferMode_p) {
    2493           0 :     spwTable = selectedInputMs_p->spectralWindow();
    2494             :   } else {
    2495           0 :     spwTable = outputMs_p->spectralWindow();
    2496             :   }
    2497           0 :   MSSpWindowColumns spwCols(spwTable);
    2498             : 
    2499             :   casacore::MFrequency::Types result;
    2500           0 :   if (reindex_p) {
    2501           0 :     result = MFrequency::castType(spwCols.measFreqRef()(0));
    2502             :   } else {
    2503           0 :     Int firstSelectedDDI = selectedInputMsCols_p->dataDescId()(0);
    2504           0 :     MSDataDescription ddiTable = outputMs_p->dataDescription();
    2505           0 :     MSDataDescColumns ddiCols(ddiTable);
    2506           0 :     Int firstSelectedSPW = ddiCols.spectralWindowId()(firstSelectedDDI);
    2507           0 :     result = MFrequency::castType(spwCols.measFreqRef()(firstSelectedSPW));
    2508           0 :   }
    2509             : 
    2510           0 :   return result;
    2511           0 : }
    2512             : 
    2513             : /**
    2514             :  * Determine phase center from output/selected MS.
    2515             :  * Helper for the initialization of the reference frame transformations
    2516             :  *
    2517             :  * @return phase center from output/selected MS.
    2518             :  */
    2519           0 : casacore::MDirection MSTransformManager::determinePhaseCenter() {
    2520           0 :   casacore::MDirection result;
    2521             : 
    2522             :   // Determine phase center
    2523           0 :   if (phaseCenterPar_p->type() == casac::variant::INT) {
    2524           0 :     Int fieldIdForPhaseCenter = phaseCenterPar_p->toInt();
    2525             : 
    2526           0 :     if (fieldIdForPhaseCenter >= (Int)inputMSFieldCols_p->nrow() ||
    2527             :         fieldIdForPhaseCenter < 0) {
    2528           0 :       logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2529             :                << "Selected FIELD_ID to determine phase center does not exist "
    2530           0 :                << LogIO::POST;
    2531             :     } else {
    2532             :       // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2533           0 :       if (radialVelocityCorrection_p) {
    2534           0 :         radialVelocity_p = inputMSFieldCols_p->radVelMeas(fieldIdForPhaseCenter,
    2535           0 :                                                           referenceTime_p.get("s").getValue());
    2536           0 :         result = inputMSFieldCols_p->phaseDirMeas(fieldIdForPhaseCenter,
    2537           0 :                                                          referenceTime_p.get("s").getValue());
    2538             :       } else {
    2539           0 :         result = inputMSFieldCols_p->phaseDirMeasCol()(fieldIdForPhaseCenter)(IPosition(1,0));
    2540             :       }
    2541             :     }
    2542             :   } else {
    2543           0 :     String phaseCenter = phaseCenterPar_p->toString(true);
    2544             : 
    2545             :     // Determine phase center from the first row in the FIELD sub-table of the output
    2546             :     // (selected) MS
    2547           0 :     if (phaseCenter.empty()) {
    2548           0 :       std::shared_ptr<MSFieldColumns> fieldCols;
    2549           0 :       if (userBufferMode_p) {
    2550           0 :         fieldCols = inputMSFieldCols_p;
    2551             :       } else {
    2552           0 :         MSField fieldTable = outputMs_p->field();
    2553           0 :         fieldCols = std::make_shared<MSFieldColumns>(fieldTable);
    2554           0 :       }
    2555             : 
    2556             :       // CAS-8870: Mstransform with outframe=’SOURCE’ crashes because of ephemeris type
    2557           0 :       Int firstSelectedField = selectedInputMsCols_p->fieldId()(0);
    2558           0 :       if (inputOutputFieldIndexMap_p.find(firstSelectedField) !=
    2559           0 :           inputOutputFieldIndexMap_p.end()) {
    2560           0 :         firstSelectedField = inputOutputFieldIndexMap_p[firstSelectedField];
    2561             :       }
    2562             : 
    2563             :       // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2564           0 :       if (radialVelocityCorrection_p) {
    2565           0 :         radialVelocity_p = fieldCols->radVelMeas(firstSelectedField, referenceTime_p.get("s").getValue());
    2566             : 
    2567           0 :         if (radialVelocity_p.getRef().getType() != MRadialVelocity::GEO) {
    2568           0 :           logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2569             :                    << "Cannot perform radial velocity correction with ephemerides attached "
    2570             :                    << "to first selected field " << firstSelectedField << " of type "
    2571           0 :                    << MRadialVelocity::showType(radialVelocity_p.getRef().getType())
    2572             :                    << ".\nType needs to be GEO."
    2573           0 :                    << LogIO::EXCEPTION;
    2574             :         }
    2575             : 
    2576           0 :         result = fieldCols->phaseDirMeas(firstSelectedField,referenceTime_p.get("s").getValue());
    2577             :       } else {
    2578           0 :         result = fieldCols->phaseDirMeasCol()(firstSelectedField)(IPosition(1,0));
    2579             :       }
    2580           0 :     } else {
    2581             :       // Parse phase center
    2582           0 :       if(!casaMDirection(phaseCenter, result)) {
    2583           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    2584           0 :                  << "Cannot interpret phase center " << phaseCenter << LogIO::POST;
    2585             :       }
    2586             :     }
    2587           0 :   }
    2588             : 
    2589           0 :   return result;
    2590           0 : }
    2591             : 
    2592             : // -----------------------------------------------------------------------
    2593             : // Method to re-grid each SPW separately in the SPW sub-table
    2594             : // It also sets the input/output frequency arrays to be used by the interpolations
    2595             : // -----------------------------------------------------------------------
    2596           0 : void MSTransformManager::regridSpwSubTable()
    2597             : {
    2598             :   // Access Spectral Window sub-table
    2599           0 :   MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2600           0 :   auto nInputSpws = spwTable.nrow();
    2601           0 :   MSSpWindowColumns spwCols(spwTable);
    2602             : 
    2603             :   // Access columns which have to be modified
    2604           0 :   ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    2605           0 :   ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    2606           0 :   ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    2607           0 :   ArrayColumn<Double> resolutionCol = spwCols.resolution();
    2608           0 :   ScalarColumn<Int> numChanCol = spwCols.numChan();
    2609           0 :   ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
    2610           0 :   ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    2611           0 :   ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
    2612             : 
    2613             :   Int spwId;
    2614           0 :   for(rownr_t spw_idx=0; spw_idx<nInputSpws; ++spw_idx) {
    2615           0 :     if (outputInputSPWIndexMap_p.size() > 0) {
    2616           0 :       spwId = outputInputSPWIndexMap_p[spw_idx];
    2617             :     } else {
    2618           0 :       spwId = spw_idx;
    2619             :     }
    2620             : 
    2621             :     // jagonzal: Skip this SPW in non-reindex mode
    2622           0 :     if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end()))
    2623           0 :       continue;
    2624             : 
    2625           0 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2626           0 :              << "Regridding SPW with Id " <<  spwId << LogIO::POST;
    2627             : 
    2628             :     // Get input frequencies and widths
    2629           0 :     Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
    2630           0 :     Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
    2631             : 
    2632             :     // Calculate output SPW
    2633           0 :     Vector<Double> regriddedCHAN_FREQ;
    2634           0 :     Vector<Double> regriddedCHAN_WIDTH;
    2635           0 :     Vector<Double> inputCHAN_FREQ;
    2636           0 :     Vector<Double> inputCHAN_WIDTH;
    2637           0 :     regridSpwAux(spwId, MFrequency::castType(spwCols.measFreqRef()(spw_idx)),
    2638             :                  originalChanFreq, originalChanWidth,
    2639             :                  inputCHAN_FREQ, inputCHAN_WIDTH,
    2640           0 :                  regriddedCHAN_FREQ, regriddedCHAN_WIDTH, string("Input"));
    2641           0 :     spwInfo inputSpw(inputCHAN_FREQ, inputCHAN_WIDTH);
    2642           0 :     spwInfo outputSpw(regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
    2643             : 
    2644             :     // Set the output SPW characteristics in the SPW sub-table
    2645           0 :     numChanCol.put(spw_idx, outputSpw.NUM_CHAN);
    2646           0 :     chanFreqCol.put(spw_idx, outputSpw.CHAN_FREQ);
    2647           0 :     chanWidthCol.put(spw_idx, outputSpw.CHAN_WIDTH);
    2648           0 :     effectiveBWCol.put(spw_idx, outputSpw.EFFECTIVE_BW);
    2649           0 :     resolutionCol.put(spw_idx, outputSpw.RESOLUTION);
    2650           0 :     refFrequencyCol.put(spw_idx, outputSpw.REF_FREQUENCY);
    2651           0 :     totalBandwidthCol.put(spw_idx, outputSpw.TOTAL_BANDWIDTH);
    2652             : 
    2653             :     // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    2654           0 :     if(outputReferenceFrame_p==MFrequency::GEO) {
    2655             :       // i.e. outframe was GEO or SOURCE
    2656           0 :       measFreqRefCol.put(spw_idx, (Int)MFrequency::REST);
    2657             :     } else {
    2658           0 :       measFreqRefCol.put(spw_idx, (Int)outputReferenceFrame_p);
    2659             :     }
    2660             : 
    2661             :     // Add input-output SPW pair to map
    2662           0 :     inputOutputSpwMap_p[spwId] = std::make_pair(inputSpw,outputSpw);
    2663             : 
    2664             :     // Prepare frequency transformation engine for the reference time
    2665           0 :     if (fftShiftEnabled_p) {
    2666           0 :       MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
    2667           0 :                                     MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2668           0 :       MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
    2669           0 :                                      MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2670           0 :       refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    2671             : 
    2672           0 :       for(uInt chan_idx=0; chan_idx < inputOutputSpwMap_p[spwId].first.CHAN_FREQ.size();
    2673             :           ++chan_idx) {
    2674           0 :         inputOutputSpwMap_p[spwId].first.CHAN_FREQ_aux[chan_idx] =
    2675           0 :           refTimeFreqTransEngine_p(inputOutputSpwMap_p[spwId].first.CHAN_FREQ[chan_idx]).
    2676           0 :           get(MSTransformations::Hz).getValue();
    2677             :       }
    2678           0 :     }
    2679           0 :   }
    2680           0 : }
    2681             : 
    2682             : // -----------------------------------------------------------------------
    2683             : // Method to combine and re-grid the SPW sub-table
    2684             : // It also sets the input/output frequency arrays to be used by the interpolations
    2685             : // -----------------------------------------------------------------------
    2686           0 : void MSTransformManager::regridAndCombineSpwSubtable()
    2687             : {
    2688             :     /// Determine input SPW structure ////////////////////
    2689             : 
    2690             :     // Access Spectral Window sub-table
    2691           0 :     MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2692           0 :     auto nInputSpws = spwTable.nrow();
    2693           0 :     MSSpWindowColumns spwCols(spwTable);
    2694             : 
    2695             :     // Access columns which have to be modified
    2696           0 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    2697           0 :     ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    2698           0 :     ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    2699           0 :     ArrayColumn<Double> resolutionCol = spwCols.resolution();
    2700           0 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    2701           0 :     ScalarColumn<Double> refFrequencyCol = spwCols.refFrequency();
    2702           0 :     ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    2703           0 :     ScalarColumn<Int> measFreqRefCol = spwCols.measFreqRef();
    2704             : 
    2705             :     // Create list of input channels
    2706           0 :     vector<channelInfo> inputChannels;
    2707           0 :     for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    2708             :     {
    2709             :         Int spwId;
    2710           0 :                 if (outputInputSPWIndexMap_p.size())
    2711             :                 {
    2712           0 :                         spwId = outputInputSPWIndexMap_p[spw_idx];
    2713             :                 }
    2714             :                 else
    2715             :                 {
    2716           0 :                         spwId = spw_idx;
    2717             :                 }
    2718             : 
    2719             :                 // jagonzal: Skip this SPW in non-reindex mode
    2720           0 :         if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
    2721             : 
    2722           0 :         Vector<Double> originalChanFreq(chanFreqCol(spw_idx));
    2723           0 :         Vector<Double> originalChanWidth(chanWidthCol(spw_idx));
    2724           0 :         Vector<Double> inputEffectiveBW(effectiveBWCol(spw_idx));
    2725           0 :         Vector<Double> inputResolution(resolutionCol(spw_idx));
    2726           0 :         uInt nChannels = originalChanFreq.size();
    2727             : 
    2728           0 :         for (uInt chan_idx=0;chan_idx<nChannels;chan_idx++)
    2729             :         {
    2730           0 :                 channelInfo channelInfo_idx;
    2731           0 :                 channelInfo_idx.SPW_id = spwId;
    2732             : 
    2733           0 :                 channelInfo_idx.inpChannel = chan_idx;
    2734           0 :                 channelInfo_idx.CHAN_FREQ = originalChanFreq(chan_idx);
    2735           0 :                 channelInfo_idx.CHAN_WIDTH = originalChanWidth(chan_idx);
    2736           0 :                 channelInfo_idx.EFFECTIVE_BW = inputEffectiveBW(chan_idx);
    2737           0 :                 channelInfo_idx.RESOLUTION = inputResolution(chan_idx);
    2738             : 
    2739           0 :                 inputChannels.push_back(channelInfo_idx);
    2740           0 :         }
    2741           0 :     }
    2742             : 
    2743             :     // Sort input channels
    2744           0 :     sort (inputChannels.begin(), inputChannels.end());
    2745             : 
    2746             :     /// Determine combined SPW structure ///////////////////
    2747             : 
    2748             :     // Determine combined SPWs
    2749           0 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2750           0 :              << "Calculate combined SPW frequencies" << LogIO::POST;
    2751             : 
    2752           0 :     Vector<Double> combinedCHAN_FREQ;
    2753           0 :     Vector<Double> combinedCHAN_WIDTH;
    2754           0 :     std::vector<std::vector<Int> > averageWhichChan;
    2755           0 :     std::vector<std::vector<Int> > averageWhichSPW;
    2756           0 :     std::vector<std::vector<Double> > averageChanFrac;
    2757           0 :     MSTransformRegridder::combineSpws(logger_p,outMsName_p,Vector<Int>(1,-1),
    2758             :                                                                   combinedCHAN_FREQ,combinedCHAN_WIDTH,
    2759             :                                                                           averageWhichChan, averageWhichSPW, averageChanFrac, true);
    2760             : 
    2761             :         // Create list of combined channels
    2762           0 :         vector<channelInfo> combinedChannels;
    2763           0 :         uInt nCombinedChannels = combinedCHAN_FREQ.size();
    2764           0 :         for (uInt chan_idx=0;chan_idx<nCombinedChannels;chan_idx++)
    2765             :         {
    2766           0 :                 channelInfo channelInfo_idx;
    2767           0 :                 channelInfo_idx.SPW_id = 0;
    2768           0 :                 channelInfo_idx.inpChannel = chan_idx;
    2769           0 :                 channelInfo_idx.CHAN_FREQ = combinedCHAN_FREQ(chan_idx);
    2770           0 :                 channelInfo_idx.CHAN_WIDTH = combinedCHAN_WIDTH(chan_idx);
    2771           0 :                 channelInfo_idx.EFFECTIVE_BW = combinedCHAN_WIDTH(chan_idx);
    2772           0 :                 channelInfo_idx.RESOLUTION = combinedCHAN_WIDTH(chan_idx);
    2773           0 :                 channelInfo_idx.contribFrac = averageChanFrac.at(chan_idx);
    2774           0 :                 channelInfo_idx.contribSPW_id = averageWhichSPW.at(chan_idx);
    2775           0 :                 channelInfo_idx.contribChannel = averageWhichChan.at(chan_idx);
    2776           0 :                 combinedChannels.push_back(channelInfo_idx);
    2777           0 :         }
    2778             : 
    2779             :         // create list of input overlapping channels per combined channel
    2780             :         // note combineSpws has an edge case growing channels for slight overlap on edges,
    2781             :         // there the overlap is 1 even though combchannel->overlap(inputchannel) is slightly smaller than 1
    2782           0 :         inputOutputChanFactorMap_p.clear();
    2783             : 
    2784           0 :         for (auto combChanIter = combinedChannels.begin(); combChanIter != combinedChannels.end(); combChanIter++)
    2785             :         {
    2786           0 :                 for (auto k = 0lu; k < combChanIter->contribFrac.size(); k++)
    2787             :                 {
    2788             :                         // combineSpws sorts spw so we need to map back to input selection to get correct input spw
    2789           0 :                         uInt spw_idx = combChanIter->contribSPW_id[k];
    2790           0 :                         if (outputInputSPWIndexMap_p.size())
    2791             :                         {
    2792           0 :                                 spw_idx = outputInputSPWIndexMap_p[spw_idx];
    2793             :                         }
    2794             : 
    2795             :                         // jagonzal: Skip this SPW in non-reindex mode
    2796           0 :                 if ((!reindex_p) and (numOfSelChanMap_p.find(spw_idx) == numOfSelChanMap_p.end())) continue;
    2797             : 
    2798           0 :                         inputOutputChanFactorMap_p[combChanIter->inpChannel].
    2799           0 :                         push_back(channelContribution(spw_idx, combChanIter->contribChannel[k], combChanIter->inpChannel, combChanIter->contribFrac[k]));
    2800             :                 }
    2801             :         }
    2802             : 
    2803             :     /// Calculate output SPW ///////////////////////////////
    2804           0 :     Vector<Double> regriddedCHAN_FREQ;
    2805           0 :     Vector<Double> regriddedCHAN_WIDTH;
    2806           0 :     Vector<Double> inputCHAN_FREQ;
    2807           0 :     Vector<Double> inputCHAN_WIDTH;
    2808           0 :     regridSpwAux(0,inputReferenceFrame_p,combinedCHAN_FREQ,combinedCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH,regriddedCHAN_FREQ,regriddedCHAN_WIDTH,string("Combined"));
    2809           0 :     spwInfo inputSpw(inputCHAN_FREQ,inputCHAN_WIDTH);
    2810           0 :     spwInfo outputSpw(regriddedCHAN_FREQ,regriddedCHAN_WIDTH);
    2811             : 
    2812             :     /// Modify SPW subtable ////////////////////////////////
    2813             : 
    2814           0 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2815           0 :                 << "Write output SPW subtable " << LogIO::POST;
    2816             : 
    2817             :     // Delete combined SPWs (reverse to preserve row number)
    2818           0 :     uInt rowsToDelete = nInputSpws-1;
    2819           0 :     for(Int spw_idx=rowsToDelete; spw_idx>0; spw_idx--)
    2820             :     {
    2821           0 :         spwTable.removeRow(spw_idx);
    2822             :     }
    2823             : 
    2824             :     // Set the output SPW characteristics in the SPW sub-table
    2825           0 :     numChanCol.put(0,outputSpw.NUM_CHAN);
    2826           0 :     chanFreqCol.put(0, outputSpw.CHAN_FREQ);
    2827           0 :     chanWidthCol.put(0,  outputSpw.CHAN_WIDTH);
    2828           0 :     effectiveBWCol.put(0, outputSpw.EFFECTIVE_BW);
    2829           0 :     resolutionCol.put(0, outputSpw.RESOLUTION);
    2830           0 :     refFrequencyCol.put(0,outputSpw.REF_FREQUENCY);
    2831           0 :     totalBandwidthCol.put(0,outputSpw.TOTAL_BANDWIDTH);
    2832           0 :     measFreqRefCol.put(0,outputReferenceFrame_p);
    2833             : 
    2834             :     /// Add input-output SPW pair to map ///////////////////
    2835           0 :     inputOutputSpwMap_p[0] = std::make_pair(inputSpw,outputSpw);
    2836             : 
    2837             :     // Prepare frequency transformation engine for the reference time
    2838           0 :     if (fftShiftEnabled_p)
    2839             :     {
    2840           0 :         MFrequency::Ref inputFrameRef(inputReferenceFrame_p,
    2841           0 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2842           0 :         MFrequency::Ref outputFrameRef(outputReferenceFrame_p,
    2843           0 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    2844           0 :         refTimeFreqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    2845             : 
    2846           0 :         for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[0].first.CHAN_FREQ.size(); chan_idx++)
    2847             :         {
    2848           0 :                 inputOutputSpwMap_p[0].first.CHAN_FREQ_aux[chan_idx] =
    2849           0 :                   refTimeFreqTransEngine_p(inputOutputSpwMap_p[0].first.CHAN_FREQ[chan_idx]).
    2850           0 :                   get(MSTransformations::Hz).getValue();
    2851             :         }
    2852           0 :     }
    2853             : 
    2854           0 :     return;
    2855           0 : }
    2856             : 
    2857             : 
    2858             : // -----------------------------------------------------------------------
    2859             : // Auxiliary method common whenever re-gridding is necessary (with or without combining
    2860             : // the SPWs). It regrids one SPW.
    2861             : // -----------------------------------------------------------------------
    2862           0 : void MSTransformManager::regridSpwAux(Int spwId, MFrequency::Types spwInputRefFrame,
    2863             :                                       Vector<Double> &originalCHAN_FREQ,
    2864             :                                       Vector<Double> &originalCHAN_WIDTH,
    2865             :                                       Vector<Double> &inputCHAN_FREQ,
    2866             :                                       Vector<Double> &inputCHAN_WIDTH,
    2867             :                                       Vector<Double> &regriddedCHAN_FREQ,
    2868             :                                       Vector<Double> &regriddedCHAN_WIDTH,
    2869             :                                       string msg)
    2870             : {
    2871             : 
    2872             :   // Print characteristics of input SPW
    2873           0 :   ostringstream oss;
    2874           0 :   oss << msg;
    2875           0 :   oss << " SPW: " << std::setw(5) << originalCHAN_FREQ.size()
    2876             :       << " channels, first channel = "
    2877           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2878           0 :       << originalCHAN_FREQ(0) << " Hz"
    2879             :       << ", last channel = "
    2880           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2881           0 :       << originalCHAN_FREQ(originalCHAN_FREQ.size() -1) << " Hz"
    2882             :       << ", first width = "
    2883           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2884           0 :       << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
    2885             :       << ", last width = "
    2886           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2887           0 :       << originalCHAN_WIDTH(originalCHAN_WIDTH.size()-1) << " Hz"
    2888             :     ;
    2889             : 
    2890           0 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
    2891             : 
    2892             :   // Apply channel average if necessary
    2893           0 :   if (freqbinMap_p.find(spwId) != freqbinMap_p.end()) {
    2894           0 :     calculateIntermediateFrequencies(spwId,originalCHAN_FREQ,originalCHAN_WIDTH,inputCHAN_FREQ,inputCHAN_WIDTH);
    2895             : 
    2896           0 :     oss.str("");
    2897           0 :     oss.clear();
    2898           0 :     oss << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
    2899             :         << " channels, first channel = "
    2900           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    2901           0 :         << inputCHAN_FREQ(0) << " Hz"
    2902             :         << ", last channel = "
    2903           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    2904           0 :         << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
    2905           0 :     logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2906           0 :              << oss.str() << LogIO::POST;
    2907             :   } else {
    2908           0 :     numOfCombInputChanMap_p[spwId] = originalCHAN_FREQ.size();
    2909           0 :     numOfCombInterChanMap_p[spwId] = originalCHAN_FREQ.size();
    2910           0 :     inputCHAN_FREQ = originalCHAN_FREQ;
    2911           0 :     inputCHAN_WIDTH = originalCHAN_WIDTH;
    2912             :   }
    2913             : 
    2914             :   // Re-grid the output SPW to be uniform and change reference frame
    2915           0 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2916           0 :            << "Calculate frequencies in output reference frame " << LogIO::POST;
    2917             : 
    2918             :   Double weightScale;
    2919           0 :   bool ret = MSTransformRegridder::calcChanFreqs(logger_p,
    2920             :                                                  regriddedCHAN_FREQ, regriddedCHAN_WIDTH,
    2921             :                                                  weightScale, inputCHAN_FREQ,
    2922           0 :                                                  inputCHAN_WIDTH, phaseCenter_p,
    2923           0 :                                                  spwInputRefFrame, referenceTime_p,
    2924           0 :                                                  observatoryPosition_p, mode_p, nChan_p,
    2925           0 :                                                  start_p, width_p, restFrequency_p,
    2926           0 :                                                  outputReferenceFramePar_p,
    2927           0 :                                                  velocityType_p,
    2928             :                                                  true, // verbose
    2929           0 :                                                  radialVelocity_p);
    2930             : 
    2931           0 :   if (!ret) {
    2932           0 :     logger_p << LogIO::SEVERE << "calcChanFreqs failed, check input start and width parameters"
    2933           0 :              << LogIO::EXCEPTION;
    2934             :   }
    2935             : 
    2936           0 :   ostringstream oss_debug;
    2937           0 :   oss_debug << "after calcChanFreqs, phaseCenter_p=" << phaseCenter_p << endl
    2938           0 :             << " inputReferenceFrame_p=" << inputReferenceFrame_p << endl
    2939           0 :             << " referenceTime_p=" << referenceTime_p << endl
    2940           0 :             << " observatoryPosition_p=" << observatoryPosition_p << endl
    2941           0 :             << " mode_p=" << mode_p << endl
    2942           0 :             << " nChan_p=" << nChan_p << endl
    2943           0 :             << " start_p=" << start_p << endl
    2944           0 :             << " width_p=" << width_p << endl
    2945           0 :             << " restFrequency_p=" << restFrequency_p << endl
    2946           0 :             << " outputReferenceFrame_p=" << outputReferenceFrame_p << endl
    2947           0 :             << " velocityType_p=" << velocityType_p << endl
    2948           0 :             << " radialVelocity_p=" << radialVelocity_p;
    2949           0 :   logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__) <<
    2950           0 :     oss_debug.str() << LogIO::POST;
    2951             : 
    2952             :   // jagonzal (new WEIGHT/SIGMA convention in CASA 4.2.2)
    2953           0 :   if (newWeightFactorMap_p.find(spwId) == newWeightFactorMap_p.end()) {
    2954           0 :     newWeightFactorMap_p[spwId] = weightScale;
    2955             :   } else {
    2956           0 :     newWeightFactorMap_p[spwId] *= weightScale;
    2957             :   }
    2958             : 
    2959           0 :   checkAndPreaverageChannelsIfNeeded(spwId, inputCHAN_FREQ, inputCHAN_WIDTH,
    2960             :                                      originalCHAN_FREQ, originalCHAN_WIDTH,
    2961             :                                      regriddedCHAN_FREQ, regriddedCHAN_WIDTH);
    2962             : 
    2963             :   // Print characteristics of output SPW
    2964           0 :   oss.str("");
    2965           0 :   oss.clear();
    2966           0 :   oss << "Output SPW: " << std::setw(5) << regriddedCHAN_FREQ.size()
    2967             :       << " channels, first channel = "
    2968           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2969           0 :       << regriddedCHAN_FREQ(0) << " Hz"
    2970             :       << ", last channel = "
    2971           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2972           0 :       << regriddedCHAN_FREQ(regriddedCHAN_FREQ.size()-1) << " Hz"
    2973             :       <<", first width = "
    2974           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2975           0 :       << regriddedCHAN_WIDTH(0) << " Hz"
    2976             :       << ", last width = "
    2977           0 :       << std::setprecision(9) << std::setw(14) << std::scientific
    2978           0 :       << regriddedCHAN_WIDTH(regriddedCHAN_WIDTH.size()-1) << " Hz";
    2979             : 
    2980           0 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2981           0 :            << oss.str() << LogIO::POST;
    2982           0 : }
    2983             : 
    2984             : // -----------------------------------------------------------------------
    2985             : //
    2986             : // -----------------------------------------------------------------------
    2987           0 : void MSTransformManager::separateSpwSubtable()
    2988             : {
    2989           0 :         if (Table::isReadable(outputMs_p->spectralWindowTableName()) and !outputMs_p->spectralWindow().isNull())
    2990             :         {
    2991             :                 // Access Spectral Window sub-table
    2992           0 :                 MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    2993             : 
    2994           0 :                 if (spwTable.nrow() > 0)
    2995             :                 {
    2996           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    2997           0 :                                 << " Multiplexing SPECTRAL_WINDOW sub-table to take into account new SPWs " << LogIO::POST;
    2998             : 
    2999           0 :                         MSSpWindowColumns spwCols(spwTable);
    3000             : 
    3001             :                         // Access columns which have to be separated
    3002           0 :                         ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    3003           0 :                         Vector<Double> chanFreq = chanFreqCol(0);
    3004           0 :                         ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    3005           0 :                         Vector<Double> chanWidth = chanWidthCol(0);
    3006           0 :                         ArrayColumn<Double> effectiveBWCol = spwCols.chanWidth();
    3007           0 :                         Vector<Double> effectiveBW = effectiveBWCol(0);
    3008           0 :                         ArrayColumn<Double> resolutionCol = spwCols.resolution();
    3009           0 :                         Vector<Double> resolution = resolutionCol(0);
    3010             : 
    3011             :                         // Resize columns to be separated
    3012             :                         // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
    3013             :                         /*
    3014             :                         if (tailOfChansforLastSpw_p)
    3015             :                         {
    3016             :                                 uInt nInChannels = chanFreq.size();
    3017             :                                 uInt nOutChannels = nspws_p*chansPerOutputSpw_p;
    3018             :                                 uInt newChannels = nOutChannels-nInChannels;
    3019             :                                 Double lastFreq = chanFreq(chanFreq.size()-1);
    3020             :                                 Double lastWidth = chanWidth(chanFreq.size()-1);
    3021             :                                 Double lastEffectiveBW = effectiveBW(chanFreq.size()-1);
    3022             :                                 Double lastResolution = resolution(chanFreq.size()-1);
    3023             : 
    3024             :                                 chanFreq.resize(nOutChannels,true);
    3025             :                                 chanWidth.resize(nOutChannels,true);
    3026             :                                 effectiveBW.resize(nOutChannels,true);
    3027             :                                 resolution.resize(nOutChannels,true);
    3028             : 
    3029             :                                 uInt outIndex;
    3030             :                                 for (uInt newChanIdx = 0; newChanIdx<newChannels; newChanIdx++)
    3031             :                                 {
    3032             :                                         outIndex = nInChannels+newChanIdx;
    3033             :                                         chanFreq(outIndex) = lastFreq + (newChanIdx+1)*lastWidth;
    3034             :                                         chanWidth(outIndex) = lastWidth;
    3035             :                                         effectiveBW(outIndex) = lastEffectiveBW;
    3036             :                                         resolution(outIndex) = lastResolution;
    3037             :                                 }
    3038             :                         }
    3039             :                         */
    3040             : 
    3041             :                         // Calculate bandwidth per output spw
    3042           0 :                         Double totalBandwidth = chanWidth(0)*chansPerOutputSpw_p;
    3043             : 
    3044           0 :                         uInt rowIndex = 0;
    3045           0 :                         for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
    3046             :                         {
    3047             :                                 // Columns that can be just copied
    3048           0 :                                 if (rowIndex > 0)
    3049             :                                 {
    3050             :                                         // Add row
    3051           0 :                                         spwTable.addRow(1,true);
    3052             : 
    3053           0 :                                         spwCols.measFreqRef().put(rowIndex,spwCols.measFreqRef()(0));
    3054           0 :                                         spwCols.flagRow().put(rowIndex,spwCols.flagRow()(0));
    3055           0 :                                         spwCols.freqGroup().put(rowIndex,spwCols.freqGroup()(0));
    3056           0 :                                         spwCols.freqGroupName().put(rowIndex,spwCols.freqGroupName()(0));
    3057           0 :                                         spwCols.ifConvChain().put(rowIndex,spwCols.ifConvChain()(0));
    3058           0 :                                         spwCols.name().put(rowIndex,spwCols.name()(0));
    3059           0 :                                         spwCols.netSideband().put(rowIndex,spwCols.netSideband()(0));
    3060             : 
    3061             :                                         // Optional columns
    3062           0 :                                         if (MSTransformDataHandler::columnOk(spwCols.bbcNo()))
    3063             :                                         {
    3064           0 :                                                 spwCols.bbcNo().put(rowIndex,spwCols.bbcNo()(0));
    3065             :                                         }
    3066             : 
    3067           0 :                                         if (MSTransformDataHandler::columnOk(spwCols.assocSpwId()))
    3068             :                                         {
    3069           0 :                                                 spwCols.assocSpwId().put(rowIndex,spwCols.assocSpwId()(0));
    3070             :                                         }
    3071             : 
    3072           0 :                                         if (MSTransformDataHandler::columnOk(spwCols.assocNature()))
    3073             :                                         {
    3074           0 :                                                 spwCols.assocNature().put(rowIndex,spwCols.assocNature()(0));
    3075             :                                         }
    3076             : 
    3077           0 :                                         if (MSTransformDataHandler::columnOk(spwCols.bbcSideband()))
    3078             :                                         {
    3079           0 :                                                 spwCols.bbcSideband().put(rowIndex,spwCols.bbcSideband()(0));
    3080             :                                         }
    3081             : 
    3082           0 :                                         if (MSTransformDataHandler::columnOk(spwCols.dopplerId()))
    3083             :                                         {
    3084           0 :                                                 spwCols.dopplerId().put(rowIndex,spwCols.dopplerId()(0));
    3085             :                                         }
    3086             : 
    3087           0 :                     if (MSTransformDataHandler::columnOk(spwCols.receiverId()))
    3088             :                     {
    3089           0 :                         spwCols.receiverId().put(rowIndex,spwCols.receiverId()(0));
    3090             :                     }
    3091             : 
    3092           0 :                     if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
    3093           0 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION"))
    3094             :                     {
    3095           0 :                         ScalarColumn<String> swfCol(spwTable, "SDM_WINDOW_FUNCTION");
    3096           0 :                         swfCol.put(rowIndex, swfCol(0));
    3097           0 :                     }
    3098             : 
    3099           0 :                     if (spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
    3100           0 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
    3101             :                     {
    3102           0 :                         ScalarColumn<Int> snbCol(spwTable, "SDM_NUM_BIN");
    3103           0 :                         snbCol.put(rowIndex, snbCol(0));
    3104           0 :                     }
    3105             : 
    3106           0 :                     if (spwTable.tableDesc().isColumn("SDM_CORR_BIT") &&
    3107           0 :                         spwTable.tableDesc().columnDescSet().isDefined("SDM_CORR_BIT"))
    3108             :                     {
    3109           0 :                         ScalarColumn<String> corrBitCol(spwTable, "SDM_CORR_BIT");
    3110           0 :                         corrBitCol.put(rowIndex, corrBitCol(0));
    3111           0 :                     }
    3112             : 
    3113             :                                 }
    3114             : 
    3115           0 :                                 if ( (spw_i < nspws_p-1) or (tailOfChansforLastSpw_p == 0) )
    3116             :                                 {
    3117           0 :                                         Slice range(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    3118             : 
    3119             :                                         // Array columns that have to be modified
    3120           0 :                                         spwCols.chanFreq().put(rowIndex,chanFreq(range));
    3121           0 :                                         spwCols.chanWidth().put(rowIndex,chanWidth(range));
    3122           0 :                                         spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
    3123           0 :                                         spwCols.resolution().put(rowIndex,resolution(range));
    3124             : 
    3125             :                                         // Scalar columns that have to be modified
    3126           0 :                                         spwCols.numChan().put(rowIndex,chansPerOutputSpw_p);
    3127           0 :                                         spwCols.totalBandwidth().put(rowIndex,totalBandwidth);
    3128           0 :                                         spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
    3129           0 :                                 }
    3130             :                                 // jagonzal (jagonzal (CAS-7435)): Last spw must have fewer channels
    3131             :                                 else
    3132             :                                 {
    3133           0 :                                         Slice range(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    3134             : 
    3135             :                                         // Array columns that have to be modified
    3136           0 :                                         spwCols.chanFreq().put(rowIndex,chanFreq(range));
    3137           0 :                                         spwCols.chanWidth().put(rowIndex,chanWidth(range));
    3138           0 :                                         spwCols.effectiveBW().put(rowIndex,effectiveBW(range));
    3139           0 :                                         spwCols.resolution().put(rowIndex,resolution(range));
    3140             : 
    3141             :                                         // Scalar columns that have to be modified
    3142           0 :                                         spwCols.numChan().put(rowIndex,tailOfChansforLastSpw_p);
    3143           0 :                                         spwCols.totalBandwidth().put(rowIndex,chanWidth(0)*tailOfChansforLastSpw_p);
    3144           0 :                                         spwCols.refFrequency().put(rowIndex,chanFreq(range)(0));
    3145             :                                 }
    3146             : 
    3147           0 :                                 rowIndex += 1;
    3148             :                         }
    3149             : 
    3150             :                         // Remove first row
    3151             :                         // spwTable.removeRow(0);
    3152           0 :                 }
    3153             :         else
    3154             :         {
    3155           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3156           0 :                                 << "SPECTRAL_WINDOW sub-table found but has no valid content" << LogIO::POST;
    3157             :         }
    3158           0 :     }
    3159             :     else
    3160             :     {
    3161           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3162           0 :                         << "SPECTRAL_WINDOW sub-table not found " << LogIO::POST;
    3163             :     }
    3164             : 
    3165           0 :         return;
    3166             : }
    3167             : 
    3168             : // -----------------------------------------------------------------------
    3169             : //
    3170             : // -----------------------------------------------------------------------
    3171           0 : void MSTransformManager::separateFeedSubtable()
    3172             : {
    3173           0 :         if (Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
    3174             :         {
    3175             :                 // Access Feed sub-table
    3176           0 :                 MSFeed feedtable = outputMs_p->feed();
    3177             : 
    3178           0 :                 if (feedtable.nrow() > 0)
    3179             :                 {
    3180           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3181           0 :                                 << " Multiplexing FEED sub-table to take into account new SPWs " << LogIO::POST;
    3182             : 
    3183           0 :                         MSFeedColumns feedCols(feedtable);
    3184             : 
    3185             :                     // Get original content from columns
    3186           0 :                         Array<Double> position = feedCols.position().getColumn();
    3187           0 :                         Array<Double> beamOffset = feedCols.beamOffset().getColumn();
    3188           0 :                         Array<String> polarizationType = feedCols.polarizationType().getColumn();
    3189           0 :                         Array<Complex> polResponse = feedCols.polResponse().getColumn();
    3190           0 :                         Array<Double> receptorAngle = feedCols.receptorAngle().getColumn();
    3191           0 :                         Array<Int> antennaId = feedCols.antennaId().getColumn();
    3192           0 :                         Array<Int> beamId = feedCols.beamId().getColumn();
    3193           0 :                         Array<Int> feedId = feedCols.feedId().getColumn();
    3194           0 :                         Array<Double> interval = feedCols.interval().getColumn();
    3195           0 :                         Array<Int> numReceptors = feedCols.numReceptors().getColumn();
    3196           0 :                         Array<Int> spectralWindowId = feedCols.spectralWindowId().getColumn();
    3197           0 :                         Array<Double> time = feedCols.time().getColumn();
    3198             : 
    3199             :                         // Optional columns
    3200           0 :                         Array<Double> focusLength;
    3201           0 :                         if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
    3202             :                         {
    3203           0 :                                 focusLength = feedCols.focusLength().getColumn();
    3204             :                         }
    3205             : 
    3206           0 :                         Array<Int> phasedFeedId;
    3207           0 :                         if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
    3208             :                         {
    3209           0 :                                 phasedFeedId = feedCols.phasedFeedId().getColumn();
    3210             :                         }
    3211             : 
    3212           0 :                         auto nRowsPerSpw = feedCols.spectralWindowId().nrow();
    3213           0 :                     auto rowIndex = nRowsPerSpw;
    3214           0 :                     for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3215             :                     {
    3216             :                         // Add rows
    3217           0 :                         feedtable.addRow(nRowsPerSpw);
    3218             : 
    3219             :                         // Prepare row reference object
    3220           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3221             : 
    3222             :                         // Reindex SPW col
    3223           0 :                         spectralWindowId = spw_i;
    3224           0 :                         feedCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3225             : 
    3226             :                         // Columns that can be just copied
    3227           0 :                         feedCols.position().putColumnCells(refRow,position);
    3228           0 :                         feedCols.beamOffset().putColumnCells(refRow,beamOffset);
    3229           0 :                         feedCols.polarizationType().putColumnCells(refRow,polarizationType);
    3230           0 :                         feedCols.polResponse().putColumnCells(refRow,polResponse);
    3231           0 :                         feedCols.receptorAngle().putColumnCells(refRow,receptorAngle);
    3232           0 :                         feedCols.antennaId().putColumnCells(refRow,antennaId);
    3233           0 :                         feedCols.beamId().putColumnCells(refRow,beamId);
    3234           0 :                         feedCols.feedId().putColumnCells(refRow,feedId);
    3235           0 :                         feedCols.interval().putColumnCells(refRow,interval);
    3236           0 :                         feedCols.numReceptors().putColumnCells(refRow,numReceptors);
    3237           0 :                         feedCols.time().putColumnCells(refRow,time);
    3238             : 
    3239             :                                 // Optional columns
    3240           0 :                         if (MSTransformDataHandler::columnOk(feedCols.focusLength()))
    3241             :                                 {
    3242           0 :                                         feedCols.focusLength().putColumnCells(refRow,focusLength);
    3243             :                                 }
    3244             : 
    3245           0 :                         if (MSTransformDataHandler::columnOk(feedCols.phasedFeedId()))
    3246             :                                 {
    3247           0 :                                         feedCols.phasedFeedId().putColumnCells(refRow,phasedFeedId);
    3248             :                                 }
    3249             : 
    3250             :                         // Increment row offset
    3251           0 :                         rowIndex += nRowsPerSpw;
    3252           0 :                     }
    3253             : 
    3254           0 :                 }
    3255             :         else
    3256             :         {
    3257           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3258           0 :                                 << "FEED sub-table found but has no valid content" << LogIO::POST;
    3259             :         }
    3260           0 :     }
    3261             :     else
    3262             :     {
    3263           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3264           0 :                         << "FEED sub-table not found " << LogIO::POST;
    3265             :     }
    3266             : 
    3267           0 :         return;
    3268             : }
    3269             : 
    3270             : // -----------------------------------------------------------------------
    3271             : //
    3272             : // -----------------------------------------------------------------------
    3273           0 : void MSTransformManager::separateSourceSubtable()
    3274             : {
    3275           0 :         if (Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
    3276             :         {
    3277             :                 // Access Source sub-table
    3278           0 :                 MSSource sourcetable = outputMs_p->source();
    3279             : 
    3280           0 :                 if (sourcetable.nrow() > 0)
    3281             :                 {
    3282           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3283           0 :                                 << " Multiplexing SOURCE sub-table to take into account new SPWs " << LogIO::POST;
    3284             : 
    3285           0 :                         MSSourceColumns sourceCols(sourcetable);
    3286             : 
    3287             :                     // Get original content from columns
    3288           0 :                         Array<Double> direction = sourceCols.direction().getColumn();
    3289           0 :                         Array<Double> properMotion = sourceCols.properMotion().getColumn();
    3290           0 :                         Array<Int> calibrationGroup = sourceCols.calibrationGroup().getColumn();
    3291           0 :                         Array<String> code = sourceCols.code().getColumn();
    3292           0 :                         Array<Double> interval = sourceCols.interval().getColumn();
    3293           0 :                         Array<String> name = sourceCols.name().getColumn();
    3294           0 :                         Array<Int> numLines = sourceCols.numLines().getColumn();
    3295           0 :                         Array<Int> sourceId = sourceCols.sourceId().getColumn();
    3296           0 :                         Array<Int> spectralWindowId = sourceCols.spectralWindowId().getColumn();
    3297           0 :                         Array<Double> time = sourceCols.time().getColumn();
    3298             : 
    3299             :                         // Optional columns
    3300           0 :                         Array<Double> position;
    3301           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.position()))
    3302             :                         {
    3303           0 :                                 position = sourceCols.position().getColumn();
    3304             :                         }
    3305             : 
    3306           0 :                         Array<String> transition;
    3307           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.transition()))
    3308             :                         {
    3309           0 :                                 transition = sourceCols.transition().getColumn();
    3310             :                         }
    3311             : 
    3312           0 :                         Array<Double> restFrequency;
    3313           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
    3314             :                         {
    3315           0 :                                 restFrequency = sourceCols.restFrequency().getColumn();
    3316             :                         }
    3317             : 
    3318           0 :                         Array<Double> sysvel;
    3319           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
    3320             :                         {
    3321           0 :                                 sysvel = sourceCols.sysvel().getColumn();
    3322             :                         }
    3323             : 
    3324           0 :                         Array<Int> pulsarId;
    3325           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
    3326             :                         {
    3327           0 :                                 pulsarId = sourceCols.pulsarId().getColumn();
    3328             :                         }
    3329             : 
    3330           0 :                         Array<TableRecord> sourceModel;
    3331           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
    3332             :                         {
    3333           0 :                                 sourceModel = sourceCols.sourceModel().getColumn();
    3334             :                         }
    3335             : 
    3336             : 
    3337           0 :                         auto nRowsPerSpw = sourceCols.spectralWindowId().nrow();
    3338           0 :                     auto rowIndex = nRowsPerSpw;
    3339           0 :                     for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3340             :                     {
    3341             :                         // Add rows
    3342           0 :                         sourcetable.addRow(nRowsPerSpw);
    3343             : 
    3344             :                         // Prepare row reference object
    3345           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3346             : 
    3347             :                         // Re-index SPW col
    3348           0 :                         spectralWindowId = spw_i;
    3349           0 :                         sourceCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3350             : 
    3351             :                         // Columns that can be just copied
    3352           0 :                         sourceCols.direction().putColumnCells(refRow,direction);
    3353           0 :                         sourceCols.properMotion().putColumnCells(refRow,properMotion);
    3354           0 :                         sourceCols.calibrationGroup().putColumnCells(refRow,calibrationGroup);
    3355           0 :                         sourceCols.code().putColumnCells(refRow,code);
    3356           0 :                         sourceCols.interval().putColumnCells(refRow,interval);
    3357           0 :                         sourceCols.name().putColumnCells(refRow,name);
    3358           0 :                         sourceCols.numLines().putColumnCells(refRow,numLines);
    3359           0 :                         sourceCols.sourceId().putColumnCells(refRow,sourceId);
    3360           0 :                         sourceCols.time().putColumnCells(refRow,time);
    3361             : 
    3362             :                         // Optional columns
    3363           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.position()))
    3364             :                         {
    3365           0 :                                 sourceCols.position().putColumnCells(refRow,position);
    3366             :                         }
    3367             : 
    3368           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.transition()))
    3369             :                         {
    3370           0 :                                 sourceCols.transition().putColumnCells(refRow,transition);
    3371             :                         }
    3372             : 
    3373           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.restFrequency()))
    3374             :                         {
    3375           0 :                                 sourceCols.restFrequency().putColumnCells(refRow,restFrequency);
    3376             :                         }
    3377             : 
    3378           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.sysvel()))
    3379             :                         {
    3380           0 :                                 sourceCols.sysvel().putColumnCells(refRow,sysvel);
    3381             :                         }
    3382             : 
    3383           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.pulsarId()))
    3384             :                         {
    3385           0 :                                 sourceCols.pulsarId().putColumnCells(refRow,pulsarId);
    3386             :                         }
    3387             : 
    3388           0 :                         if (MSTransformDataHandler::columnOk(sourceCols.sourceModel()))
    3389             :                         {
    3390           0 :                                 sourceCols.sourceModel().putColumnCells(refRow,sourceModel);
    3391             :                         }
    3392             : 
    3393             :                         // Increment row offset
    3394           0 :                         rowIndex += nRowsPerSpw;
    3395           0 :                     }
    3396             : 
    3397           0 :                 }
    3398             :         else
    3399             :         {
    3400           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3401           0 :                                 << "SOURCE sub-table found but has no valid content" << LogIO::POST;
    3402             :         }
    3403           0 :     }
    3404             :     else
    3405             :     {
    3406           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    3407           0 :                         << "SOURCE sub-table not found " << LogIO::POST;
    3408             :     }
    3409             : 
    3410           0 :         return;
    3411             : }
    3412             : 
    3413             : // -----------------------------------------------------------------------
    3414             : //
    3415             : // -----------------------------------------------------------------------
    3416           0 : void MSTransformManager::separateSyscalSubtable()
    3417             : {
    3418             : 
    3419           0 :     if (Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
    3420             :     {
    3421             :         // Access SysCal sub-table
    3422           0 :         MSSysCal syscalTable = outputMs_p->sysCal();
    3423             : 
    3424           0 :         if (syscalTable.nrow() > 0)
    3425             :         {
    3426           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3427           0 :                                 << " Multiplexing SYSCAL sub-table to take into account new SPWs " << LogIO::POST;
    3428             : 
    3429           0 :                 MSSysCalColumns syscalCols(syscalTable);
    3430             : 
    3431             :                         // Get original content from columns
    3432           0 :                         Array<Int> antennaId = syscalCols.antennaId().getColumn();
    3433           0 :                         Array<Int> feedId = syscalCols.feedId().getColumn();
    3434           0 :                         Array<Double> interval = syscalCols.interval().getColumn();
    3435           0 :                         Array<Int> spectralWindowId = syscalCols.spectralWindowId().getColumn();
    3436           0 :                         Array<Double> time = syscalCols.time().getColumn();
    3437             : 
    3438             :                         // Optional columns
    3439           0 :                         Array<Float> phaseDiff;
    3440           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
    3441             :                         {
    3442           0 :                                 phaseDiff = syscalCols.phaseDiff().getColumn();
    3443             :                         }
    3444             : 
    3445           0 :                         Array<bool> phaseDiffFlag;
    3446           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
    3447             :                         {
    3448           0 :                                 phaseDiffFlag = syscalCols.phaseDiffFlag().getColumn();
    3449             :                         }
    3450             : 
    3451           0 :                         Array<Float> tant;
    3452           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tant()))
    3453             :                         {
    3454           0 :                                 tant = syscalCols.tant().getColumn();
    3455             :                         }
    3456             : 
    3457           0 :                         Array<bool> tantFlag;
    3458           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
    3459             :                         {
    3460           0 :                                 tantFlag = syscalCols.tantFlag().getColumn();
    3461             :                         }
    3462             : 
    3463           0 :                         Array<Float> tantSpectrum;
    3464           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
    3465             :                         {
    3466           0 :                                 tantSpectrum = syscalCols.tantSpectrum().getColumn();
    3467             :                         }
    3468             : 
    3469           0 :                         Array<Float> tantTsys;
    3470           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
    3471             :                         {
    3472           0 :                                 tantTsys = syscalCols.tantTsys().getColumn();
    3473             :                         }
    3474             : 
    3475           0 :                         Array<bool> tantTsysFlag;
    3476           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
    3477             :                         {
    3478           0 :                                 tantTsysFlag = syscalCols.tantTsysFlag().getColumn();
    3479             :                         }
    3480             : 
    3481           0 :                         Array<Float> tantTsysSpectrum;
    3482           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
    3483             :                         {
    3484           0 :                                 tantTsysSpectrum = syscalCols.tantTsysSpectrum().getColumn();
    3485             :                         }
    3486             : 
    3487           0 :                         Array<Float> tcal;
    3488           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
    3489             :                         {
    3490           0 :                                 tcal = syscalCols.tcal().getColumn();
    3491             :                         }
    3492             : 
    3493           0 :                         Array<bool> tcalFlag;
    3494           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
    3495             :                         {
    3496           0 :                                 tcalFlag = syscalCols.tcalFlag().getColumn();
    3497             :                         }
    3498             : 
    3499           0 :                         Array<Float> tcalSpectrum;
    3500           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
    3501             :                         {
    3502           0 :                                 tcalSpectrum = syscalCols.tcalSpectrum().getColumn();
    3503             :                         }
    3504             : 
    3505           0 :                         Array<Float> trx;
    3506           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.trx()))
    3507             :                         {
    3508           0 :                                 trx = syscalCols.trx().getColumn();
    3509             :                         }
    3510             : 
    3511           0 :                         Array<bool> trxFlag;
    3512           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
    3513             :                         {
    3514           0 :                                 trxFlag = syscalCols.trxFlag().getColumn();
    3515             :                         }
    3516             : 
    3517           0 :                         Array<Float> trxSpectrum;
    3518           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
    3519             :                         {
    3520           0 :                                 trxSpectrum = syscalCols.trxSpectrum().getColumn();
    3521             :                         }
    3522             : 
    3523           0 :                         Array<Float> tsky;
    3524           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
    3525             :                         {
    3526           0 :                                 tsky = syscalCols.tsky().getColumn();
    3527             :                         }
    3528             : 
    3529           0 :                         Array<bool> tskyFlag;
    3530           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
    3531             :                         {
    3532           0 :                                 tskyFlag = syscalCols.tskyFlag().getColumn();
    3533             :                         }
    3534             : 
    3535           0 :                         Array<Float> tskySpectrum;
    3536           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
    3537             :                         {
    3538           0 :                                 tskySpectrum = syscalCols.tskySpectrum().getColumn();
    3539             :                         }
    3540             : 
    3541           0 :                         Array<Float> tsys;
    3542           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
    3543             :                         {
    3544           0 :                                 tsys = syscalCols.tsys().getColumn();
    3545             :                         }
    3546             : 
    3547           0 :                         Array<bool> tsysFlag;
    3548           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
    3549             :                         {
    3550           0 :                                 tsysFlag = syscalCols.tsysFlag().getColumn();
    3551             :                         }
    3552             : 
    3553           0 :                         Array<Float> tsysSpectrum;
    3554           0 :                         if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
    3555             :                         {
    3556           0 :                                 tsysSpectrum = syscalCols.tsysSpectrum().getColumn();
    3557             :                         }
    3558             : 
    3559             : 
    3560           0 :                         auto nRowsPerSpw = syscalCols.spectralWindowId().nrow();
    3561           0 :                         auto rowIndex = nRowsPerSpw;
    3562           0 :                         for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3563             :                         {
    3564             :                                 // Add rows
    3565           0 :                                 syscalTable.addRow(nRowsPerSpw);
    3566             : 
    3567             :                                 // Prepare row reference object
    3568           0 :                                 RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3569             : 
    3570             :                                 // Re-index SPW col
    3571           0 :                                 spectralWindowId = spw_i;
    3572           0 :                                 syscalCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3573             : 
    3574             :                                 // Columns that can be just copied
    3575           0 :                                 syscalCols.antennaId().putColumnCells(refRow,antennaId);
    3576           0 :                                 syscalCols.feedId().putColumnCells(refRow,feedId);
    3577           0 :                                 syscalCols.interval().putColumnCells(refRow,interval);
    3578           0 :                                 syscalCols.time().putColumnCells(refRow,time);
    3579             : 
    3580             :                                 // Optional columns
    3581           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.phaseDiff()))
    3582             :                                 {
    3583           0 :                                         syscalCols.phaseDiff().putColumnCells(refRow,phaseDiff);
    3584             :                                 }
    3585             : 
    3586           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.phaseDiffFlag()))
    3587             :                                 {
    3588           0 :                                         syscalCols.phaseDiffFlag().putColumnCells(refRow,phaseDiffFlag);
    3589             :                                 }
    3590             : 
    3591           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tant()))
    3592             :                                 {
    3593           0 :                                         syscalCols.tant().putColumnCells(refRow,tant);
    3594             :                                 }
    3595             : 
    3596           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantFlag()))
    3597             :                                 {
    3598           0 :                                         syscalCols.tantFlag().putColumnCells(refRow,tantFlag);
    3599             :                                 }
    3600             : 
    3601           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantSpectrum()))
    3602             :                                 {
    3603           0 :                                         syscalCols.tantSpectrum().putColumnCells(refRow,tantSpectrum);
    3604             :                                 }
    3605             : 
    3606           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsys()))
    3607             :                                 {
    3608           0 :                                         syscalCols.tantTsys().putColumnCells(refRow,tantTsys);
    3609             :                                 }
    3610             : 
    3611           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsysFlag()))
    3612             :                                 {
    3613           0 :                                         syscalCols.tantTsysFlag().putColumnCells(refRow,tantTsysFlag);
    3614             :                                 }
    3615             : 
    3616           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tantTsysSpectrum()))
    3617             :                                 {
    3618           0 :                                         syscalCols.tantTsysSpectrum().putColumnCells(refRow,tantTsysSpectrum);
    3619             :                                 }
    3620             : 
    3621           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcal()))
    3622             :                                 {
    3623           0 :                                         syscalCols.tcal().putColumnCells(refRow,tcal);
    3624             :                                 }
    3625             : 
    3626           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcalFlag()))
    3627             :                                 {
    3628           0 :                                         syscalCols.tcalFlag().putColumnCells(refRow,tcalFlag);
    3629             :                                 }
    3630             : 
    3631           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tcalSpectrum()))
    3632             :                                 {
    3633           0 :                                         syscalCols.tcalSpectrum().putColumnCells(refRow,tcalSpectrum);
    3634             :                                 }
    3635             : 
    3636           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trx()))
    3637             :                                 {
    3638           0 :                                         syscalCols.trx().putColumnCells(refRow,trx);
    3639             :                                 }
    3640             : 
    3641           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trxFlag()))
    3642             :                                 {
    3643           0 :                                         syscalCols.trxFlag().putColumnCells(refRow,trxFlag);
    3644             :                                 }
    3645             : 
    3646           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.trxSpectrum()))
    3647             :                                 {
    3648           0 :                                         syscalCols.trxSpectrum().putColumnCells(refRow,trxSpectrum);
    3649             :                                 }
    3650             : 
    3651           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsky()))
    3652             :                                 {
    3653           0 :                                         syscalCols.tsky().putColumnCells(refRow,tsky);
    3654             :                                 }
    3655             : 
    3656           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tskyFlag()))
    3657             :                                 {
    3658           0 :                                         syscalCols.tskyFlag().putColumnCells(refRow,tskyFlag);
    3659             :                                 }
    3660             : 
    3661           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tskySpectrum()))
    3662             :                                 {
    3663           0 :                                         syscalCols.tskySpectrum().putColumnCells(refRow,tskySpectrum);
    3664             :                                 }
    3665             : 
    3666           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsys()))
    3667             :                                 {
    3668           0 :                                         syscalCols.tsys().putColumnCells(refRow,tsys);
    3669             :                                 }
    3670             : 
    3671           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsysFlag()))
    3672             :                                 {
    3673           0 :                                         syscalCols.tsysFlag().putColumnCells(refRow,tsysFlag);
    3674             :                                 }
    3675             : 
    3676           0 :                                 if (MSTransformDataHandler::columnOk(syscalCols.tsysSpectrum()))
    3677             :                                 {
    3678           0 :                                         syscalCols.tsysSpectrum().putColumnCells(refRow,tsysSpectrum);
    3679             :                                 }
    3680             : 
    3681             :                                 // Increment row offset
    3682           0 :                                 rowIndex += nRowsPerSpw;
    3683           0 :                         }
    3684             : 
    3685           0 :         }
    3686             :         else
    3687             :         {
    3688           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3689           0 :                                 << "SYSCAL sub-table found but has no valid content" << LogIO::POST;
    3690             :         }
    3691           0 :     }
    3692             :     else
    3693             :     {
    3694           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3695           0 :                         << "SYSCAL sub-table not found " << LogIO::POST;
    3696             :     }
    3697             : 
    3698           0 :         return;
    3699             : }
    3700             : 
    3701             : // -----------------------------------------------------------------------
    3702             : //
    3703             : // -----------------------------------------------------------------------
    3704           0 : void MSTransformManager::separateFreqOffsetSubtable()
    3705             : {
    3706             : 
    3707           0 :     if (Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
    3708             :     {
    3709             :         // Access SysCal sub-table
    3710           0 :         MSFreqOffset freqoffsetTable = outputMs_p->freqOffset();
    3711             : 
    3712           0 :         if (freqoffsetTable.nrow() > 0)
    3713             :         {
    3714           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3715           0 :                                                 << " Multiplexing FREQ_OFFSET sub-table to take into account new SPWs " << LogIO::POST;
    3716             : 
    3717           0 :                 MSFreqOffsetColumns freqoffsetCols(freqoffsetTable);
    3718             : 
    3719             :                 // Get original content from columns
    3720           0 :                 Array<Int> antenna1 = freqoffsetCols.antenna1().getColumn();
    3721           0 :                 Array<Int> antenna2 = freqoffsetCols.antenna2().getColumn();
    3722           0 :                 Array<Int> feedId = freqoffsetCols.feedId().getColumn();
    3723           0 :                 Array<Double> interval = freqoffsetCols.interval().getColumn();
    3724           0 :                 Array<Double> offset = freqoffsetCols.offset().getColumn();
    3725           0 :                 Array<Int> spectralWindowId = freqoffsetCols.spectralWindowId().getColumn();
    3726           0 :                 Array<Double> time = freqoffsetCols.time().getColumn();
    3727             : 
    3728             :                 // NOTE (jagonzal): FreqOffset does not have optional columns
    3729             : 
    3730           0 :                 auto nRowsPerSpw = freqoffsetCols.spectralWindowId().nrow();
    3731           0 :                 auto rowIndex = nRowsPerSpw;
    3732           0 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3733             :                 {
    3734             :                         // Add rows
    3735           0 :                         freqoffsetTable.addRow(nRowsPerSpw);
    3736             : 
    3737             :                         // Prepare row reference object
    3738           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3739             : 
    3740             :                         // Re-index SPW col
    3741           0 :                         spectralWindowId = spw_i;
    3742           0 :                         freqoffsetCols.spectralWindowId().putColumnCells(refRow,spectralWindowId);
    3743             : 
    3744             :                         // Columns that can be just copied
    3745           0 :                         freqoffsetCols.antenna1().putColumnCells(refRow,antenna1);
    3746           0 :                         freqoffsetCols.antenna2().putColumnCells(refRow,antenna2);
    3747           0 :                         freqoffsetCols.feedId().putColumnCells(refRow,feedId);
    3748           0 :                         freqoffsetCols.interval().putColumnCells(refRow,interval);
    3749           0 :                         freqoffsetCols.offset().putColumnCells(refRow,offset);
    3750           0 :                         freqoffsetCols.time().putColumnCells(refRow,time);
    3751             : 
    3752             :                         // Increment row offset
    3753           0 :                         rowIndex += nRowsPerSpw;
    3754           0 :                 }
    3755             : 
    3756           0 :         }
    3757             :         else
    3758             :         {
    3759           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3760           0 :                                 << "FREQ_OFFSET sub-table found but has no valid content" << LogIO::POST;
    3761             :         }
    3762           0 :     }
    3763             :     else
    3764             :     {
    3765           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3766           0 :                         << "FREQ_OFFSET sub-table not found " << LogIO::POST;
    3767             :     }
    3768             : 
    3769           0 :         return;
    3770             : }
    3771             : 
    3772             : // -----------------------------------------------------------------------
    3773             : //
    3774             : // -----------------------------------------------------------------------
    3775           0 : void MSTransformManager::separateCalDeviceSubtable()
    3776             : {
    3777           0 :         if (Table::isReadable(outputMs_p->tableName() + "/CALDEVICE"))
    3778             :         {
    3779           0 :                 Table subtable(outputMs_p->tableName() + "/CALDEVICE", Table::Update);
    3780             : 
    3781           0 :                 if (subtable.nrow() > 0)
    3782             :                 {
    3783           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3784           0 :                                 << " Multiplexing CALDEVICE sub-table to take into account new SPWs " << LogIO::POST;
    3785             : 
    3786             :                 // Get RW access to columns
    3787           0 :                         ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
    3788           0 :                         ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
    3789           0 :                         ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
    3790           0 :                         ScalarColumn<Double> timeCol(subtable, "TIME");
    3791           0 :                         ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
    3792           0 :                         ScalarColumn<Int> numCalLoadCol(subtable, "NUM_CAL_LOAD");
    3793           0 :                         ArrayColumn<String> calLoadNamesCol(subtable, "CAL_LOAD_NAMES");
    3794           0 :                         ScalarColumn<Int> numReceptorCol(subtable, "NUM_RECEPTOR");
    3795           0 :                         ArrayColumn<Float> noiseCalCol(subtable, "NOISE_CAL");
    3796           0 :                         ArrayColumn<Float> calEffCol(subtable, "CAL_EFF");
    3797           0 :                         ArrayColumn<Double> temperatureLoadCol(subtable, "TEMPERATURE_LOAD");
    3798             : 
    3799             :                 // Get original content of columns
    3800           0 :                         Array<Int> antennaId;
    3801           0 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3802           0 :                                 antennaId = antennaIdCol.getColumn();
    3803           0 :                         Array<Int> feedId;
    3804           0 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3805           0 :                                 feedId = feedIdCol.getColumn();
    3806           0 :                         Array<Int> spectralWindowId;
    3807           0 :                         if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
    3808           0 :                                 spectralWindowId = spectralWindowIdCol.getColumn();
    3809           0 :                         Array<Double> time;
    3810           0 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3811           0 :                                 time = timeCol.getColumn();
    3812           0 :                         Array<Double> interval;
    3813           0 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3814           0 :                                 interval = intervalCol.getColumn();
    3815             : 
    3816           0 :                         Array<Int> numCalLoad;
    3817           0 :                         if (MSTransformDataHandler::columnOk(numCalLoadCol))
    3818           0 :                                 numCalLoad = numCalLoadCol.getColumn();
    3819           0 :                         Array<String> calLoadNames;
    3820           0 :                         if (MSTransformDataHandler::columnOk(calLoadNamesCol))
    3821           0 :                                 calLoadNames = calLoadNamesCol.getColumn();
    3822           0 :                         Array<Int> numReceptor;
    3823           0 :                         if (MSTransformDataHandler::columnOk(numReceptorCol))
    3824           0 :                                 numReceptor = numReceptorCol.getColumn();
    3825           0 :                         Array<Float> noiseCal;
    3826           0 :                         if (MSTransformDataHandler::columnOk(noiseCalCol))
    3827           0 :                                 noiseCal = noiseCalCol.getColumn();
    3828           0 :                         Array<Float> calEff;
    3829           0 :                         if (MSTransformDataHandler::columnOk(calEffCol))
    3830           0 :                                 calEff = calEffCol.getColumn();
    3831           0 :                         Array<Double> temperatureLoad;
    3832           0 :                         if (MSTransformDataHandler::columnOk(temperatureLoadCol))
    3833           0 :                                 temperatureLoad = temperatureLoadCol.getColumn();
    3834             : 
    3835             : 
    3836           0 :                 uInt nRowsPerSpw = spectralWindowId.nelements();
    3837           0 :                 uInt rowIndex = nRowsPerSpw;
    3838           0 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3839             :                 {
    3840             :                         // Add rows
    3841           0 :                         subtable.addRow(nRowsPerSpw);
    3842             : 
    3843             :                         // Prepare row reference object
    3844           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3845             : 
    3846             :                         // Re-index SPW col
    3847           0 :                         spectralWindowId = spw_i;
    3848           0 :                         spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
    3849             : 
    3850             :                         // Columns that can be just copied
    3851           0 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3852           0 :                                 antennaIdCol.putColumnCells(refRow,antennaId);
    3853           0 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3854           0 :                                 feedIdCol.putColumnCells(refRow,feedId);
    3855           0 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3856           0 :                                 timeCol.putColumnCells(refRow,time);
    3857           0 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3858           0 :                                 intervalCol.putColumnCells(refRow,interval);
    3859             : 
    3860           0 :                         if (MSTransformDataHandler::columnOk(numCalLoadCol))
    3861           0 :                                 numCalLoadCol.putColumnCells(refRow,numCalLoad);
    3862           0 :                         if (MSTransformDataHandler::columnOk(calLoadNamesCol))
    3863           0 :                                 calLoadNamesCol.putColumnCells(refRow,calLoadNames);
    3864           0 :                         if (MSTransformDataHandler::columnOk(numReceptorCol))
    3865           0 :                                 numReceptorCol.putColumnCells(refRow,numReceptor);
    3866           0 :                         if (MSTransformDataHandler::columnOk(noiseCalCol))
    3867           0 :                                 noiseCalCol.putColumnCells(refRow,noiseCal);
    3868           0 :                         if (MSTransformDataHandler::columnOk(calEffCol))
    3869           0 :                                 calEffCol.putColumnCells(refRow,calEff);
    3870           0 :                         if (MSTransformDataHandler::columnOk(temperatureLoadCol))
    3871           0 :                                 temperatureLoadCol.putColumnCells(refRow,temperatureLoad);
    3872             : 
    3873             :                         // Increment row offset
    3874           0 :                         rowIndex += nRowsPerSpw;
    3875           0 :                 }
    3876             : 
    3877           0 :                 }
    3878             :                 else
    3879             :                 {
    3880           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3881           0 :                                 << "CALDEVICE sub-table found but has no valid content" << LogIO::POST;
    3882             :                 }
    3883           0 :         }
    3884             :         else
    3885             :         {
    3886           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3887           0 :                         << "CALDEVICE sub-table not found." << LogIO::POST;
    3888             :         }
    3889             : 
    3890           0 :         return;
    3891             : }
    3892             : 
    3893             : // -----------------------------------------------------------------------
    3894             : //
    3895             : // -----------------------------------------------------------------------
    3896           0 : void MSTransformManager::separateSysPowerSubtable()
    3897             : {
    3898           0 :         if (Table::isReadable(outputMs_p->tableName() + "/SYSPOWER"))
    3899             :         {
    3900           0 :                 Table subtable(outputMs_p->tableName() + "/SYSPOWER", Table::Update);
    3901             : 
    3902           0 :                 if (subtable.nrow() > 0)
    3903             :                 {
    3904           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    3905           0 :                                 << " Multiplexing SYSPOWER sub-table to take into account new SPWs " << LogIO::POST;
    3906             : 
    3907             :                 // Get RW access to columns
    3908           0 :                         ScalarColumn<Int> antennaIdCol(subtable, "ANTENNA_ID");
    3909           0 :                         ScalarColumn<Int> feedIdCol(subtable, "FEED_ID");
    3910           0 :                         ScalarColumn<Int> spectralWindowIdCol(subtable, "SPECTRAL_WINDOW_ID");
    3911           0 :                         ScalarColumn<Double> timeCol(subtable, "TIME");
    3912           0 :                         ScalarColumn<Double> intervalCol(subtable, "INTERVAL");
    3913           0 :                         ArrayColumn<Float> switchedDiffCol(subtable, "SWITCHED_DIFF");
    3914           0 :                         ArrayColumn<Float> switchedSumCol(subtable, "SWITCHED_SUM");
    3915           0 :                         ArrayColumn<Float> requantizerGainCol(subtable, "REQUANTIZER_GAIN");
    3916             : 
    3917             :                 // Get original content of columns
    3918           0 :                         Array<Int> antennaId;
    3919           0 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3920           0 :                                 antennaId = antennaIdCol.getColumn();
    3921           0 :                         Array<Int> feedId;
    3922           0 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3923           0 :                                 feedId = feedIdCol.getColumn();
    3924           0 :                         Array<Int> spectralWindowId;
    3925           0 :                         if (MSTransformDataHandler::columnOk(spectralWindowIdCol))
    3926           0 :                                 spectralWindowId = spectralWindowIdCol.getColumn();
    3927           0 :                         Array<Double> time;
    3928           0 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3929           0 :                                 time = timeCol.getColumn();
    3930           0 :                         Array<Double> interval;
    3931           0 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3932           0 :                                 interval = intervalCol.getColumn();
    3933             : 
    3934           0 :                         Array<Float> switchedDiff;
    3935           0 :                         if (MSTransformDataHandler::columnOk(switchedDiffCol))
    3936           0 :                                 switchedDiff = switchedDiffCol.getColumn();
    3937           0 :                         Array<Float> switchedSum;
    3938           0 :                         if (MSTransformDataHandler::columnOk(switchedSumCol))
    3939           0 :                                 switchedSum = switchedSumCol.getColumn();
    3940           0 :                         Array<Float> requantizerGain;
    3941           0 :                         if (MSTransformDataHandler::columnOk(requantizerGainCol))
    3942           0 :                                 requantizerGain = requantizerGainCol.getColumn();
    3943             : 
    3944           0 :                 auto nRowsPerSpw = spectralWindowId.nelements();
    3945           0 :                 auto rowIndex = nRowsPerSpw;
    3946           0 :                 for (uInt spw_i=1; spw_i<nspws_p; spw_i++)
    3947             :                 {
    3948             :                         // Add rows
    3949           0 :                         subtable.addRow(nRowsPerSpw);
    3950             : 
    3951             :                         // Prepare row reference object
    3952           0 :                         RefRows refRow(rowIndex,rowIndex+nRowsPerSpw-1);
    3953             : 
    3954             :                         // Re-index SPW col
    3955           0 :                         spectralWindowId = spw_i;
    3956           0 :                         spectralWindowIdCol.putColumnCells(refRow,spectralWindowId);
    3957             : 
    3958             :                         // Columns that can be just copied
    3959           0 :                         if (MSTransformDataHandler::columnOk(antennaIdCol))
    3960           0 :                                 antennaIdCol.putColumnCells(refRow,antennaId);
    3961           0 :                         if (MSTransformDataHandler::columnOk(feedIdCol))
    3962           0 :                                 feedIdCol.putColumnCells(refRow,feedId);
    3963           0 :                         if (MSTransformDataHandler::columnOk(timeCol))
    3964           0 :                                 timeCol.putColumnCells(refRow,time);
    3965           0 :                         if (MSTransformDataHandler::columnOk(intervalCol))
    3966           0 :                                 intervalCol.putColumnCells(refRow,interval);
    3967             : 
    3968           0 :                         if (MSTransformDataHandler::columnOk(switchedDiffCol))
    3969           0 :                                         switchedDiffCol.putColumnCells(refRow,switchedDiff);
    3970           0 :                         if (MSTransformDataHandler::columnOk(switchedSumCol))
    3971           0 :                                         switchedSumCol.putColumnCells(refRow,switchedSum);
    3972           0 :                         if (MSTransformDataHandler::columnOk(requantizerGainCol))
    3973           0 :                                         requantizerGainCol.putColumnCells(refRow,requantizerGain);
    3974             : 
    3975             :                         // Increment row offset
    3976           0 :                         rowIndex += nRowsPerSpw;
    3977           0 :                 }
    3978             : 
    3979           0 :                 }
    3980             :                 else
    3981             :                 {
    3982           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3983           0 :                                 << "SYSPOWER sub-table found but has no valid content" << LogIO::POST;
    3984             :                 }
    3985           0 :         }
    3986             :         else
    3987             :         {
    3988           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    3989           0 :                         << "SYSPOWER sub-table not found." << LogIO::POST;
    3990             :         }
    3991             : 
    3992           0 :         return;
    3993             : }
    3994             : 
    3995             : // -----------------------------------------------------------------------
    3996             : // Return polarization id corresponding to polarization averaged data (Stokes I)
    3997             : // Append Polarization row if necessary
    3998             : // -----------------------------------------------------------------------
    3999           0 : Int MSTransformManager::getAveragedPolarizationId() {
    4000           0 :   logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
    4001           0 :   MSPolarizationColumns cols(outputMs_p->polarization());
    4002           0 :   Int polId = -1;
    4003           0 :   auto nrow = cols.nrow();
    4004           0 :   for (rownr_t i = 0; i < nrow; ++i) {
    4005           0 :     auto const numCorr = cols.numCorr()(i);
    4006           0 :     auto const flagRow = cols.flagRow()(i);
    4007           0 :     if (numCorr == 1 && flagRow == False) {
    4008           0 :       Vector<Int> const corrType = cols.corrType()(i);
    4009           0 :       Int const corrType0 = corrType[0];
    4010           0 :       if (Stokes::type(corrType0) == Stokes::I) {
    4011           0 :         logger_p << "Matched " << i << LogIO::POST;
    4012           0 :         polId = i;
    4013           0 :         break;
    4014             :       }
    4015           0 :     }
    4016             :   }
    4017             : 
    4018           0 :   if (polId < 0) {
    4019             :     // add new row to PolarizationTable
    4020           0 :     outputMs_p->polarization().addRow(1, False);
    4021           0 :     polId = nrow;
    4022           0 :     Matrix<Int> corrProduct(2, 1, 0);
    4023           0 :     cols.corrProduct().put(polId, corrProduct);
    4024           0 :     Vector<Int> corrType(1, Stokes::I);
    4025           0 :     cols.corrType().put(polId, corrType);
    4026           0 :     cols.flagRow().put(polId, False);
    4027           0 :     cols.numCorr().put(polId, 1);
    4028           0 :   }
    4029             : 
    4030           0 :   return polId;
    4031           0 : }
    4032             : 
    4033             : // -----------------------------------------------------------------------
    4034             : // Re-index POLARIZATION_ID's in DATA_DESCRIPTION table
    4035             : // -----------------------------------------------------------------------
    4036           0 : void MSTransformManager::reindexPolarizationIdInDataDesc(Int newPolarizationId) {
    4037           0 :   logger_p << LogOrigin("MSTransformManager", __func__, WHERE);
    4038           0 :   logger_p << "new polid is " << newPolarizationId << LogIO::POST;
    4039           0 :   MSDataDescColumns ddcols(outputMs_p->dataDescription());
    4040           0 :   MSPolarizationColumns pcols(outputMs_p->polarization());
    4041           0 :   rownr_t nrow = ddcols.nrow();
    4042           0 :   auto __isValidType = [&](Vector<Int> const &ctype) {
    4043           0 :     return (anyEQ(ctype, (Int)Stokes::XX) && anyEQ(ctype, (Int)Stokes::YY))
    4044           0 :       || (anyEQ(ctype, (Int)Stokes::RR) && anyEQ(ctype, (Int)Stokes::LL));
    4045             :   };
    4046           0 :   for (rownr_t i = 0; i < nrow; ++i) {
    4047           0 :     Int const polarizationId = ddcols.polarizationId()(i);
    4048           0 :     Int nCorr = pcols.numCorr()(polarizationId);
    4049           0 :     Vector<Int> corrType = pcols.corrType()(polarizationId);
    4050           0 :     bool flagRow = pcols.flagRow()(polarizationId);
    4051           0 :     bool needReindex = (polarizationId != newPolarizationId) &&
    4052           0 :         (nCorr > 1) && (flagRow == False) && __isValidType(corrType);
    4053           0 :     if (needReindex) {
    4054           0 :       logger_p << "ddid " << i << " polid " << polarizationId << " needs reindex" << LogIO::POST;
    4055           0 :       ddcols.polarizationId().put(i, newPolarizationId);
    4056             :     }
    4057           0 :   }
    4058           0 : }
    4059             : 
    4060             : 
    4061             : // -----------------------------------------------------------------------
    4062             : //
    4063             : // -----------------------------------------------------------------------
    4064           0 : void MSTransformManager::checkAndPreaverageChannelsIfNeeded(Int spwId,
    4065             :                                                             Vector<Double> &inputCHAN_FREQ,
    4066             :                                                             Vector<Double> &inputCHAN_WIDTH,
    4067             : 
    4068             :                                                             const Vector<Double> &originalCHAN_FREQ,
    4069             :                                                             const Vector<Double> &originalCHAN_WIDTH,
    4070             :                                                             const Vector<Double> &regriddedCHAN_FREQ,
    4071             :                                                             const Vector<Double> &regriddedCHAN_WIDTH
    4072             :                                                             ) {
    4073             :   // Check if pre-averaging step is necessary
    4074           0 :   if (freqbinMap_p.find(spwId) == freqbinMap_p.end()) {
    4075             :     Double weightScaleDummy;
    4076           0 :     Vector<Double> tmpCHAN_FREQ;
    4077           0 :     Vector<Double> tmpCHAN_WIDTH;
    4078           0 :     MSTransformRegridder::calcChanFreqs(logger_p, tmpCHAN_FREQ, tmpCHAN_WIDTH,
    4079             :                                         weightScaleDummy, originalCHAN_FREQ,
    4080           0 :                                         originalCHAN_WIDTH, phaseCenter_p,
    4081             :                                         inputReferenceFrame_p,
    4082           0 :                                         referenceTime_p,
    4083           0 :                                         observatoryPosition_p,
    4084           0 :                                         String("channel"), -1,
    4085           0 :                                         String("0"), String("1"),
    4086           0 :                                         restFrequency_p,
    4087           0 :                                         outputReferenceFramePar_p,
    4088           0 :                                         velocityType_p, false // verbose
    4089             :                                         );
    4090             : 
    4091           0 :     Double avgCombinedWidth = 0;
    4092           0 :     for (uInt chanIdx = 0; chanIdx < tmpCHAN_WIDTH.size(); ++chanIdx) {
    4093           0 :       avgCombinedWidth += tmpCHAN_WIDTH(chanIdx);
    4094             :     }
    4095           0 :     avgCombinedWidth /= tmpCHAN_WIDTH.size();
    4096             : 
    4097           0 :     Double avgRegriddedWidth = 0;
    4098           0 :     for (uInt chanIdx=0;chanIdx<regriddedCHAN_WIDTH.size();chanIdx++) {
    4099           0 :       avgRegriddedWidth += regriddedCHAN_WIDTH(chanIdx);
    4100             :     }
    4101           0 :     avgRegriddedWidth /= regriddedCHAN_WIDTH.size();
    4102             : 
    4103           0 :     Double widthFactor = fabs(avgRegriddedWidth/avgCombinedWidth);
    4104           0 :     uInt widthFactorInt =  (uInt)floor(widthFactor + 0.001);
    4105             : 
    4106           0 :     if ((widthFactorInt >= 2) and 2*widthFactorInt <= originalCHAN_WIDTH.size()) {
    4107           0 :       if (!enableChanPreAverage_p) {
    4108           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4109             :                  << "Ratio between input and output width is >=2: " << avgRegriddedWidth/avgCombinedWidth
    4110             :                  << ", but not doing pre-channel average (it is disabled by "
    4111           0 :                  << "default since CASA release 5.0)." << LogIO::POST;
    4112             : 
    4113           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4114             :                  << "Regridding to intermediate grid ("
    4115             :                  << originalCHAN_FREQ.size()
    4116             :                  << " channels) for interpolation as in tclean when the "
    4117             :                  << " ratio between the output and input widths is >2."
    4118           0 :                  << LogIO::POST;
    4119             : 
    4120           0 :         initGridForRegridTClean(originalCHAN_FREQ, regriddedCHAN_FREQ,
    4121             :                                 regriddedCHAN_WIDTH, widthFactor);
    4122             : 
    4123             :       } else {
    4124           0 :         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    4125             :                  << "mstransform with regridms does not regrid properly for channel widths "
    4126             :           "> or = 2 x the native channel width, when using channel pre-averaging. Please "
    4127             :           "use clean or tclean for larger regridding. "
    4128           0 :                  << LogIO::POST;
    4129             : 
    4130           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4131             :                  << "Ratio between input and output width is " << avgRegriddedWidth/avgCombinedWidth
    4132           0 :                  << ", setting pre-channel average width to " << widthFactorInt << LogIO::POST;
    4133             : 
    4134           0 :         doPreAveragingBeforeRegridding(widthFactorInt, spwId,
    4135             :                                        originalCHAN_FREQ, originalCHAN_WIDTH,
    4136             :                                        inputCHAN_FREQ, inputCHAN_WIDTH);
    4137             :       }
    4138             :     }
    4139           0 :   }
    4140           0 : }
    4141             : 
    4142             : // -----------------------------------------------------------------------
    4143             : //
    4144             : // -----------------------------------------------------------------------
    4145           0 : void MSTransformManager::doPreAveragingBeforeRegridding(uInt widthFactor, Int spwId,
    4146             :                                                         const Vector<Double> &originalCHAN_FREQ,
    4147             :                                                         const Vector<Double> &originalCHAN_WIDTH,
    4148             :                                                         Vector<Double> &inputCHAN_FREQ,
    4149             :                                                         Vector<Double> &inputCHAN_WIDTH) {
    4150           0 :   channelAverage_p = true;
    4151           0 :   freqbinMap_p[spwId] = widthFactor;
    4152           0 :   newWeightFactorMap_p[spwId] /= widthFactor; // jagonzal: Remove channel width contribution to the scale factor
    4153             : 
    4154             :   // Calculate averaged frequencies
    4155           0 :   calculateIntermediateFrequencies(spwId, originalCHAN_FREQ, originalCHAN_WIDTH,
    4156             :                                    inputCHAN_FREQ, inputCHAN_WIDTH);
    4157             : 
    4158           0 :   ostringstream oss;
    4159           0 :   oss   << "Averaged SPW: " << std::setw(5) << inputCHAN_WIDTH.size()
    4160             :         << " channels, first channel = "
    4161           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    4162           0 :         << inputCHAN_FREQ(0) << " Hz"
    4163             :         << ", last channel = "
    4164           0 :         << std::setprecision(9) << std::setw(14) << std::scientific
    4165           0 :         << inputCHAN_FREQ(inputCHAN_WIDTH.size() -1) << " Hz";
    4166           0 :   logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4167           0 :            << oss.str() << LogIO::POST;
    4168           0 : }
    4169             : 
    4170             : // -----------------------------------------------------------------------
    4171             : //
    4172             : // -----------------------------------------------------------------------
    4173           0 : void MSTransformManager::calculateIntermediateFrequencies(      Int spwId,
    4174             :                                                                                                                                 const Vector<Double> &inputChanFreq,
    4175             :                                                                                                                                 const Vector<Double> &inputChanWidth,
    4176             :                                                                                                                                 Vector<Double> &intermediateChanFreq,
    4177             :                                                                                                                                 Vector<Double> &intermediateChanWidth)
    4178             : {
    4179           0 :         uInt mumOfInterChan = inputChanFreq.size() / freqbinMap_p[spwId];
    4180           0 :         uInt lastChannelWidth = inputChanFreq.size() % freqbinMap_p[spwId];
    4181           0 :         if (lastChannelWidth > 0)
    4182             :         {
    4183           0 :                 mumOfInterChan += 1;
    4184             :         }
    4185           0 :         numOfCombInputChanMap_p[spwId] = inputChanFreq.size();
    4186           0 :         numOfCombInterChanMap_p[spwId] = mumOfInterChan;
    4187           0 :         intermediateChanFreq.resize(mumOfInterChan,false);
    4188           0 :         intermediateChanWidth.resize(mumOfInterChan,false);
    4189           0 :         simpleAverage(freqbinMap_p[spwId], inputChanFreq, intermediateChanFreq);
    4190           0 :         simpleAverage(freqbinMap_p[spwId], inputChanWidth, intermediateChanWidth);
    4191             : 
    4192           0 :         for (uInt chanIdx=0;chanIdx<mumOfInterChan;chanIdx++)
    4193             :         {
    4194           0 :                 intermediateChanWidth[chanIdx] *= freqbinMap_p[spwId];
    4195             :         }
    4196             : 
    4197           0 :         if (lastChannelWidth > 0)
    4198             :         {
    4199           0 :                 intermediateChanWidth[mumOfInterChan-1] /= freqbinMap_p[spwId];
    4200           0 :                 intermediateChanWidth[mumOfInterChan-1] *= lastChannelWidth;
    4201             :         }
    4202             : 
    4203           0 :     return;
    4204             : }
    4205             : 
    4206             : /**
    4207             :  * Create a fake grid and create a map [input channels] => [output channels]
    4208             :  * from it. This is for the tclean-like interpolation that is applied when
    4209             :  * the width of the output is > 2 x width of the inputs.
    4210             :  *
    4211             :  * Irrespective of channel widths, we want as many channels as in the
    4212             :  * original input, with their (lower) width, but projected/aligned
    4213             :  * with the output grid. As the output grid is fixed based on the
    4214             :  * first row timestamp, this only need to be done once, at init time.
    4215             :  *
    4216             :  * After this method is run, the interpolation methods can use
    4217             :  * regridTCleanChanMap_p to interpolate the tclean way.
    4218             :  *
    4219             :  * @param originalCHAN_FREQ initial input channel frequencies
    4220             :  * @param outCHAN_FREQ final output channel frequencies
    4221             :  * @param outCHAN_WIDTH final output channel widths
    4222             :  * @param widthFactor avg(output_widths) / avg(input_widths)
    4223             :  */
    4224           0 : void MSTransformManager::initGridForRegridTClean(const Vector<Double> &originalCHAN_FREQ,
    4225             :                                                  const Vector<Double> &outCHAN_FREQ,
    4226             :                                                  const Vector<Double> &outCHAN_WIDTH,
    4227             :                                                  Double widthFactor)
    4228             : {
    4229             :   // build grid with widths of the input channels but aligned with the output
    4230             :   // grid
    4231           0 :   regridTCleanCHAN_FREQ_p.resize(originalCHAN_FREQ.size());
    4232           0 :   Vector<Double> regridTCleanCHAN_WIDTH_p;
    4233           0 :   regridTCleanCHAN_WIDTH_p.resize(regridTCleanCHAN_FREQ_p.size());
    4234             : 
    4235           0 :   const auto &outputFreqs = outCHAN_FREQ;
    4236           0 :   bool negativeWidths = outputFreqs[0] > outputFreqs[outputFreqs.size()-1];
    4237             : 
    4238             :   // swap first/last if "negative width" (decreasing frequencies)
    4239           0 :   auto startIdx = negativeWidths ? (outCHAN_FREQ.size() -1) : 0;
    4240           0 :   regridTCleanCHAN_FREQ_p[0] = outCHAN_FREQ[startIdx] - outCHAN_WIDTH[startIdx]/2.;
    4241           0 :   regridTCleanCHAN_WIDTH_p[0] = outCHAN_WIDTH[startIdx] / widthFactor;
    4242           0 :   Double widthFactorIdx = static_cast<Double>(regridTCleanCHAN_FREQ_p.size()) /
    4243           0 :     outCHAN_FREQ.size();
    4244             : 
    4245           0 :   for (size_t idx = 1; idx < regridTCleanCHAN_FREQ_p.size(); ++idx) {
    4246           0 :     Int outIdx = static_cast<Int>(idx / widthFactorIdx);
    4247           0 :     regridTCleanCHAN_WIDTH_p[idx] = outCHAN_WIDTH[outIdx] / widthFactorIdx;
    4248           0 :     regridTCleanCHAN_FREQ_p[idx] = regridTCleanCHAN_FREQ_p[idx-1] +
    4249           0 :       regridTCleanCHAN_WIDTH_p[idx];
    4250             :   }
    4251             : 
    4252             : 
    4253             :   // Build map from fake input channels => output channels
    4254           0 :   regridTCleanChanMap_p.resize(regridTCleanCHAN_FREQ_p.size());
    4255           0 :   regridTCleanChanMap_p = -1;
    4256           0 :   const auto &intermFreqs = regridTCleanCHAN_FREQ_p;
    4257           0 :   const auto &outputWidths = outCHAN_WIDTH;
    4258           0 :   for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
    4259           0 :     for (uInt outIdx = 0; outIdx < outputFreqs.size(); ++outIdx) {
    4260           0 :       if (intermFreqs[mapIdx] >= outputFreqs[outIdx] - outputWidths[outIdx]/2. and
    4261           0 :           intermFreqs[mapIdx] < outputFreqs[outIdx] + outputWidths[outIdx]/2.) {
    4262           0 :         regridTCleanChanMap_p(mapIdx) = outIdx;
    4263           0 :         break;
    4264             :       }
    4265             :     }
    4266             :   }
    4267           0 :   regridTClean_p = true;
    4268           0 : }
    4269             : 
    4270             : // -----------------------------------------------------------------------
    4271             : // Method to set all the elements of a scalar column to a given value
    4272             : // -----------------------------------------------------------------------
    4273           0 : void MSTransformManager::reindexColumn(ScalarColumn<Int> &inputCol, Int value)
    4274             : {
    4275           0 :         for(rownr_t idx=0; idx<inputCol.nrow(); idx++)
    4276             :         {
    4277           0 :                 inputCol.put(idx,value);
    4278             :         }
    4279             : 
    4280           0 :         return;
    4281             : }
    4282             : 
    4283             : // -----------------------------------------------------------------------
    4284             : // Method to re-index Spectral Window column in Source sub-table
    4285             : // -----------------------------------------------------------------------
    4286           0 : void MSTransformManager::reindexSourceSubTable()
    4287             : {
    4288           0 :     if(Table::isReadable(outputMs_p->sourceTableName()) and !outputMs_p->source().isNull())
    4289             :     {
    4290             : 
    4291           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4292           0 :                         << "Re-indexing SOURCE sub-table" << LogIO::POST;
    4293             : 
    4294             : 
    4295           0 :         MSSource sourceSubtable = outputMs_p->source();
    4296           0 :         MSSourceColumns tableCols(sourceSubtable);
    4297           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4298           0 :         ScalarColumn<Int> sourceId = tableCols.sourceId();
    4299           0 :         reindexColumn(spectralWindowId,0);
    4300             : 
    4301             :         // Remove duplicates
    4302           0 :         std::vector<rownr_t> duplicateIdx;
    4303           0 :         std::vector< std::pair<uInt,uInt> > sourceIdSpwIdMap;
    4304             : 
    4305           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4306             :         {
    4307           0 :                 std::pair<uInt,uInt> sourceIdSpwId = std::make_pair(spectralWindowId(idx),sourceId(idx));
    4308             : 
    4309           0 :                 if (std::find(sourceIdSpwIdMap.begin(),sourceIdSpwIdMap.end(),sourceIdSpwId) != sourceIdSpwIdMap.end())
    4310             :                 {
    4311           0 :                         duplicateIdx.push_back(idx);
    4312             :                 }
    4313             :                 else
    4314             :                 {
    4315           0 :                         sourceIdSpwIdMap.push_back(sourceIdSpwId);
    4316             :                 }
    4317             :         }
    4318             : 
    4319           0 :         sourceSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4320             : 
    4321           0 :     }
    4322             :     else
    4323             :     {
    4324           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4325           0 :                         << "SOURCE sub-table not found " << LogIO::POST;
    4326             :     }
    4327             : 
    4328           0 :     return;
    4329             : }
    4330             : 
    4331             : // -----------------------------------------------------------------------
    4332             : // Method to re-index Spectral Window column in DDI sub-table
    4333             : // -----------------------------------------------------------------------
    4334           0 : void MSTransformManager::reindexDDISubTable()
    4335             : {
    4336           0 :     if(Table::isReadable(outputMs_p->dataDescriptionTableName()) and !outputMs_p->dataDescription().isNull())
    4337             :     {
    4338           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4339           0 :                         << "Re-indexing DDI sub-table" << LogIO::POST;
    4340             : 
    4341             :         // Access DDI sub-table
    4342           0 :         MSDataDescription ddiTable = outputMs_p->dataDescription();
    4343           0 :         MSDataDescColumns ddiCols(ddiTable);
    4344             : 
    4345             :         // Add a new row for each of the separated SPWs
    4346           0 :         uInt rowIndex = 0;
    4347           0 :       for (uInt spw_i=0; spw_i<nspws_p; spw_i++)
    4348             :         {
    4349           0 :                 if (rowIndex > 0)
    4350             :                 {
    4351             :                         // Add row
    4352           0 :                         ddiTable.addRow(1,true);
    4353             : 
    4354             :                     // Copy polID and flagRow from the first original SPW
    4355           0 :                         ddiCols.polarizationId().put(rowIndex,ddiCols.polarizationId()(0));
    4356           0 :                         ddiCols.flagRow().put(rowIndex,ddiCols.flagRow()(0));
    4357             : 
    4358             :                         // Optional columns
    4359           0 :                         if (ddiCols.lagId().isNull()==false and ddiCols.lagId().hasContent()==true)
    4360             :                         {
    4361           0 :                                 ddiCols.lagId().put(rowIndex,ddiCols.lagId()(0));
    4362             :                         }
    4363             :                 }
    4364             : 
    4365             :                 // Set SPW id separately
    4366           0 :                 ddiCols.spectralWindowId().put(rowIndex,ddiStart_p+spw_i);
    4367             : 
    4368           0 :                 rowIndex += 1;
    4369             :         }
    4370             : 
    4371             :         // Delete the old rows
    4372           0 :         rownr_t nrowsToDelete = ddiCols.nrow()-nspws_p;
    4373           0 :         if (nrowsToDelete > 0)
    4374             :         {
    4375           0 :             rownr_t rownr = ddiCols.nrow()-1;
    4376           0 :             Vector<rownr_t> rowsToDelete(nrowsToDelete);
    4377           0 :             for(rownr_t idx=0; idx<nrowsToDelete; idx++)
    4378             :             {
    4379           0 :                 rowsToDelete(idx) = rownr;
    4380           0 :                 rownr -= 1;
    4381             :             }
    4382             : 
    4383           0 :             ddiTable.removeRow(rowsToDelete);
    4384           0 :         }
    4385             : 
    4386             : 
    4387           0 :     }
    4388             :     else
    4389             :     {
    4390           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4391           0 :                         << "DATA_DESCRIPTION sub-table not found " << LogIO::POST;
    4392             :     }
    4393           0 : }
    4394             : 
    4395             : // -----------------------------------------------------------------------
    4396             : // Method to re-index Spectral Window column in Feed sub-table
    4397             : // -----------------------------------------------------------------------
    4398           0 : void MSTransformManager::reindexFeedSubTable()
    4399             : {
    4400           0 :     if(Table::isReadable(outputMs_p->feedTableName()) and !outputMs_p->feed().isNull())
    4401             :     {
    4402           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4403           0 :                         << "Re-indexing FEED sub-table and removing duplicates" << LogIO::POST;
    4404             : 
    4405           0 :         MSFeed feedSubtable = outputMs_p->feed();
    4406           0 :         MSFeedColumns tableCols(feedSubtable);
    4407           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4408           0 :         ScalarColumn<Int> antennaId = tableCols.antennaId();
    4409           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4410           0 :         ScalarColumn<Double> time = tableCols.time();
    4411             : 
    4412             :         // Re-index SPWId to be 0
    4413           0 :         reindexColumn(spectralWindowId,0);
    4414             : 
    4415             :         // Remove duplicates
    4416           0 :         std::vector<rownr_t> duplicateIdx;
    4417           0 :         std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4418           0 :         std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4419             : 
    4420           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4421             :         {
    4422           0 :                 std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4423           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4424             : 
    4425           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4426             :                 {
    4427           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4428             :                         {
    4429           0 :                                 duplicateIdx.push_back(idx);
    4430             :                         }
    4431             :                         else
    4432             :                         {
    4433           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4434             :                         }
    4435             :                 }
    4436             :                 else
    4437             :                 {
    4438           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4439             :                 }
    4440             :         }
    4441             : 
    4442             : 
    4443           0 :         feedSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4444             : 
    4445           0 :     }
    4446             :     else
    4447             :     {
    4448           0 :         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__) <<
    4449           0 :                          "FEED sub-table not found " << LogIO::POST;
    4450             :     }
    4451             : 
    4452           0 :         return;
    4453             : }
    4454             : 
    4455             : // -----------------------------------------------------------------------
    4456             : // Method to re-index Spectral Window column in SysCal sub-table
    4457             : // -----------------------------------------------------------------------
    4458           0 : void MSTransformManager::reindexSysCalSubTable()
    4459             : {
    4460           0 :     if(Table::isReadable(outputMs_p->sysCalTableName()) and !outputMs_p->sysCal().isNull())
    4461             :     {
    4462           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4463           0 :                         << "Re-indexing SYSCAL sub-table and removing duplicates" << LogIO::POST;
    4464             : 
    4465           0 :         MSSysCal syscalSubtable = outputMs_p->sysCal();
    4466           0 :         MSSysCalColumns tableCols(syscalSubtable);
    4467           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4468           0 :         ScalarColumn<Int> antennaId = tableCols.antennaId();
    4469           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4470           0 :         ScalarColumn<Double> time = tableCols.time();
    4471             : 
    4472             :         // Re-index SPWId to be 0
    4473           0 :         reindexColumn(spectralWindowId,0);
    4474             : 
    4475             :         // Remove duplicates
    4476           0 :         std::vector<rownr_t> duplicateIdx;
    4477           0 :         std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4478           0 :         std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4479             : 
    4480           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4481             :         {
    4482           0 :                 std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4483           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4484             : 
    4485           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4486             :                 {
    4487           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4488             :                         {
    4489           0 :                                 duplicateIdx.push_back(idx);
    4490             :                         }
    4491             :                         else
    4492             :                         {
    4493           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4494             :                         }
    4495             :                 }
    4496             :                 else
    4497             :                 {
    4498           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4499             :                 }
    4500             :         }
    4501             : 
    4502           0 :         syscalSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4503             : 
    4504           0 :     }
    4505             :     else
    4506             :     {
    4507           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4508           0 :                         << "SYSCAL sub-table not found " << LogIO::POST;
    4509             :     }
    4510             : 
    4511           0 :         return;
    4512             : }
    4513             : 
    4514             : // -----------------------------------------------------------------------
    4515             : // Method to re-index Spectral Window column in FreqOffset sub-table
    4516             : // -----------------------------------------------------------------------
    4517           0 : void MSTransformManager::reindexFreqOffsetSubTable()
    4518             : {
    4519           0 :     if(Table::isReadable(outputMs_p->freqOffsetTableName()) and !outputMs_p->freqOffset().isNull())
    4520             :     {
    4521           0 :         logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4522           0 :                         << "Re-indexing FREQ_OFFSET sub-table and removing duplicates" << LogIO::POST;
    4523             : 
    4524           0 :         MSFreqOffset freqoffsetSubtable = outputMs_p->freqOffset();
    4525           0 :         MSFreqOffsetColumns tableCols(freqoffsetSubtable);
    4526           0 :         ScalarColumn<Int> feedId = tableCols.feedId();
    4527           0 :         ScalarColumn<Int> antenna1 = tableCols.antenna1();
    4528           0 :         ScalarColumn<Int> antenna2 = tableCols.antenna2();
    4529           0 :         ScalarColumn<Int> spectralWindowId = tableCols.spectralWindowId();
    4530           0 :         ScalarColumn<Double> time = tableCols.time();
    4531             : 
    4532             :         // Re-index SPWId to be 0
    4533           0 :         reindexColumn(spectralWindowId,0);
    4534             : 
    4535             :         // Remove duplicates
    4536           0 :         std::vector<rownr_t> duplicateIdx;
    4537           0 :         std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double > antennaFeedTimeMap;
    4538           0 :         std::map< std::pair < std::pair<uInt,uInt> , uInt> , Double >::iterator antennaFeedTimeIter;
    4539             : 
    4540           0 :         for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4541             :         {
    4542           0 :                 std::pair < std::pair<uInt,uInt> , uInt> antennaFeedPair = std::make_pair(std::make_pair(antenna1(idx),antenna2(idx)),feedId(idx));
    4543           0 :                 antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4544             : 
    4545           0 :                 if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4546             :                 {
    4547           0 :                         if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4548             :                         {
    4549           0 :                                 duplicateIdx.push_back(idx);
    4550             :                         }
    4551             :                         else
    4552             :                         {
    4553           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4554             :                         }
    4555             :                 }
    4556             :                 else
    4557             :                 {
    4558           0 :                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4559             :                 }
    4560             :         }
    4561             : 
    4562           0 :         freqoffsetSubtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4563             : 
    4564           0 :     }
    4565             :     else
    4566             :     {
    4567           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4568           0 :                         << "FREQ_OFFSET sub-table not found " << LogIO::POST;
    4569             :     }
    4570             : 
    4571           0 :     return;
    4572             : }
    4573             : 
    4574             : // -----------------------------------------------------------------------
    4575             : // Method to re-index Spectral Window column in a generic sub-table (with feedId, antennaId and time columns)
    4576             : // -----------------------------------------------------------------------
    4577           0 : void MSTransformManager::reindexGenericTimeDependentSubTable(const String& subtabname)
    4578             : {
    4579           0 :         if (Table::isReadable(outputMs_p->tableName() + "/" + subtabname))
    4580             :         {
    4581           0 :                 Table subtable(outputMs_p->tableName() + "/" + subtabname, Table::Update);
    4582             : 
    4583           0 :                 if (subtable.nrow() > 0)
    4584             :                 {
    4585           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4586             :                                 << "Re-indexing SPW column of " << subtabname
    4587           0 :                                 << " sub-table and removing duplicates " << LogIO::POST;
    4588             : 
    4589           0 :                         ScalarColumn<Int> feedId(subtable, "FEED_ID");
    4590           0 :                         ScalarColumn<Int> antennaId(subtable, "ANTENNA_ID");
    4591           0 :                         ScalarColumn<Int> spectralWindowId(subtable, "SPECTRAL_WINDOW_ID");
    4592           0 :                         ScalarColumn<Double> time(subtable, "TIME");
    4593             : 
    4594             :                 // Re-index SPWId to be 0
    4595           0 :                 reindexColumn(spectralWindowId,0);
    4596             : 
    4597             :                 // Remove duplicates
    4598           0 :                 std::vector<rownr_t> duplicateIdx;
    4599           0 :                 std::map< std::pair<uInt,uInt> , Double > antennaFeedTimeMap;
    4600           0 :                 std::map< std::pair<uInt,uInt> , Double >::iterator antennaFeedTimeIter;
    4601             : 
    4602           0 :                 for (rownr_t idx = 0; idx < spectralWindowId.nrow(); idx++)
    4603             :                 {
    4604           0 :                         std::pair<uInt,uInt> antennaFeedPair = std::make_pair(antennaId(idx),feedId(idx));
    4605           0 :                         antennaFeedTimeIter = antennaFeedTimeMap.find(antennaFeedPair);
    4606             : 
    4607           0 :                         if (antennaFeedTimeIter != antennaFeedTimeMap.end())
    4608             :                         {
    4609           0 :                                 if (abs(antennaFeedTimeIter->second - time(idx)) < 2*FLT_MIN)
    4610             :                                 {
    4611           0 :                                         duplicateIdx.push_back(idx);
    4612             :                                 }
    4613             :                                 else
    4614             :                                 {
    4615           0 :                                         antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4616             :                                 }
    4617             :                         }
    4618             :                         else
    4619             :                         {
    4620           0 :                                 antennaFeedTimeMap[antennaFeedPair] = time(idx);
    4621             :                         }
    4622             :                 }
    4623             : 
    4624           0 :                 subtable.removeRow(Vector<rownr_t>(duplicateIdx.begin(),duplicateIdx.end()));
    4625             : 
    4626           0 :                 }
    4627             :                 else
    4628             :                 {
    4629           0 :                         if (subtabname == casacore::String("FEED"))
    4630             :                         {
    4631           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4632           0 :                                         << subtabname << " sub-table found but has no valid content" << LogIO::POST;
    4633             :                         }
    4634             :                         else
    4635             :                         {
    4636           0 :                         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4637           0 :                                         << subtabname << " sub-table found but has no valid content" << LogIO::POST;
    4638             :                         }
    4639             :                 }
    4640           0 :         }
    4641             :         else
    4642             :         {
    4643           0 :                 if (subtabname == casacore::String("FEED"))
    4644             :                 {
    4645           0 :                 logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4646           0 :                                 << subtabname << " sub-table not found" << LogIO::POST;
    4647             :                 }
    4648             :                 else
    4649             :                 {
    4650           0 :                 logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager", __FUNCTION__)
    4651           0 :                                 << subtabname << " sub-table not found" << LogIO::POST;
    4652             :                 }
    4653             :         }
    4654             : 
    4655           0 :         return;
    4656             : }
    4657             : 
    4658             : // -----------------------------------------------------------------------
    4659             : //
    4660             : // -----------------------------------------------------------------------
    4661          35 : void MSTransformManager::getInputNumberOfChannels()
    4662             : {
    4663             :     // Access spectral window sub-table
    4664          35 :     MSSpectralWindow spwTable = inputMs_p->spectralWindow();
    4665          35 :     auto nInputSpws = spwTable.nrow();
    4666          35 :     MSSpWindowColumns spwCols(spwTable);
    4667          35 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4668             : 
    4669             :     // Get number of output channels per input spw
    4670         116 :     for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4671             :     {
    4672          81 :         numOfInpChanMap_p[spw_idx] = numChanCol(spw_idx);
    4673             :     }
    4674             : 
    4675          70 :     return;
    4676          35 : }
    4677             : 
    4678             : // -----------------------------------------------------------------------
    4679             : //
    4680             : // -----------------------------------------------------------------------
    4681          17 : void MSTransformManager::dropNonUniformWidthChannels()
    4682             : {
    4683             :         // Access spectral window sub-table
    4684          17 :         MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    4685          17 :         auto nInputSpws = spwTable.nrow();
    4686          17 :         MSSpWindowColumns spwCols(spwTable);
    4687          17 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    4688          17 :     ArrayColumn<Double> chanWidthCol = spwCols.chanWidth();
    4689          17 :     ArrayColumn<Double> effectiveBWCol = spwCols.effectiveBW();
    4690          17 :     ArrayColumn<Double> resolutionCol = spwCols.resolution();
    4691          17 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4692          17 :     ScalarColumn<Double> totalBandwidthCol = spwCols.totalBandwidth();
    4693             : 
    4694             :         uInt nChans;
    4695             :         Int spwId;
    4696          36 :         for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4697             :         {
    4698          19 :                 nChans = numChanCol(spw_idx);
    4699          19 :                 Vector<Double> widthVector = chanWidthCol(spw_idx);
    4700             : 
    4701          19 :         if (outputInputSPWIndexMap_p.size()>0)
    4702             :         {
    4703           3 :                 spwId = outputInputSPWIndexMap_p[spw_idx];
    4704             :         }
    4705             :         else
    4706             :         {
    4707          16 :                 spwId = spw_idx;
    4708             :         }
    4709             : 
    4710             :         // Skip this SPW in non-reindex mode
    4711          19 :         if ((!reindex_p) and (numOfSelChanMap_p.find(spwId) == numOfSelChanMap_p.end())) continue;
    4712             : 
    4713             :         //logger_p << dataHandler_p->getDroppedChannelsMap() << LogIO::POST;
    4714             : 
    4715          19 :         if (dataHandler_p->getDroppedChannelsMap().find(spwId) != dataHandler_p->getDroppedChannelsMap().end())
    4716             :         {
    4717           0 :                 vector<Int>::iterator iter;
    4718           0 :                 Double droppedWidth = 0;
    4719           0 :                 vector<Int> &droppedChannels = dataHandler_p->getDroppedChannelsMap()[spwId];
    4720           0 :                 for (iter = droppedChannels.begin(); iter != droppedChannels.end(); iter++)
    4721             :                 {
    4722           0 :                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    4723             :                                                 << "Not enough input channels to populate output channel n# "
    4724           0 :                                                 << *iter << " from SPW " << spwId << "." << endl
    4725             :                                                 << "The channel will be dropped in order to have an uniform grid."
    4726           0 :                                                 << LogIO::POST;
    4727             : 
    4728           0 :                         droppedWidth += widthVector(*iter);
    4729             :                 }
    4730             : 
    4731             :                 // Calculate final number of channels
    4732           0 :                 uInt nChansFinal = nChans-droppedChannels.size();
    4733             : 
    4734           0 :                 if (nChansFinal <= 0)
    4735             :                 {
    4736           0 :                         logger_p        << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    4737             :                                                 << "Channel selection does not allow to produce any output channel with the requested width "
    4738           0 :                                                 << LogIO::POST;
    4739             : 
    4740           0 :                         throw AipsError("Channel selection does not allow to produce any output channel with the requested width ");
    4741             :                 }
    4742             : 
    4743             : 
    4744             : 
    4745           0 :                 numChanCol.put(spw_idx, nChansFinal);
    4746             : 
    4747             :                 // Total BW has to be reduced to account for the dropped channels
    4748           0 :                 totalBandwidthCol.put(spw_idx, totalBandwidthCol(spw_idx)-droppedWidth);
    4749             : 
    4750             :                 // Get current vectors
    4751           0 :                 Vector<Double> effectiveBWVector = effectiveBWCol(spw_idx);
    4752           0 :                 Vector<Double> resolutionVector = resolutionCol(spw_idx);
    4753           0 :                 Vector<Double> frequencyVector = chanFreqCol(spw_idx);
    4754             : 
    4755             :                 // Declare new vectors
    4756           0 :                 Vector<Double> newWidthVector(nChansFinal);
    4757           0 :                 Vector<Double> newEffectiveBWVector(nChansFinal);
    4758           0 :                 Vector<Double> newResolutionVector(nChansFinal);
    4759           0 :                 Vector<Double> newFrequencyVector(nChansFinal);
    4760             : 
    4761             :                 // Create a new frequency vector
    4762           0 :                 uInt finalIdx = 0;
    4763           0 :                 vector<Int>::iterator matchIdx;
    4764           0 :                 for (uInt idx=0;idx < widthVector.size(); idx++)
    4765             :                 {
    4766           0 :                         matchIdx = find (droppedChannels.begin(), droppedChannels.end(), idx);
    4767           0 :                         if (matchIdx == droppedChannels.end() )
    4768             :                         {
    4769           0 :                                 newWidthVector(finalIdx) = widthVector(idx);
    4770           0 :                                 newEffectiveBWVector(finalIdx) = effectiveBWVector(idx);
    4771           0 :                                 newResolutionVector(finalIdx) = resolutionVector(idx);
    4772           0 :                                 newFrequencyVector(finalIdx) = frequencyVector(idx);
    4773           0 :                                 finalIdx ++;
    4774             :                         }
    4775             :                 }
    4776             : 
    4777             :                 // Put new vectors in corresponding columns
    4778           0 :                 chanWidthCol.put(spw_idx, newWidthVector);
    4779           0 :                 effectiveBWCol.put(spw_idx, newEffectiveBWVector);
    4780           0 :                 resolutionCol.put(spw_idx, newResolutionVector);
    4781           0 :                 chanFreqCol.put(spw_idx, newFrequencyVector);
    4782             : 
    4783             :                 // Update output number of channels
    4784           0 :                 if (regridding_p) inputOutputSpwMap_p[spw_idx].second.resize(nChansFinal);
    4785           0 :         }
    4786          19 :         }
    4787             : 
    4788          34 :         return;
    4789          17 : }
    4790             : 
    4791             : 
    4792             : // -----------------------------------------------------------------------
    4793             : //
    4794             : // -----------------------------------------------------------------------
    4795          17 : void MSTransformManager::getOutputNumberOfChannels()
    4796             : {
    4797          17 :         if (regridding_p or combinespws_p)
    4798             :         {
    4799           0 :                 map<uInt,uInt>::iterator iter;
    4800           0 :                 for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4801             :                 {
    4802           0 :                         if (freqbinMap_p.find(iter->first) == freqbinMap_p.end())
    4803             :                         {
    4804             :                                 // When doing only re-gridding, maybe not all SPWs require pre-averaging
    4805           0 :                                 if (not combinespws_p)
    4806             :                                 {
    4807           0 :                                         freqbinMap_p[iter->first] = 1;
    4808             :                                 }
    4809             :                                 // When combining SPWs all of them get the same freqbin
    4810             :                                 else
    4811             :                                 {
    4812           0 :                                         freqbinMap_p[iter->first] = freqbinMap_p[0];
    4813             :                                 }
    4814             :                         }
    4815             :                 }
    4816             :         }
    4817             : 
    4818             :         // Access spectral window sub-table
    4819          17 :         MSSpectralWindow spwTable = outputMs_p->spectralWindow();
    4820          17 :     auto nInputSpws = spwTable.nrow();
    4821          17 :     MSSpWindowColumns spwCols(spwTable);
    4822          17 :     ScalarColumn<Int> numChanCol = spwCols.numChan();
    4823          17 :     ArrayColumn<Double> chanFreqCol = spwCols.chanFreq();
    4824             : 
    4825          17 :     if (combinespws_p)
    4826             :     {
    4827           0 :                 map<uInt,uInt>::iterator iter;
    4828           0 :                 for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4829             :                 {
    4830             :                         // Note: This will truncate the result, but it is ok because we are dropping the last channel
    4831           0 :                         numOfOutChanMap_p[iter->first] = numOfSelChanMap_p[iter->first] / freqbinMap_p[iter->first];
    4832             :                 }
    4833             :     }
    4834             :     else
    4835             :     {
    4836             :             // Get number of output channels per input spw
    4837             :             Int spwId;
    4838          36 :             for(rownr_t spw_idx=0; spw_idx<nInputSpws; spw_idx++)
    4839             :             {
    4840          19 :                 if (outputInputSPWIndexMap_p.size()>0)
    4841             :                 {
    4842           3 :                         spwId = outputInputSPWIndexMap_p[spw_idx];
    4843             :                 }
    4844             :                 else
    4845             :                 {
    4846          16 :                         spwId = spw_idx;
    4847             :                 }
    4848             : 
    4849          19 :                 numOfOutChanMap_p[spwId] = numChanCol(spw_idx);
    4850             :             }
    4851             :     }
    4852             : 
    4853          34 :         return;
    4854          17 : }
    4855             : 
    4856             : // -----------------------------------------------------------------------
    4857             : //
    4858             : // -----------------------------------------------------------------------
    4859           0 : void MSTransformManager::calculateWeightAndSigmaFactors()
    4860             : {
    4861           0 :         map<uInt,uInt>::iterator iter;
    4862           0 :         for(iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4863             :         {
    4864           0 :                 weightFactorMap_p[iter->first] = (Float)numOfSelChanMap_p[iter->first] /
    4865           0 :                                                                                 (Float)numOfInpChanMap_p[iter->first];
    4866           0 :                 sigmaFactorMap_p[iter->first] = 1./sqrt((Float)numOfSelChanMap_p[iter->first] /
    4867           0 :                                                                                 (Float)numOfOutChanMap_p[iter->first]);
    4868             :         }
    4869             : 
    4870           0 :         return;
    4871             : }
    4872             : 
    4873             : // -----------------------------------------------------------------------
    4874             : //
    4875             : // -----------------------------------------------------------------------
    4876          17 : void MSTransformManager::calculateNewWeightAndSigmaFactors()
    4877             : {
    4878             : 
    4879          17 :         map<uInt, uInt>::iterator iter;
    4880          36 :         for (iter = numOfSelChanMap_p.begin(); iter != numOfSelChanMap_p.end(); iter++)
    4881             :         {
    4882             :                 // Populateremaining SPWs of weight factor map
    4883          19 :                 if (newWeightFactorMap_p.find(iter->first)== newWeightFactorMap_p.end())
    4884             :                 {
    4885             :                         // When doing only re-gridding, maybe not all SPWs require pre-averaging
    4886           0 :                         if (not combinespws_p)
    4887             :                         {
    4888           0 :                                 newWeightFactorMap_p[iter->first] = 1;
    4889             :                         }
    4890             :                         // When combining SPWs all of them get the same freqbin
    4891             :                         else
    4892             :                         {
    4893           0 :                                 newWeightFactorMap_p[iter->first] = newWeightFactorMap_p[0];
    4894             :                         }
    4895             :                 }
    4896             : 
    4897             :                 // Populate sigma factor map
    4898          19 :                 newSigmaFactorMap_p[iter->first] = 1 / sqrt(newWeightFactorMap_p[iter->first]);
    4899             :         }
    4900             : 
    4901          34 :         return;
    4902             : }
    4903             : 
    4904             : // -----------------------------------------------------------------------
    4905             : // Method to check if flag category has to be filled
    4906             : // -----------------------------------------------------------------------
    4907          35 : void MSTransformManager::checkFillFlagCategory()
    4908             : {
    4909          35 :         inputFlagCategoryAvailable_p = false;
    4910          35 :         if (    !selectedInputMsCols_p->flagCategory().isNull()
    4911          35 :                         && selectedInputMsCols_p->flagCategory().isDefined(0)
    4912         105 :                         && selectedInputMsCols_p->flagCategory()(0).shape() == 3)
    4913             :         {
    4914           0 :                 inputFlagCategoryAvailable_p = true;
    4915           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4916           0 :                                 << "Optional column FLAG_CATEGORY found in input MS will be written to output MS" << LogIO::POST;
    4917             :         }
    4918             : 
    4919          35 :         return;
    4920             : }
    4921             : 
    4922             : // -----------------------------------------------------------------------
    4923             : // Method to check if weight spectrum column has to be filled
    4924             : // -----------------------------------------------------------------------
    4925          35 : void MSTransformManager::checkFillWeightSpectrum()
    4926             : {
    4927          35 :         inputWeightSpectrumAvailable_p = false;
    4928          38 :         if (!selectedInputMsCols_p->weightSpectrum().isNull() and
    4929           3 :             selectedInputMsCols_p->weightSpectrum().isDefined(0))
    4930             :         {
    4931           0 :                 inputWeightSpectrumAvailable_p = true;
    4932           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    4933           0 :                                 << "Optional column WEIGHT_SPECTRUM found in input MS will be written to output MS" << LogIO::POST;
    4934             :         }
    4935          35 : }
    4936             : 
    4937             : /**
    4938             :  * Early check for a potential issue that would prevent an MSTransform
    4939             :  * setup which looks in principle fine from running correctly. Ensures
    4940             :  * that we catch a current limitation in the underlying iterators /
    4941             :  * VI/VB2 framework whereby combinespws won't work when the number of
    4942             :  * channels is different for different SPWs.
    4943             :  *
    4944             :  * Requires that numOfInpChanMap_p be populated previously (in
    4945             :  * getInputNumberOfChannels()).
    4946             :  *
    4947             :  * @throws AipsError if combinespws is enabled and the input MS of the
    4948             :  * current configuration has different number of channels for
    4949             :  * different SPWs
    4950             :  */
    4951          35 : void MSTransformManager::checkSPWChannelsKnownLimitation()
    4952             : {
    4953          35 :   if (not combinespws_p)
    4954          35 :     return;
    4955             : 
    4956           0 :   auto nSpws = inputMs_p->spectralWindow().nrow();
    4957           0 :   if (1 >= nSpws or numOfInpChanMap_p.empty() or numOfSelChanMap_p.empty())
    4958           0 :     return;
    4959             : 
    4960           0 :   auto firstNum = numOfSelChanMap_p.begin()->second;
    4961           0 :   auto diff = std::find_if(numOfSelChanMap_p.begin(), numOfSelChanMap_p.end(),
    4962           0 :                            [&firstNum](const std::pair<casacore::uInt,casacore::uInt> &other) {
    4963           0 :                              return firstNum != other.second; });
    4964             : 
    4965             : 
    4966           0 :   if (numOfSelChanMap_p.end() != diff) {
    4967           0 :     auto otherNum = diff->second;
    4968           0 :     throw AipsError("Currently the option 'combinespws' is only supported when the number "
    4969             :                     "of channels is the same for all the spw's selected. One of the SPWs "
    4970           0 :                     "selected has " + std::to_string(firstNum) + " channels, but another "
    4971           0 :                     "selected SPW has " + std::to_string(otherNum) + " channels.");
    4972             :   }
    4973             : }
    4974             : 
    4975             : /**
    4976             :  * Early check to issue a warning if the data was preaveraged
    4977             :  * by the correlator ans we are performing a further
    4978             :  * smoothing and average.
    4979             :  */
    4980          35 : void MSTransformManager::checkCorrelatorPreaveraging()
    4981             : {
    4982          35 :   std::string spwPreaveraged;
    4983          35 :   if (hanningSmooth_p || channelAverage_p)
    4984             :   {
    4985          17 :     auto spwTable = inputMs_p->spectralWindow();
    4986          17 :     MSSpWindowColumns spwColumns(spwTable);
    4987          34 :     if (spwTable.tableDesc().isColumn("SDM_WINDOW_FUNCTION") &&
    4988          17 :         spwTable.tableDesc().columnDescSet().isDefined("SDM_WINDOW_FUNCTION") &&
    4989          51 :         spwTable.tableDesc().isColumn("SDM_NUM_BIN") &&
    4990          17 :         spwTable.tableDesc().columnDescSet().isDefined("SDM_NUM_BIN"))
    4991             :     {
    4992           0 :       auto nrows = spwColumns.nrow();
    4993           0 :       auto effBWCol = spwColumns.effectiveBW();
    4994           0 :       auto chanWidthCol = spwColumns.chanWidth();
    4995           0 :       ScalarColumn<String> windowFunctionCol(spwTable, "SDM_WINDOW_FUNCTION");
    4996           0 :       ScalarColumn<Int> numBinCol(spwTable, "SDM_NUM_BIN");
    4997           0 :       for (size_t spwIdx = 0; spwIdx < nrows; spwIdx++)
    4998             :       {
    4999           0 :         auto numBin =  numBinCol(spwIdx);
    5000           0 :         auto windowFunction = windowFunctionCol(spwIdx);
    5001           0 :         if(windowFunction != "UNKNOWN" && numBin != 1)
    5002           0 :           spwPreaveraged += std::to_string(spwIdx)+" ";
    5003           0 :       }
    5004           0 :     }
    5005          17 :   }
    5006             : 
    5007          35 :   if(spwPreaveraged != "")
    5008           0 :     logger_p << LogIO::WARN<<LogOrigin("MSTransformManager", __func__) <<
    5009             :         "The data has already been preaveraged by the correlator but "
    5010             :         "further smoothing or averaging has been requested. "
    5011           0 :         "Preaveraged SPWs are: "<<spwPreaveraged<<LogIO::POST;
    5012          35 : }
    5013             : 
    5014             : // -----------------------------------------------------------------------
    5015             : //
    5016             : // -----------------------------------------------------------------------
    5017          35 : void MSTransformManager::checkDataColumnsAvailable()
    5018             : {
    5019          35 :         dataColumnAvailable_p = false;
    5020          35 :         correctedDataColumnAvailable_p = false;
    5021          35 :         modelDataColumnAvailable_p = false;
    5022             : 
    5023             : 
    5024          35 :         floatDataColumnAvailable_p = false;
    5025          35 :         lagDataColumnAvailable_p = false;
    5026             : 
    5027             : 
    5028             :         // DATA
    5029          35 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::DATA)))
    5030             :         {
    5031          35 :                 dataColumnAvailable_p = true;
    5032             :         }
    5033             : 
    5034             : 
    5035             :         // CORRECTED_DATA already exists in the input MS
    5036          35 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::CORRECTED_DATA)))
    5037             :         {
    5038           6 :                 correctedDataColumnAvailable_p = true;
    5039             :         }
    5040             :         // CORRECTED_DATA does not exist but there is a calibration parameter set available
    5041          29 :         else if (calibrate_p and (makeVirtualCorrectedColReal_p or bufferMode_p))
    5042             :         {
    5043           0 :                 correctedDataColumnAvailable_p = true;
    5044             :         }
    5045             :         // There is no calibration parameter set available
    5046             :         else
    5047             :         {
    5048             :                 // TODO: Inform that virtual CORRECTED_DATA is not available
    5049             : 
    5050             :                 // Unset makeVirtualModelColReal_p as virtual CORRECTED col. is not available
    5051          29 :                 makeVirtualCorrectedColReal_p = false;
    5052             :         }
    5053             : 
    5054             :         // FLOAT_DATA
    5055          35 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::FLOAT_DATA)))
    5056             :         {
    5057           0 :                 floatDataColumnAvailable_p = true;
    5058             :         }
    5059             : 
    5060             : 
    5061             :         // MODEL_DATA already exists in the input MS
    5062          35 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::MODEL_DATA)))
    5063             :         {
    5064           6 :                 modelDataColumnAvailable_p = true;
    5065             :         }
    5066             :         // MODEL_DATA does not exist but there is a model available in the SOURCE sub-table
    5067             :         // MODEL_DATA should not be made real if the user does not specify it implicitly
    5068          29 :         else if (inputMs_p->source().isColumn(MSSource::SOURCE_MODEL) and makeVirtualModelColReal_p)
    5069             :         {
    5070           0 :                 modelDataColumnAvailable_p = true;
    5071             :         }
    5072             :         // CAS-7390: Provide default MODEL_DATA in buffer mode
    5073          29 :         else if (bufferMode_p and not floatDataColumnAvailable_p) // MODEL is not defined for SD data
    5074             :         {
    5075           0 :                 makeVirtualModelColReal_p = true;
    5076           0 :                 modelDataColumnAvailable_p = true;
    5077             :         }
    5078             :         // There is no model available in the SOURCE sub-table
    5079             :         else
    5080             :         {
    5081          29 :                 modelDataColumnAvailable_p = false;
    5082             : 
    5083             :                 // Inform that virtual MODEL_DATA is not available
    5084          29 :                 if (makeVirtualModelColReal_p)
    5085             :                 {
    5086           0 :                         if (bufferMode_p)
    5087             :                         {
    5088           0 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5089             :                                                 << "Requested to make virtual MODEL_DATA column available from MSTransformBuffer but"
    5090             :                                                 << "SOURCE_MODEL column is not present in SOURCE sub-table"
    5091           0 :                                                 << LogIO::POST;
    5092             :                         }
    5093             :                         else
    5094             :                         {
    5095           0 :                                 logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5096             :                                                  << "Requested to make virtual MODEL_DATA column real but "
    5097             :                                                  << "SOURCE_MODEL column is not present in SOURCE sub-table"
    5098           0 :                                                  << LogIO::POST;
    5099             :                         }
    5100             :                 }
    5101             : 
    5102             :                 // Unset makeVirtualModelColReal_p as virtual MODEL col. is not available
    5103          29 :                 makeVirtualModelColReal_p = false;
    5104             :         }
    5105             : 
    5106             : 
    5107             :         // LAG_DATA
    5108          35 :         if (inputMs_p->tableDesc().isColumn(MS::columnName(MS::LAG_DATA)))
    5109             :         {
    5110           0 :                 lagDataColumnAvailable_p = true;
    5111             :         }
    5112             : 
    5113          35 :         return;
    5114             : }
    5115             : 
    5116             : // -----------------------------------------------------------------------
    5117             : // Method to check which data columns have to be filled
    5118             : // -----------------------------------------------------------------------
    5119          35 : void MSTransformManager::checkDataColumnsToFill()
    5120             : {
    5121          35 :         dataColMap_p.clear();
    5122          35 :         bool mainColSet=false;
    5123          35 :         timeAvgOptions_p = vi::AveragingOptions(vi::AveragingOptions::Nothing);
    5124             : 
    5125          35 :         if (datacolumn_p.contains("ALL"))
    5126             :         {
    5127           1 :                 if (dataColumnAvailable_p)
    5128             :                 {
    5129           1 :                         if (!mainColSet)
    5130             :                         {
    5131           1 :                                 mainColumn_p = MS::DATA;
    5132           1 :                                 mainColSet = true;
    5133             :                         }
    5134           1 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5135           1 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5136             : 
    5137           1 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5138           1 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5139             :                 }
    5140             : 
    5141           1 :                 if (correctedDataColumnAvailable_p)
    5142             :                 {
    5143           0 :                         if (!mainColSet)
    5144             :                         {
    5145           0 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5146           0 :                                 mainColSet = true;
    5147             :                         }
    5148           0 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
    5149           0 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5150             : 
    5151           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5152           0 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5153             :                 }
    5154           1 :         if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
    5155           0 :             bothDataColumnsAreOutput_p = true;
    5156             : 
    5157             : 
    5158           1 :                 if (modelDataColumnAvailable_p)
    5159             :                 {
    5160           0 :                         if (!mainColSet)
    5161             :                         {
    5162           0 :                                 mainColumn_p = MS::MODEL_DATA;
    5163           0 :                                 mainColSet = true;
    5164             :                         }
    5165           0 :                         dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
    5166           0 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5167             : 
    5168           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5169             : 
    5170           0 :                         if (correctedDataColumnAvailable_p)
    5171             :                         {
    5172           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
    5173             :                         }
    5174           0 :                         else if (dataColumnAvailable_p)
    5175             :                         {
    5176           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
    5177             :                         }
    5178             :                         else
    5179             :                         {
    5180           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5181             :                         }
    5182             :                 }
    5183             : 
    5184           1 :                 if (floatDataColumnAvailable_p)
    5185             :                 {
    5186           0 :                         if (!mainColSet)
    5187             :                         {
    5188           0 :                                 mainColumn_p = MS::FLOAT_DATA;
    5189           0 :                                 mainColSet = true;
    5190             :                         }
    5191           0 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5192           0 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5193             : 
    5194           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5195             :                 }
    5196             : 
    5197           1 :                 if (lagDataColumnAvailable_p)
    5198             :                 {
    5199           0 :                         if (!mainColSet)
    5200             :                         {
    5201           0 :                                 mainColumn_p = MS::LAG_DATA;
    5202           0 :                                 mainColSet = true;
    5203             :                         }
    5204           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5205           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5206             : 
    5207             :                         // TODO: LAG_DATA is not yet supported by TVI
    5208             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5209             :                 }
    5210             :         }
    5211          34 :         else if (datacolumn_p.contains("DATA,MODEL,CORRECTED"))
    5212             :         {
    5213           2 :                 if (dataColumnAvailable_p)
    5214             :                 {
    5215           2 :                         if (!mainColSet)
    5216             :                         {
    5217           2 :                                 mainColumn_p = MS::DATA;
    5218           2 :                                 mainColSet = true;
    5219             :                         }
    5220           2 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5221           2 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5222             : 
    5223           2 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5224           2 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5225             :                 }
    5226             : 
    5227           2 :                 if (correctedDataColumnAvailable_p)
    5228             :                 {
    5229           2 :                         if (!mainColSet)
    5230             :                         {
    5231           0 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5232           0 :                                 mainColSet = true;
    5233             :                         }
    5234           2 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::CORRECTED_DATA;
    5235           2 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5236             : 
    5237           2 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5238           2 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5239             :                 }
    5240             : 
    5241           2 :         if (dataColumnAvailable_p && correctedDataColumnAvailable_p)
    5242           2 :             bothDataColumnsAreOutput_p = true;
    5243           2 :                 if (modelDataColumnAvailable_p)
    5244             :                 {
    5245           2 :                         if (!mainColSet)
    5246             :                         {
    5247           0 :                                 mainColumn_p = MS::MODEL_DATA;
    5248           0 :                                 mainColSet = true;
    5249             :                         }
    5250           2 :                         dataColMap_p[MS::MODEL_DATA] = MS::MODEL_DATA;
    5251           2 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5252             : 
    5253           2 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5254             : 
    5255           2 :                         if (correctedDataColumnAvailable_p)
    5256             :                         {
    5257           2 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromWEIGHT;
    5258             :                         }
    5259           0 :                         else if (dataColumnAvailable_p)
    5260             :                         {
    5261           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelFlagWeightAvgFromSIGMA;
    5262             :                         }
    5263             :                         else
    5264             :                         {
    5265           0 :                                 timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5266             :                         }
    5267             :                 }
    5268             :         }
    5269          32 :         else if (datacolumn_p.contains("FLOAT_DATA,DATA"))
    5270             :         {
    5271             : 
    5272           0 :                 if (dataColumnAvailable_p)
    5273             :                 {
    5274           0 :                         if (!mainColSet)
    5275             :                         {
    5276           0 :                                 mainColumn_p = MS::DATA;
    5277           0 :                                 mainColSet = true;
    5278             :                         }
    5279           0 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5280           0 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5281             : 
    5282           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5283           0 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5284             :                 }
    5285             :                 else
    5286             :                 {
    5287           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5288           0 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5289             :                 }
    5290             : 
    5291           0 :                 if (floatDataColumnAvailable_p)
    5292             :                 {
    5293           0 :                         if (!mainColSet)
    5294             :                         {
    5295           0 :                                 mainColumn_p = MS::FLOAT_DATA;
    5296           0 :                                 mainColSet = true;
    5297             :                         }
    5298           0 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5299           0 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5300             : 
    5301           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5302             :                 }
    5303             :                 else
    5304             :                 {
    5305           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5306           0 :                                         "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
    5307             :                 }
    5308             :         }
    5309          32 :         else if (datacolumn_p.contains("FLOAT_DATA"))
    5310             :         {
    5311           0 :                 if (floatDataColumnAvailable_p)
    5312             :                 {
    5313           0 :                         if (!mainColSet)
    5314             :                         {
    5315           0 :                                 mainColumn_p = MS::FLOAT_DATA;
    5316           0 :                                 mainColSet = true;
    5317             :                         }
    5318           0 :                         dataColMap_p[MS::FLOAT_DATA] = MS::FLOAT_DATA;
    5319           0 :                         colCheckInfo(MS::columnName(MS::FLOAT_DATA),MS::columnName(dataColMap_p[MS::FLOAT_DATA]));
    5320             : 
    5321           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageFloat;
    5322             :                 }
    5323             :                 else
    5324             :                 {
    5325           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5326           0 :                                         "FLOAT_DATA column requested but not available in input MS "<< LogIO::POST;
    5327             :                 }
    5328             :         }
    5329          32 :         else if (datacolumn_p.contains("LAG_DATA,DATA"))
    5330             :         {
    5331           0 :                 if (dataColumnAvailable_p)
    5332             :                 {
    5333           0 :                         if (!mainColSet)
    5334             :                         {
    5335           0 :                                 mainColumn_p = MS::DATA;
    5336           0 :                                 mainColSet = true;
    5337             :                         }
    5338           0 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5339           0 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5340             : 
    5341           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5342           0 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5343             :                 }
    5344             :                 else
    5345             :                 {
    5346           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5347           0 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5348             :                 }
    5349             : 
    5350           0 :                 if (lagDataColumnAvailable_p)
    5351             :                 {
    5352           0 :                         if (!mainColSet)
    5353             :                         {
    5354           0 :                                 mainColumn_p = MS::LAG_DATA;
    5355           0 :                                 mainColSet = true;
    5356             :                         }
    5357           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5358           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5359             : 
    5360             :                         // TODO: LAG_DATA is not yet supported by TVI
    5361             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5362             :                 }
    5363             :                 else
    5364             :                 {
    5365           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5366           0 :                                         "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
    5367             :                 }
    5368             :         }
    5369          32 :         else if (datacolumn_p.contains("LAG_DATA"))
    5370             :         {
    5371           0 :                 if (lagDataColumnAvailable_p)
    5372             :                 {
    5373           0 :                         if (!mainColSet)
    5374             :                         {
    5375           0 :                                 mainColumn_p = MS::LAG_DATA;
    5376           0 :                                 mainColSet = true;
    5377             :                         }
    5378           0 :                         dataColMap_p[MS::LAG_DATA] = MS::LAG_DATA;
    5379           0 :                         colCheckInfo(MS::columnName(MS::LAG_DATA),MS::columnName(dataColMap_p[MS::LAG_DATA]));
    5380             : 
    5381             :                         // TODO: LAG_DATA is not yet supported by TVI
    5382             :                         // timeAvgOptions_p |= vi::AveragingOptions::AverageLagData;
    5383             :                 }
    5384             :                 else
    5385             :                 {
    5386           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5387           0 :                                         "LAG_DATA column requested but not available in input MS "<< LogIO::POST;
    5388             :                 }
    5389             :         }
    5390          32 :         else if (datacolumn_p.contains("DATA"))
    5391             :         {
    5392          29 :                 if (dataColumnAvailable_p)
    5393             :                 {
    5394          29 :                         if (!mainColSet)
    5395             :                         {
    5396          29 :                                 mainColumn_p = MS::DATA;
    5397          29 :                                 mainColSet = true;
    5398             :                         }
    5399          29 :                         dataColMap_p[MS::DATA] = MS::DATA;
    5400          29 :                         colCheckInfo(MS::columnName(MS::DATA),MS::columnName(dataColMap_p[MS::DATA]));
    5401             : 
    5402          29 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageObserved;
    5403          29 :                         timeAvgOptions_p |= vi::AveragingOptions::ObservedFlagWeightAvgFromSIGMA;
    5404             :                 }
    5405             :                 else
    5406             :                 {
    5407           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5408           0 :                                         "DATA column requested but not available in input MS "<< LogIO::POST;
    5409             :                 }
    5410             :         }
    5411           3 :         else if (datacolumn_p.contains("CORRECTED"))
    5412             :         {
    5413           3 :                 if (correctedDataColumnAvailable_p)
    5414             :                 {
    5415           3 :                         if (!mainColSet)
    5416             :                         {
    5417           3 :                                 mainColumn_p = MS::CORRECTED_DATA;
    5418           3 :                                 mainColSet = true;
    5419             :                         }
    5420           3 :                         dataColMap_p[MS::CORRECTED_DATA] = MS::DATA;
    5421           3 :                         correctedToData_p = true;
    5422           3 :                         colCheckInfo(MS::columnName(MS::CORRECTED_DATA),MS::columnName(dataColMap_p[MS::CORRECTED_DATA]));
    5423             : 
    5424           3 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageCorrected;
    5425           3 :                         timeAvgOptions_p |= vi::AveragingOptions::CorrectedFlagWeightAvgFromWEIGHT;
    5426             :                 }
    5427             :                 else
    5428             :                 {
    5429           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5430           0 :                                         "CORRECTED_DATA column requested but not available in input MS "<< LogIO::POST;
    5431             :                 }
    5432             :         }
    5433           0 :         else if (datacolumn_p.contains("MODEL"))
    5434             :         {
    5435             : 
    5436           0 :                 if (modelDataColumnAvailable_p)
    5437             :                 {
    5438           0 :                         if (!mainColSet)
    5439             :                         {
    5440           0 :                                 mainColumn_p = MS::MODEL_DATA;
    5441           0 :                                 mainColSet = true;
    5442             :                         }
    5443             : 
    5444           0 :                         dataColMap_p[MS::MODEL_DATA] = MS::DATA;
    5445           0 :                         colCheckInfo(MS::columnName(MS::MODEL_DATA),MS::columnName(dataColMap_p[MS::MODEL_DATA]));
    5446           0 :                         timeAvgOptions_p |= vi::AveragingOptions::AverageModel;
    5447           0 :                         timeAvgOptions_p |= vi::AveragingOptions::ModelPlainAvg;
    5448             :                 }
    5449             :                 else
    5450             :                 {
    5451           0 :                         logger_p << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__) <<
    5452           0 :                                         "MODEL_DATA column requested but not available in input MS "<< LogIO::POST;
    5453             :                 }
    5454             :         }
    5455           0 :         else if (datacolumn_p.contains("NONE") and userBufferMode_p)
    5456             :         {
    5457           0 :                 logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    5458             :                                         << "No datacolumn selected in buffer mode"
    5459           0 :                                         << LogIO::POST;
    5460             :         }
    5461             :         else
    5462             :         {
    5463           0 :                 logger_p        << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    5464           0 :                                         << "Requested data column " << datacolumn_p
    5465             :                                         << " is not supported, possible choices are ALL,DATA,CORRECTED,MODEL,FLOAT_DATA,LAG_DATA"
    5466           0 :                                         << LogIO::POST;
    5467             :         }
    5468             : 
    5469          35 :         if (produceModel_p) {
    5470           0 :             const auto colname = (MS::DATA == mainColumn_p) ? "DATA" : "CORRECTED_DATA";
    5471           0 :             logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5472             :                      << "Will produce a MODEL_DATA column in the output MS, "
    5473             :                      << "with the fit calculated for input " << colname
    5474           0 :                      << LogIO::POST;
    5475           0 :             dataColMap_p[MS::MODEL_DATA] = mainColumn_p;
    5476             :         }
    5477             : 
    5478             :         // Add shortcuts to be used in the context of WeightSpectrum related transformations
    5479          35 :         dataColMap::iterator iter;
    5480             : 
    5481             :         // Check if we are doing DATA
    5482          35 :         iter = dataColMap_p.find(MS::DATA);
    5483          35 :         if (iter != dataColMap_p.end()) doingData_p = true;
    5484             : 
    5485             :         // Check if we are doing CORRECTED_DATA
    5486          35 :         iter = dataColMap_p.find(MS::CORRECTED_DATA);
    5487          35 :         if (iter != dataColMap_p.end()) doingCorrected_p = true;
    5488             : 
    5489             :         // Check if we are doing MODEL_DATA
    5490          35 :         iter = dataColMap_p.find(MS::MODEL_DATA);
    5491          35 :         if (iter != dataColMap_p.end()) doingModel_p = true;
    5492             : 
    5493          70 :         return;
    5494             : }
    5495             : 
    5496             : 
    5497             : // -----------------------------------------------------------------------
    5498             : //
    5499             : // -----------------------------------------------------------------------
    5500          39 : void MSTransformManager::colCheckInfo(const String& inputColName, const String& outputColName)
    5501             : {
    5502          39 :         if (inputMs_p->tableDesc().isColumn(inputColName))
    5503             :         {
    5504          39 :                 if (not bufferMode_p)
    5505             :                 {
    5506          78 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5507             :                                                 << "Adding " << outputColName << " column to output MS from input " << inputColName<< " column"
    5508          78 :                                                 << LogIO::POST;
    5509             :                 }
    5510             :                 else
    5511             :                 {
    5512           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5513             :                                                 << inputColName << " column present in input MS will be available from MSTransformBuffer"
    5514           0 :                                                 << LogIO::POST;
    5515             :                 }
    5516             :         }
    5517             :         else
    5518             :         {
    5519           0 :                 if (not bufferMode_p)
    5520             :                 {
    5521           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5522             :                                                 << "Adding " << outputColName << " column to output MS from input virtual " << inputColName<< " column"
    5523           0 :                                                 << LogIO::POST;
    5524             :                 }
    5525             :                 else
    5526             :                 {
    5527           0 :                         logger_p        << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5528             :                                                 << "Virtual " << inputColName << " column present in input MS will be available from MSTransformBuffer"
    5529           0 :                                                 << LogIO::POST;
    5530             :                 }
    5531             :         }
    5532             : 
    5533          39 :         return;
    5534             : }
    5535             : 
    5536             : 
    5537             : // -----------------------------------------------------------------------
    5538             : // Method to determine sort columns order
    5539             : // -----------------------------------------------------------------------
    5540          35 : void MSTransformManager::setIterationApproach()
    5541             : {
    5542          35 :         uInt nSortColumns = 7;
    5543             : 
    5544          35 :         if (timespan_p.contains("scan")) nSortColumns -= 1;
    5545          35 :         if (timespan_p.contains("state")) nSortColumns -= 1;
    5546          35 :         if (timespan_p.contains("field")) nSortColumns -= 1;
    5547          35 :         if ((combinespws_p) || (spwAverage_p)) nSortColumns -= 1;
    5548             : 
    5549          35 :         sortColumns_p = Block<Int>(nSortColumns);
    5550          35 :         uInt sortColumnIndex = 0;
    5551             : 
    5552          35 :         sortColumns_p[0] = MS::OBSERVATION_ID;
    5553          35 :         sortColumnIndex += 1;
    5554             : 
    5555          35 :         sortColumns_p[1] = MS::ARRAY_ID;
    5556          35 :         sortColumnIndex += 1;
    5557             : 
    5558          35 :         if (!timespan_p.contains("scan"))
    5559             :         {
    5560          35 :                 sortColumns_p[sortColumnIndex] =  MS::SCAN_NUMBER;
    5561          35 :                 sortColumnIndex += 1;
    5562             :         }
    5563             :         else
    5564             :         {
    5565           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5566           0 :                                 << "Combining data through scans for time average " << LogIO::POST;
    5567             :         }
    5568             : 
    5569          35 :         if (!timespan_p.contains("state"))
    5570             :         {
    5571          35 :                 sortColumns_p[sortColumnIndex] =  MS::STATE_ID;
    5572          35 :                 sortColumnIndex += 1;
    5573             :         }
    5574             :         else
    5575             :         {
    5576           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5577           0 :                                 << "Combining data through state for time average" << LogIO::POST;
    5578             :         }
    5579             : 
    5580          35 :         if (!timespan_p.contains("field"))
    5581             :         {
    5582          35 :                 sortColumns_p[sortColumnIndex] =  MS::FIELD_ID;
    5583          35 :                 sortColumnIndex += 1;
    5584             :         }
    5585             :         else
    5586             :         {
    5587           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5588           0 :                                 << "Combining data through field time average" << LogIO::POST;
    5589             :         }
    5590             : 
    5591          35 :         if ((!combinespws_p) && (!spwAverage_p))
    5592             :         {
    5593          35 :                 sortColumns_p[sortColumnIndex] =  MS::DATA_DESC_ID;
    5594          35 :                 sortColumnIndex += 1;
    5595             :         }
    5596             :         else
    5597             :         {
    5598           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5599           0 :                                 << "Combining data from selected spectral windows" << LogIO::POST;
    5600             :         }
    5601             : 
    5602          35 :         sortColumns_p[sortColumnIndex] =  MS::TIME;
    5603             : 
    5604          35 :         return;
    5605             : }
    5606             : 
    5607             : 
    5608             : // -----------------------------------------------------------------------
    5609             : // Method to generate the initial iterator
    5610             : // -----------------------------------------------------------------------
    5611          35 : void MSTransformManager::generateIterator()
    5612             : {
    5613          35 :         bool isWritable = false;
    5614          35 :         if (interactive_p) isWritable = true;
    5615             : 
    5616             :         // Prepare time average parameters (common for all cases)
    5617          35 :         std::shared_ptr<vi::AveragingParameters> timeavgParams = nullptr;
    5618          35 :         if (timeAverage_p)
    5619             :         {
    5620          19 :                 if (maxuvwdistance_p > 0)
    5621             :                 {
    5622           0 :                         timeAvgOptions_p |= vi::AveragingOptions::BaselineDependentAveraging;
    5623             :                 }
    5624             : 
    5625             :                 timeavgParams = std::make_shared<vi::AveragingParameters>
    5626          38 :                     (timeBin_p, .0, vi::SortColumns(sortColumns_p, false),
    5627          57 :                      timeAvgOptions_p, maxuvwdistance_p, nullptr, isWritable, dx_p, dy_p);
    5628             :         }
    5629             : 
    5630             :         // Calibrating VI
    5631          35 :         if (uvcontsub_p)
    5632             :         {
    5633             :                 // First determine number of layers
    5634           0 :                 uInt nTVIs = 1;
    5635           0 :                 if (timeAverage_p) nTVIs++;
    5636           0 :                 if (uvcontsub_p) nTVIs++;
    5637             : 
    5638             :                 // Init vector of TVI factories and populate it
    5639           0 :                 uInt TVIFactoryIdx = 0;
    5640           0 :                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5641             : 
    5642             :                 // Data layer
    5643           0 :                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5644           0 :                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5645           0 :                 TVIFactories[TVIFactoryIdx]=&dataLayerTVIFactory;
    5646           0 :                 TVIFactoryIdx++;
    5647             : 
    5648             :                 // Time avg. layer
    5649           0 :                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5650           0 :                 if (timeAverage_p)
    5651             :                 {
    5652           0 :                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5653           0 :                         TVIFactories[TVIFactoryIdx]=timeAverageTVIFactory.get();
    5654           0 :                         TVIFactoryIdx++;
    5655             :                 }
    5656             : 
    5657             :                 // UVContSub layer
    5658           0 :                 std::unique_ptr<vi::UVContSubTVILayerFactory> uvContSubTVIFactory;
    5659           0 :                 if (uvcontsub_p)
    5660             :                 {
    5661             :                         // needed for warning to prevent confusion with old uvcontsub!
    5662           0 :                         uvcontsubRec_p.define("allowed_spws", spwSelection_p);
    5663           0 :                         uvContSubTVIFactory.reset(new vi::UVContSubTVILayerFactory (uvcontsubRec_p));
    5664           0 :                         TVIFactories[TVIFactoryIdx]=uvContSubTVIFactory.get();
    5665           0 :                         TVIFactoryIdx++;
    5666             :                 }
    5667             : 
    5668           0 :                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5669             : 
    5670           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__)
    5671           0 :                                 << "TVI chain is " << visibilityIterator_p->ViiType() << LogIO::POST;
    5672           0 :         }
    5673          35 :         else if (calibrate_p || scalarAverage_p)
    5674             :         {
    5675             :                 try
    5676             :                 {
    5677             :                         // Isolate iteration parameters
    5678           0 :                         vi::IteratingParameters iterpar;
    5679           0 :                         if (scalarAverage_p)
    5680           0 :                                 iterpar = vi::IteratingParameters(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5681             :                         else
    5682           0 :                                 iterpar = vi::IteratingParameters(0,vi::SortColumns(sortColumns_p, false));
    5683             : 
    5684             :                         // By callib String
    5685           0 :                         if (callib_p.length() > 0)
    5686             :                         {
    5687           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    5688             :                                         << "OTF calibration activated, using calibration file spec to generate iterator"
    5689           0 :                                         << LogIO::POST;
    5690             : 
    5691           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callib_p, timeavgParams.get()));
    5692             :                         }
    5693             :                         // By callib Record
    5694           0 :                         else if (callibRec_p.nfields() > 0)
    5695             :                         {
    5696           0 :                                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    5697             :                                         << "OTF calibration activated, using calibration record spec to generate iterator"
    5698           0 :                                         << LogIO::POST;
    5699             : 
    5700           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar,callibRec_p, timeavgParams.get()));
    5701             :                         }
    5702             :                         else // scalar
    5703             :                         {
    5704           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::LayeredVi2Factory(selectedInputMs_p, &iterpar));
    5705             :                         }
    5706           0 :                 }
    5707           0 :                 catch (const MSSelectionError &x)
    5708             :                 {
    5709           0 :                         delete visibilityIterator_p;
    5710             : 
    5711           0 :                         correctedDataColumnAvailable_p = false;
    5712           0 :                         checkDataColumnsToFill();
    5713             : 
    5714             :                         // Averaging VI
    5715           0 :                         if (timeAverage_p && !tviphaseshift_p)
    5716             :                         {
    5717           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
    5718             :                         }
    5719             :                         // Polarization Averaging VI
    5720           0 :                         else if (polAverage_p) {
    5721           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
    5722           0 :                                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5723             :                         }
    5724             :                         // Pointings Interpolator VI
    5725           0 :                         else if (pointingsInterpolation_p) {
    5726           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
    5727           0 :                                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5728             :                         }
    5729             :                         // CAS-12706 To run phase shift via a TVI which has
    5730             :                         // support for shifting across large offset/angles
    5731           0 :                         else if (tviphaseshift_p) {
    5732             : 
    5733             :                                 // First determine number of layers
    5734           0 :                                 uInt nTVIs = (timeAverage_p ? 3 : 2);
    5735             : 
    5736             :                                 // Init vector of TVI factories and populate it
    5737           0 :                                 uInt TVIFactoryIdx = 0;
    5738           0 :                                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5739             : 
    5740             :                                 // Data layer
    5741           0 :                                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5742           0 :                                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5743           0 :                                 TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
    5744             : 
    5745             :                                 // Time avg. layer
    5746           0 :                                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5747           0 :                                 if (timeAverage_p)
    5748             :                                 {
    5749           0 :                                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5750           0 :                                         TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
    5751             :                                 }
    5752             : 
    5753             :                                 // Phaseshift layer
    5754           0 :                                 vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
    5755           0 :                                 TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
    5756             : 
    5757           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5758           0 :                         }
    5759             :                         // Plain VI
    5760             :                         else
    5761             :                         {
    5762           0 :                                 visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
    5763           0 :                                                                                                                                         isWritable, NULL, timeBin_p);
    5764             :                         }
    5765           0 :                 }
    5766           0 :                 catch (const AipsError &x)
    5767             :                 {
    5768           0 :                         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    5769             :                                 << "Error initializing calibration VI: " << x.getMesg()
    5770           0 :                                 << LogIO::POST;
    5771           0 :                         throw(x);
    5772           0 :                 }
    5773           0 :         }
    5774             :         // Averaging VI
    5775          35 :         else if (timeAverage_p && !tviphaseshift_p)
    5776             :         {
    5777          19 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::AveragingVi2Factory(*timeavgParams, selectedInputMs_p));
    5778             :         }
    5779             :         // Polarization Averaging VI
    5780          16 :         else if (polAverage_p) {
    5781           0 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PolAverageVi2Factory(polAverageConfig_p, selectedInputMs_p,
    5782           0 :                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5783             :         }
    5784             :         // VI interpolating pointing directions
    5785          16 :         else if (pointingsInterpolation_p) {
    5786           0 :                 visibilityIterator_p = new vi::VisibilityIterator2(vi::PointingInterpolationVi2Factory(pointingsInterpolationConfig_p, selectedInputMs_p,
    5787           0 :                         vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable));
    5788             :         }
    5789             :         // CAS-12706 To run phase shift via a TVI which has
    5790             :         // support for shifting across large offset/angles
    5791          16 :         else if (tviphaseshift_p) {
    5792             : 
    5793             :                 // First determine number of layers
    5794           0 :                 uInt nTVIs = (timeAverage_p ? 3 : 2);
    5795             : 
    5796             :                 // Init vector of TVI factories and populate it
    5797           0 :                 uInt TVIFactoryIdx = 0;
    5798           0 :                 Vector<vi::ViiLayerFactory*> TVIFactories(nTVIs);
    5799             : 
    5800             :                 // Data layer
    5801           0 :                 vi::IteratingParameters ipar(timeBin_p,vi::SortColumns(sortColumns_p, false));
    5802           0 :                 vi::VisIterImpl2LayerFactory dataLayerTVIFactory(selectedInputMs_p,ipar,isWritable);
    5803           0 :                 TVIFactories[TVIFactoryIdx++]=&dataLayerTVIFactory;
    5804             : 
    5805             :                 // Time avg. layer
    5806           0 :                 std::unique_ptr<vi::AveragingVi2LayerFactory> timeAverageTVIFactory;
    5807           0 :                 if (timeAverage_p)
    5808             :                 {
    5809           0 :                         timeAverageTVIFactory.reset(new vi::AveragingVi2LayerFactory(*timeavgParams));
    5810           0 :                         TVIFactories[TVIFactoryIdx++]=timeAverageTVIFactory.get();
    5811             :                 }
    5812             : 
    5813             :                 // Phaseshift layer
    5814           0 :                 vi::PhaseShiftingTVILayerFactory phaseShiftingTVILayerFactory(tviphaseshiftConfig_p);
    5815           0 :                 TVIFactories[TVIFactoryIdx]=&phaseShiftingTVILayerFactory;
    5816             : 
    5817           0 :                 visibilityIterator_p = new vi::VisibilityIterator2 (TVIFactories);
    5818           0 :     }
    5819             :     // Offline ATM correction
    5820          16 :         else if (doAtmCor_p) {
    5821           0 :                 visibilityIterator_p = new vi::VisibilityIterator2(
    5822           0 :                         vi::SDAtmosphereCorrectionVi2Factory(
    5823           0 :                                 atmCorConfig_p, selectedInputMs_p, vi::SortColumns(sortColumns_p, false), timeBin_p, isWritable
    5824             :                         )
    5825           0 :                 );
    5826             :         }
    5827             :         // Plain VI
    5828             :         else
    5829             :         {
    5830          32 :                 visibilityIterator_p = new vi::VisibilityIterator2(*selectedInputMs_p,vi::SortColumns(sortColumns_p, false),
    5831          16 :                                                                                                                         isWritable, NULL, timeBin_p);
    5832             :         }
    5833             : 
    5834          35 :         if (timeAverage_p) visibilityIterator_p->setWeightScaling(vi::WeightScaling::generateUnityWeightScaling());
    5835          35 :         if (channelSelector_p != NULL) visibilityIterator_p->setFrequencySelection(*channelSelector_p);
    5836             : 
    5837          70 :         return;
    5838          35 : }
    5839             : 
    5840             : 
    5841             : // -----------------------------------------------------------------------
    5842             : //
    5843             : // -----------------------------------------------------------------------
    5844        1771 : void MSTransformManager::setupBufferTransformations(vi::VisBuffer2 *vb)
    5845             : {
    5846             :         // Calculate number of rows to add to the output MS depending on the combination parameters
    5847        1771 :         uInt rowsToAdd = 0;
    5848             : 
    5849        1771 :         if ((combinespws_p) or (nspws_p > 1))
    5850             :         {
    5851             :                 // Fill baseline map using as key Ant1,Ant2,Scan and State,
    5852             :                 // Which are the elements that can be combined in one chunk
    5853           0 :                 rowIndex_p.clear();
    5854           0 :                 baselineMap_p.clear();
    5855           0 :                 Vector<Int> antenna1 = vb->antenna1();
    5856           0 :                 Vector<Int> antenna2 = vb->antenna2();
    5857           0 :                 Vector<Int> scan = vb->scan();
    5858           0 :                 Vector<Int> state = vb->stateId();
    5859           0 :                 Int relativeTimeInMiliseconds = 0;
    5860           0 :                 for (uInt row=0;row<antenna1.size();row++)
    5861             :                 {
    5862           0 :                         pair<uInt,uInt> baseline = std::make_pair(antenna1(row),antenna2(row));
    5863           0 :                         relativeTimeInMiliseconds = (Int)floor(1E3*(vb->time()(row) - vb->time()(0)));
    5864           0 :                         pair< pair<uInt,uInt>, uInt > baselineTime = std::make_pair(baseline,relativeTimeInMiliseconds);
    5865             : 
    5866             :                         // Fill row index vector with to the first row for every element in the baseline map
    5867           0 :                         if (baselineMap_p.find(baselineTime) == baselineMap_p.end())
    5868             :                         {
    5869           0 :                                 rowIndex_p.push_back(row);
    5870             :                         }
    5871             : 
    5872           0 :                         baselineMap_p[baselineTime].push_back(row);
    5873             : 
    5874             :                 }
    5875             : 
    5876           0 :                 rowsToAdd = baselineMap_p.size();
    5877             : 
    5878             :                 // Fill row index vector with to the first row for every element in the baseline map
    5879             :                 // jagonzal (CAS-8492): For SPW separation only we don't
    5880             :                 // follow the baselineMap order but the input order
    5881           0 :                 if (combinespws_p)
    5882             :                 {
    5883           0 :                         uInt rowIndex = 0;
    5884           0 :                         rowIndex_p.clear();
    5885           0 :                         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    5886             :                         {
    5887           0 :                                 rowIndex_p.push_back((iter->second)[0]);
    5888           0 :                                 rowIndex ++;
    5889             :                         }
    5890             :                 }
    5891           0 :         }
    5892             :         else
    5893             :         {
    5894        1771 :                 rowsToAdd = vb->nRows();
    5895             :         }
    5896             : 
    5897             :         // Initialize reference frame transformation parameters
    5898        1771 :         if (refFrameTransformation_p)
    5899             :         {
    5900           0 :                 initFrequencyTransGrid(vb);
    5901             :         }
    5902             : 
    5903             :         // Calculate total number for rows to add
    5904        1771 :         nRowsToAdd_p = rowsToAdd*nspws_p;
    5905             : 
    5906        1771 :     return;
    5907             : 
    5908             : }
    5909             : 
    5910             : // -----------------------------------------------------------------------
    5911             : // Fill output MS with data from an input VisBuffer
    5912             : // -----------------------------------------------------------------------
    5913        1771 : void MSTransformManager::fillOutputMs(vi::VisBuffer2 *vb)
    5914             : {
    5915        1771 :         setupBufferTransformations(vb);
    5916             : 
    5917        1771 :         if (not bufferMode_p)
    5918             :         {
    5919             :                 // Create RowRef object to fill new rows
    5920        1771 :                 auto currentRows = outputMs_p->nrow();
    5921        1771 :                 RefRows rowRef( currentRows, currentRows + nRowsToAdd_p/nspws_p - 1);
    5922             : 
    5923             :                 // Add new rows to output MS
    5924        1771 :                 outputMs_p->addRow(nRowsToAdd_p,false);
    5925             : 
    5926             :                 // Fill new rows
    5927        1771 :                 weightSpectrumFlatFilled_p = false;
    5928        1771 :                 weightSpectrumFromSigmaFilled_p = false;
    5929        1771 :             fillWeightCols(vb,rowRef);
    5930        1771 :             fillDataCols(vb,rowRef);
    5931        1771 :                 fillIdCols(vb,rowRef);
    5932        1771 :         }
    5933             : 
    5934        1771 :     return;
    5935             : }
    5936             : 
    5937             : // -----------------------------------------------------------------------
    5938             : // Method to initialize the input frequency grid to change reference frame
    5939             : // -----------------------------------------------------------------------
    5940           0 : void MSTransformManager::initFrequencyTransGrid(vi::VisBuffer2 *vb)
    5941             : {
    5942             :         // NOTE (jagonzal): According to dpetry the difference between times is negligible but he recommends to use TIME
    5943             :         //                  However it does not cross-validate unless we use timeMeas from the MS columns
    5944           0 :         ScalarMeasColumn<MEpoch> mainTimeMeasCol = selectedInputMsCols_p->timeMeas();
    5945           0 :         MEpoch currentRowTime = mainTimeMeasCol(vb->rowIds()(0));
    5946             : 
    5947             :         // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    5948           0 :         MDoppler radVelCorr;
    5949           0 :         MDirection inputFieldDirection;
    5950           0 :         bool radVelSignificant = false;
    5951           0 :         if (radialVelocityCorrection_p && inputMSFieldCols_p->needInterTime(vb->fieldId()(0)))
    5952             :         {
    5953           0 :                 MRadialVelocity mRV = inputMSFieldCols_p->radVelMeas(vb->fieldId()(0),vb->time()(0));
    5954           0 :                 Quantity mrv = mRV.get("m/s");
    5955           0 :                 Quantity offsetMrv = radialVelocity_p.get("m/s"); // the radvel by which the out SPW def was shifted
    5956           0 :                 radVelCorr =  MDoppler(mrv-(Quantity(2.)*offsetMrv));
    5957           0 :                 if (fabs(mrv.getValue()) > 1E-6) radVelSignificant = true;
    5958             : 
    5959           0 :                 inputFieldDirection = inputMSFieldCols_p->phaseDirMeas(vb->fieldId()(0), vb->time()(0));
    5960           0 :         }
    5961             :         else
    5962             :         {
    5963           0 :                 inputFieldDirection = vb->phaseCenter();
    5964             :         }
    5965             : 
    5966           0 :         MFrequency::Ref inputFrameRef = MFrequency::Ref(inputReferenceFrame_p,
    5967           0 :                                                                                                         MeasFrame(inputFieldDirection, observatoryPosition_p, currentRowTime));
    5968             : 
    5969           0 :         MFrequency::Ref outputFrameRef;
    5970           0 :         outputFrameRef = MFrequency::Ref(outputReferenceFrame_p,
    5971           0 :                         MeasFrame(phaseCenter_p, observatoryPosition_p, referenceTime_p));
    5972             : 
    5973           0 :         freqTransEngine_p = MFrequency::Convert(MSTransformations::Hz, inputFrameRef, outputFrameRef);
    5974             : 
    5975           0 :         Int spwIndex = 0;
    5976           0 :         if (not combinespws_p)
    5977             :         {
    5978             :                 // jagonzal : It is not necessary to map spwIndex because we
    5979             :                 // pass the original SPWId down to the interpol1D method
    5980           0 :                 spwIndex = vb->spectralWindows()(0);
    5981             :         }
    5982             : 
    5983             : 
    5984           0 :         if (fftShiftEnabled_p)
    5985             :         {
    5986           0 :                 uInt centralChan = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size()/2;
    5987             : 
    5988           0 :                 Double oldCentralFrequencyBeforeRegridding = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[centralChan];
    5989             :                 Double newCentralFrequencyBeforeRegriddingAtCurrentTime =
    5990           0 :                                 freqTransEngine_p(oldCentralFrequencyBeforeRegridding).get(MSTransformations::Hz).getValue();
    5991             : 
    5992             :                 // CAS-6778: Support for new ref. frame SOURCE that requires radial velocity correction
    5993           0 :                 if (radVelSignificant)
    5994             :                 {
    5995           0 :                         Vector<Double> tmp(1,newCentralFrequencyBeforeRegriddingAtCurrentTime);
    5996           0 :                         newCentralFrequencyBeforeRegriddingAtCurrentTime = radVelCorr.shiftFrequency(tmp)(0);
    5997           0 :                 }
    5998             : 
    5999           0 :                 Double newCentralFrequencyBeforeRegriddingAtReferenceTime = inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[centralChan];
    6000           0 :                 Double absoluteShift = newCentralFrequencyBeforeRegriddingAtCurrentTime - newCentralFrequencyBeforeRegriddingAtReferenceTime;
    6001             : 
    6002           0 :                 Double chanWidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
    6003           0 :                 Double bandwidth = inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[inputOutputSpwMap_p[spwIndex].second.NUM_CHAN-1] - inputOutputSpwMap_p[spwIndex].second.CHAN_FREQ[0];
    6004           0 :                 bandwidth += chanWidth;
    6005             : 
    6006           0 :                 fftShift_p = - absoluteShift / bandwidth;
    6007             : 
    6008           0 :                 ostringstream current;
    6009           0 :                 current << setprecision(numeric_limits<double>::max_digits10)
    6010           0 :                         << newCentralFrequencyBeforeRegriddingAtCurrentTime;
    6011           0 :                 ostringstream reference;
    6012           0 :                 reference << setprecision(numeric_limits<double>::max_digits10)
    6013           0 :                           << newCentralFrequencyBeforeRegriddingAtReferenceTime;
    6014           0 :                 logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager",__FUNCTION__)
    6015             :                          << "Using fftshift interpolation. The absolute shift is the "
    6016             :                          << "new central frequency at current (input SPW) time - new "
    6017             :                          << "central frequency "
    6018             :                          << "at reference (output SPW) time\nAbsolute shift: "
    6019             :                          << current
    6020             :                          << " - " << reference
    6021             :                          << " = " << absoluteShift << ", bandwidth " << bandwidth
    6022           0 :                          << ", relative shift: " << fftShift_p << LogIO::POST;
    6023             : 
    6024           0 :         }
    6025             :         else
    6026             :         {
    6027           0 :             for(uInt chan_idx=0; chan_idx<inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ.size(); chan_idx++)
    6028             :             {
    6029           0 :                 inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[chan_idx] =
    6030           0 :                 freqTransEngine_p(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[chan_idx]).get(MSTransformations::Hz).getValue();
    6031             :             }
    6032             : 
    6033             :             /*
    6034             :                 ostringstream oss;
    6035             :                 oss.precision(30);
    6036             :                 oss << " field direction input frame=" << inputFieldDirection << endl;
    6037             :                 oss << " input frame=" << inputFrameRef << endl;
    6038             :                 oss << " field direction output frame=" << phaseCenter_p << endl;
    6039             :                 oss << " output frame=" << outputFrameRef << endl;
    6040             :                 oss << " transformation engine=" << freqTransEngine_p << endl;
    6041             :                 oss << " before transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ[0] << endl;
    6042             :                 oss << " after transformation=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
    6043             :                 */
    6044             : 
    6045             : 
    6046           0 :         if (radVelSignificant)
    6047             :         {
    6048           0 :                 inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux =
    6049           0 :                                 radVelCorr.shiftFrequency(inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux);
    6050             : 
    6051             :                 /*
    6052             :                 oss << " correction engine=" << radVelCorr << endl;
    6053             :                 oss << " after radial velocity correction=" << inputOutputSpwMap_p[spwIndex].first.CHAN_FREQ_aux[0] << endl;
    6054             :                         */
    6055             :         }
    6056             : 
    6057             :                 //logger_p << LogIO::NORMAL << LogOrigin("MSTransformManager", __FUNCTION__) << oss.str() << LogIO::POST;
    6058             :         }
    6059             : 
    6060           0 :         return;
    6061           0 : }
    6062             : 
    6063             : // ----------------------------------------------------------------------------------------
    6064             : // Fill auxiliary (meta data) columns which don't depend on the SPW (merely consist of Ids)
    6065             : // ----------------------------------------------------------------------------------------
    6066        1771 : void MSTransformManager::fillIdCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6067             : {
    6068             :     // Declare common auxiliary variables
    6069        1771 :     RefRows absoluteRefRows(rowRef.firstRow(),rowRef.firstRow()+nRowsToAdd_p-1);
    6070        1771 :     Vector<Int> tmpVectorInt(nRowsToAdd_p,0);
    6071        1771 :     Vector<Double> tmpVectorDouble(nRowsToAdd_p,0.0);
    6072        1771 :     Vector<bool> tmpVectorbool(nRowsToAdd_p,false);
    6073             : 
    6074             :     // Special case for Data description Id
    6075        1771 :     if (transformDDIVector(vb->dataDescriptionIds(),tmpVectorInt))
    6076             :     {
    6077        1771 :         outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,tmpVectorInt);
    6078             :     }
    6079             :     else
    6080             :     {
    6081           0 :         outputMsCols_p->dataDescId().putColumnCells(absoluteRefRows,vb->dataDescriptionIds());
    6082             :     }
    6083             : 
    6084             :     // Re-indexable Columns
    6085        1771 :     transformAndWriteReindexableVector(vb->observationId(),tmpVectorInt,true,
    6086        1771 :                                        inputOutputObservationIndexMap_p,
    6087        1771 :                                        outputMsCols_p->observationId(),absoluteRefRows);
    6088        1771 :     transformAndWriteReindexableVector(vb->arrayId(),tmpVectorInt,true,
    6089        1771 :                                        inputOutputArrayIndexMap_p,
    6090        1771 :                                        outputMsCols_p->arrayId(),absoluteRefRows);
    6091        1771 :     transformAndWriteReindexableVector(vb->fieldId(),tmpVectorInt,!timespan_p.contains("field"),
    6092        1771 :                                        inputOutputFieldIndexMap_p,
    6093        1771 :                                        outputMsCols_p->fieldId(),absoluteRefRows);
    6094        1771 :     transformAndWriteReindexableVector(vb->stateId(),tmpVectorInt,!timespan_p.contains("state"),
    6095        1771 :                                        inputOutputScanIntentIndexMap_p,
    6096        1771 :                                        outputMsCols_p->stateId(),absoluteRefRows);
    6097        1771 :     transformAndWriteReindexableVector(vb->antenna1(),tmpVectorInt,false,
    6098        1771 :                                        inputOutputAntennaIndexMap_p,
    6099        1771 :                                        outputMsCols_p->antenna1(),absoluteRefRows);
    6100        1771 :     transformAndWriteReindexableVector(vb->antenna2(),tmpVectorInt,false,
    6101        1771 :                                        inputOutputAntennaIndexMap_p,
    6102        1771 :                                        outputMsCols_p->antenna2(),absoluteRefRows);
    6103             : 
    6104             :     // Not Re-indexable Columns
    6105        1771 :     transformAndWriteNotReindexableVector(vb->scan(),tmpVectorInt,!timespan_p.contains("scan"),outputMsCols_p->scanNumber(),absoluteRefRows);
    6106        1771 :     transformAndWriteNotReindexableVector(vb->processorId(),tmpVectorInt,false,outputMsCols_p->processorId(),absoluteRefRows);
    6107        1771 :     transformAndWriteNotReindexableVector(vb->feed1(),tmpVectorInt,false,outputMsCols_p->feed1(),absoluteRefRows);
    6108        1771 :     transformAndWriteNotReindexableVector(vb->feed2(),tmpVectorInt,false,outputMsCols_p->feed2(),absoluteRefRows);
    6109        1771 :     transformAndWriteNotReindexableVector(vb->time(),tmpVectorDouble,false,outputMsCols_p->time(),absoluteRefRows);
    6110        1771 :     transformAndWriteNotReindexableVector(vb->timeCentroid(),tmpVectorDouble,false,outputMsCols_p->timeCentroid(),absoluteRefRows);
    6111        1771 :     transformAndWriteNotReindexableVector(vb->timeInterval(),tmpVectorDouble,false,outputMsCols_p->interval(),absoluteRefRows);
    6112             : 
    6113             :     // Special case for vectors that have to be averaged
    6114        1771 :     if (combinespws_p)
    6115             :     {
    6116           0 :         mapAndAverageVector(vb->flagRow(),tmpVectorbool);
    6117           0 :         outputMsCols_p->flagRow().putColumnCells(absoluteRefRows, tmpVectorbool);
    6118             : 
    6119             :         // jagonzal: We average exposures by default, if they are the same we obtain the same results
    6120           0 :         mapAndAverageVector(vb->exposure(),tmpVectorDouble);
    6121           0 :         outputMsCols_p->exposure().putColumnCells(absoluteRefRows, tmpVectorDouble);
    6122             :     }
    6123             :     else
    6124             :     {
    6125        1771 :         transformAndWriteNotReindexableVector(vb->flagRow(),tmpVectorbool,false,outputMsCols_p->flagRow(),absoluteRefRows);
    6126        1771 :         transformAndWriteNotReindexableVector(vb->exposure(),tmpVectorDouble,false,outputMsCols_p->exposure(),absoluteRefRows);
    6127             :     }
    6128             : 
    6129        1771 :     if (combinespws_p)
    6130             :     {
    6131           0 :         Matrix<Double> tmpUvw(IPosition(2,3,rowRef.nrows()),0.0);
    6132           0 :         Matrix<Float> tmpMatrixFloat(IPosition(2,vb->nCorrelations(),rowRef.nrows()),0.0);
    6133             : 
    6134           0 :         mapMatrix(vb->uvw(),tmpUvw);
    6135           0 :         writeMatrix(tmpUvw,outputMsCols_p->uvw(),rowRef,nspws_p);
    6136             : 
    6137             :         // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
    6138           0 :         if (not spectrumTransformation_p)
    6139             :         {
    6140           0 :             if (newWeightFactorMap_p.size() > 0)
    6141             :             {
    6142           0 :                 mapAndScaleMatrix(vb->weight(),tmpMatrixFloat,newWeightFactorMap_p,vb->spectralWindows());
    6143           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
    6144             :             }
    6145             :             else
    6146             :             {
    6147             :                 // jagonzal: According to dpetry we have to copy weights from the first SPW
    6148             :                 // This is justified since the rows to be combined _must_ be from the
    6149             :                 // same baseline and therefore have the same UVW coordinates in the MS (in meters).
    6150             :                 // They could therefore be regarded to also have the same WEIGHT, at least to
    6151             :                 // a good approximation.
    6152           0 :                 mapMatrix(vb->weight(),tmpMatrixFloat);
    6153           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->weight(),rowRef,nspws_p);
    6154             :             }
    6155             : 
    6156             : 
    6157             :             // Sigma must be redefined to 1/weight when corrected data becomes data
    6158           0 :             if (correctedToData_p)
    6159             :             {
    6160           0 :                 arrayTransformInPlace(tmpMatrixFloat, vi::AveragingTvi2::weightToSigma);
    6161           0 :                 outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
    6162           0 :                 writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6163             :             }
    6164             :             else
    6165             :             {
    6166           0 :                 if (newSigmaFactorMap_p.size() > 0)
    6167             :                 {
    6168           0 :                     mapAndScaleMatrix(vb->sigma(),tmpMatrixFloat,newSigmaFactorMap_p,vb->spectralWindows());
    6169           0 :                     outputMsCols_p->sigma().putColumnCells(rowRef, tmpMatrixFloat);
    6170           0 :                     writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6171             :                 }
    6172             :                 else
    6173             :                 {
    6174             :                     // jagonzal: According to dpetry we have to copy weights from the first SPW
    6175             :                     // This is justified since the rows to be combined _must_ be from the
    6176             :                     // same baseline and therefore have the same UVW coordinates in the MS (in meters).
    6177             :                     // They could therefore be regarded to also have the same WEIGHT, at least to
    6178             :                     // a good approximation.
    6179           0 :                     mapMatrix(vb->sigma(),tmpMatrixFloat);
    6180           0 :                     writeMatrix(tmpMatrixFloat,outputMsCols_p->sigma(),rowRef,nspws_p);
    6181             :                 }
    6182             :             }
    6183             :         }
    6184             : 
    6185           0 :     }
    6186             :     else
    6187             :     {
    6188        1771 :         writeMatrix(vb->uvw(),outputMsCols_p->uvw(),rowRef,nspws_p);
    6189             : 
    6190             :         // WEIGHT/SIGMA are defined as the median of WEIGHT_SPECTRUM / SIGMA_SPECTRUM in the case of SPECTRUM transformation
    6191        1771 :         if (not spectrumTransformation_p)
    6192             :         {
    6193        1182 :             if (correctedToData_p) {
    6194             : 
    6195             :               // weight -> weight
    6196        1080 :                 Matrix<Float> weights = vb->weight();
    6197        1080 :                 if (newWeightFactorMap_p.size() > 0)
    6198             :                 {
    6199           0 :                     if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6200           0 :                             (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6201             :                     {
    6202           0 :                          weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
    6203             :                     }
    6204             :                 }
    6205        1080 :                 writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
    6206             : 
    6207             :                 // weight -> sigma
    6208        1080 :                 arrayTransformInPlace(weights, vi::AveragingTvi2::weightToSigma);
    6209        1080 :                 writeMatrix(weights,outputMsCols_p->sigma(),rowRef,nspws_p);
    6210             : 
    6211        1080 :             }
    6212         102 :             else if(!bothDataColumnsAreOutput_p)
    6213             :             {
    6214             :                 // sigma -> sigma
    6215          30 :                 Matrix<Float> sigma = vb->sigma();
    6216          30 :                 if (newSigmaFactorMap_p.size() > 0)
    6217             :                 {
    6218           0 :                     if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
    6219           0 :                             (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6220             :                     {
    6221           0 :                         sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6222             :                     }
    6223             :                 }
    6224          30 :                 writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
    6225             : 
    6226             :                 // sigma -> weight
    6227          30 :                 arrayTransformInPlace(sigma, vi::AveragingTvi2::sigmaToWeight);
    6228          30 :                 writeMatrix(sigma, outputMsCols_p->weight(), rowRef, nspws_p);
    6229          30 :             }
    6230             :             // If both DATA and DATA_CORRECTED are input and output then
    6231             :             // SIGMA(_SPECTRUM) and WEIGHT(_SPECTRUM) should maintain their alignment
    6232             :             // with DATA and CORRECTED_DATA, respectively and nothing is done. See CAS-11139
    6233             :             else
    6234             :             {
    6235             :                 // weight -> weight
    6236          72 :                 Matrix<Float> weights = vb->weight();
    6237          72 :                 if (newWeightFactorMap_p.size() > 0)
    6238             :                 {
    6239           0 :                     if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6240           0 :                             (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6241             :                     {
    6242           0 :                          weights *= newWeightFactorMap_p[vb->spectralWindows()(0)];
    6243             :                     }
    6244             :                 }
    6245          72 :                 writeMatrix(weights,outputMsCols_p->weight(),rowRef,nspws_p);
    6246             : 
    6247             :                 // sigma -> sigma
    6248          72 :                 Matrix<Float> sigma = vb->sigma();
    6249          72 :                 if (newSigmaFactorMap_p.size() > 0)
    6250             :                 {
    6251           0 :                     if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0)) != newSigmaFactorMap_p.end()) and
    6252           0 :                             (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6253             :                     {
    6254           0 :                         sigma *= newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6255             :                     }
    6256             :                 }
    6257          72 :                 writeMatrix(sigma,outputMsCols_p->sigma(),rowRef,nspws_p);
    6258          72 :             }
    6259             :         }
    6260             :     }
    6261             : 
    6262        3542 :     return;
    6263        1771 : }
    6264             : 
    6265             : // ------------------------------------------------------------------------------------
    6266             : //
    6267             : // ------------------------------------------------------------------------------------
    6268       15939 : template <class T> void MSTransformManager::transformAndWriteNotReindexableVector(        const Vector<T> &inputVector,
    6269             :                                                                                                                                                                         Vector<T> &outputVector,
    6270             :                                                                                                                                                                         bool constant,
    6271             :                                                                                                                                                                         ScalarColumn<T> &outputCol,
    6272             :                                                                                                                                                                         RefRows &rowReference)
    6273             : {
    6274       15939 :         bool transformed = transformNotReindexableVector(inputVector,outputVector,constant);
    6275             : 
    6276       15939 :         if (transformed)
    6277             :         {
    6278           0 :                 outputCol.putColumnCells(rowReference, outputVector);
    6279             :         }
    6280             :         else
    6281             :         {
    6282       15939 :                 outputCol.putColumnCells(rowReference, inputVector);
    6283             :         }
    6284             : 
    6285       15939 :         return;
    6286             : };
    6287             : 
    6288             : // ------------------------------------------------------------------------------------
    6289             : //
    6290             : // ------------------------------------------------------------------------------------
    6291       10626 : template <class T> void MSTransformManager::transformAndWriteReindexableVector(   const Vector<T> &inputVector,
    6292             :                                                                                                                         Vector<T> &outputVector,
    6293             :                                                                                                                         bool constant,
    6294             :                                                                                                                         map<uInt,uInt> &inputOutputIndexMap,
    6295             :                                                                                                                         ScalarColumn<T> &outputCol,
    6296             :                                                                                                                         RefRows &rowReference)
    6297             : {
    6298       10626 :         bool transformed = transformReindexableVector(inputVector,outputVector,constant,inputOutputIndexMap);
    6299             : 
    6300       10626 :         if (transformed)
    6301             :         {
    6302           8 :                 outputCol.putColumnCells(rowReference, outputVector);
    6303             :         }
    6304             :         else
    6305             :         {
    6306       10618 :                 outputCol.putColumnCells(rowReference, inputVector);
    6307             :         }
    6308             : 
    6309       10626 :         return;
    6310             : };
    6311             : 
    6312             : // ------------------------------------------------------------------------------------
    6313             : //
    6314             : // ------------------------------------------------------------------------------------
    6315        1771 : bool MSTransformManager::transformDDIVector(const Vector<Int> &inputVector,Vector<Int> &outputVector)
    6316             : {
    6317        1771 :         bool transformed = true;
    6318             : 
    6319        1771 :         if ((combinespws_p) or (nspws_p > 1))
    6320             :         {
    6321           0 :                 if (nspws_p > 1)
    6322             :                 {
    6323           0 :                         uInt absoluteIndex = 0;
    6324           0 :                         for (uInt index=0; index<rowIndex_p.size();index++)
    6325             :                         {
    6326           0 :                                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6327             :                                 {
    6328           0 :                                         outputVector(absoluteIndex) = ddiStart_p + spwIndex;
    6329           0 :                                         absoluteIndex += 1;
    6330             :                                 }
    6331             :                         }
    6332             :                 }
    6333             :                 else
    6334             :                 {
    6335           0 :                         outputVector = ddiStart_p;
    6336             :                 }
    6337           0 :         }
    6338             :         else
    6339             :         {
    6340        1771 :                 transformed = transformReindexableVector(inputVector,outputVector,true,inputOutputDDIndexMap_p);
    6341             :         }
    6342             : 
    6343        1771 :         return transformed;
    6344             : }
    6345             : 
    6346             : // ------------------------------------------------------------------------------------
    6347             : //
    6348             : // ------------------------------------------------------------------------------------
    6349           0 : void MSTransformManager::mapAndAverageVector(   const Vector<Double> &inputVector,
    6350             :                                                                                                 Vector<Double> &outputVector)
    6351             : {
    6352           0 :         Double vec_average = 0;
    6353           0 :         vector<uInt> baselineRows;
    6354           0 :         uInt row, counts, absoluteIndex = 0;
    6355           0 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6356             :         {
    6357             :                 // Get baseline rows vector
    6358           0 :                 baselineRows = iter->second;
    6359             : 
    6360             :                 // Compute combined value from each SPW
    6361           0 :                 counts = 0;
    6362             : 
    6363           0 :                 for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6364             :                 {
    6365           0 :                         row = *iter_row;
    6366           0 :                         if (counts == 0)
    6367             :                         {
    6368           0 :                                 vec_average = inputVector(row);
    6369             :                         }
    6370             :                         else
    6371             :                         {
    6372           0 :                                 vec_average += inputVector(row);
    6373             :                         }
    6374             : 
    6375           0 :                         counts += 1;
    6376             :                 }
    6377             : 
    6378             :                 // Normalize value
    6379           0 :                 if (counts) vec_average /= counts;
    6380             : 
    6381             :                 // Set value in output vector
    6382           0 :                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6383             :                 {
    6384           0 :                         outputVector(absoluteIndex) = vec_average;
    6385           0 :                         absoluteIndex += 1;
    6386             :                 }
    6387             :         }
    6388             : 
    6389           0 :         return;
    6390           0 : }
    6391             : 
    6392             : // ------------------------------------------------------------------------------------
    6393             : //
    6394             : // ------------------------------------------------------------------------------------
    6395           0 : void MSTransformManager::mapAndAverageVector(   const Vector<bool> &inputVector,
    6396             :                                                                                                 Vector<bool> &outputVector)
    6397             : {
    6398           0 :         bool vec_average = false;
    6399           0 :         vector<uInt> baselineRows;
    6400           0 :         uInt row, counts, absoluteIndex = 0;
    6401           0 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6402             :         {
    6403             :                 // Get baseline rows vector
    6404           0 :                 baselineRows = iter->second;
    6405             : 
    6406             :                 // Compute combined value from each SPW
    6407           0 :                 counts = 0;
    6408             : 
    6409           0 :                 for (auto iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6410             :                 {
    6411           0 :                         row = *iter_row;
    6412           0 :                         if (counts == 0)
    6413             :                         {
    6414           0 :                                 vec_average = inputVector(row);
    6415             :                         }
    6416             :                         else
    6417             :                         {
    6418           0 :                                 vec_average &= inputVector(row);
    6419             :                         }
    6420             :                 }
    6421             : 
    6422             :                 // Set value in output vector
    6423           0 :                 for (uInt spwIndex=0;spwIndex < nspws_p; spwIndex++)
    6424             :                 {
    6425           0 :                         outputVector(absoluteIndex) = vec_average;
    6426           0 :                         absoluteIndex += 1;
    6427             :                 }
    6428             :         }
    6429             : 
    6430           0 :         return;
    6431           0 : }
    6432             : 
    6433             : 
    6434             : // -----------------------------------------------------------------------------------
    6435             : // Fill the data from an input matrix with shape [nCol,nBaselinesxnSPWs] into an
    6436             : // output matrix with shape [nCol,nBaselines] accumulating the averaging from all SPWS
    6437             : // -----------------------------------------------------------------------------------
    6438             : template <class T> void MSTransformManager::mapAndAverageMatrix(  const Matrix<T> &inputMatrix,
    6439             :                                                                                                                                                 Matrix<T> &outputMatrix,
    6440             :                                                                                                                                                 bool convolveFlags,
    6441             :                                                                                                                                                 vi::VisBuffer2 *vb)
    6442             : {
    6443             :         // Get number of columns
    6444             :         uInt nCols = outputMatrix.shape()(0);
    6445             : 
    6446             :     // Access FLAG_ROW in case we need to convolute the average
    6447             :         Vector<bool> flags;
    6448             :         if (convolveFlags) flags = vb->flagRow();
    6449             : 
    6450             :     // Fill output array with the combined data from each SPW
    6451             :         uInt row;
    6452             :         uInt baseline_index = 0;
    6453             :         Double normalizingFactor = 0;
    6454             :         Double contributionFactor = 0;
    6455             :         vector<uInt> baselineRows;
    6456             :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6457             :         {
    6458             :                 // Get baseline rows vector
    6459             :                 baselineRows = iter->second;
    6460             : 
    6461             :                 // Reset normalizing factor
    6462             :                 normalizingFactor = 0;
    6463             : 
    6464             :                 // Compute combined value from each SPW
    6465             :                 for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    6466             :                 {
    6467             :                         row = *iter_row;
    6468             :                         if (convolveFlags)
    6469             :                         {
    6470             :                                 contributionFactor = !flags(row);
    6471             :                         }
    6472             :                         else
    6473             :                         {
    6474             :                                 contributionFactor = 1;
    6475             :                         }
    6476             : 
    6477             :                         for (uInt col = 0; col < nCols; col++)
    6478             :                         {
    6479             :                                 outputMatrix(col,baseline_index) += contributionFactor*inputMatrix(col,row);
    6480             :                         }
    6481             : 
    6482             :                         normalizingFactor += contributionFactor;
    6483             :                 }
    6484             : 
    6485             :                 // Normalize accumulated value
    6486             :                 if (normalizingFactor>0)
    6487             :                 {
    6488             :                         for (uInt col = 0; col < nCols; col++)
    6489             :                         {
    6490             :                                 outputMatrix(col,baseline_index) /= normalizingFactor;
    6491             :                         }
    6492             :                 }
    6493             : 
    6494             :                 baseline_index += 1;
    6495             :         }
    6496             : 
    6497             :         return;
    6498             : }
    6499             : 
    6500             : // -----------------------------------------------------------------------
    6501             : //
    6502             : // -----------------------------------------------------------------------
    6503           0 : template <class T> void MSTransformManager::mapAndScaleMatrix(    const Matrix<T> &inputMatrix,
    6504             :                                                                                                                                                 Matrix<T> &outputMatrix,
    6505             :                                                                                                                                                 map<uInt,T> scaleMap,
    6506             :                                                                                                                                                 Vector<Int> spws)
    6507             : {
    6508             :         // Reset output Matrix
    6509           0 :         outputMatrix = 0;
    6510             : 
    6511             :         // Get number of columns
    6512           0 :         uInt nCols = outputMatrix.shape()(0);
    6513             : 
    6514             :     // Fill output array with the combined data from each SPW
    6515             :         Int spw;
    6516             :         uInt row;
    6517           0 :         uInt baseline_index = 0;
    6518           0 :         vector<uInt> baselineRows;
    6519             :         T contributionFactor;
    6520           0 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    6521             :         {
    6522             :                 // Get baseline rows vector
    6523           0 :                 baselineRows = iter->second;
    6524             : 
    6525             :                 // Reset normalizing factor
    6526             : 
    6527             :                 // Get value from first SPW (this is for Weight and Sigma and cvel is doing it so)
    6528           0 :                 row = baselineRows.at(0);
    6529           0 :                 spw = spws(row);
    6530           0 :                 if (scaleMap.find(spw) != scaleMap.end())
    6531             :                 {
    6532           0 :                         contributionFactor = scaleMap[spw];
    6533             :                 }
    6534             :                 else
    6535             :                 {
    6536           0 :                         contributionFactor = 1;
    6537             :                 }
    6538             : 
    6539           0 :                 for (uInt col = 0; col < nCols; col++)
    6540             :                 {
    6541           0 :                         outputMatrix(col,baseline_index) = contributionFactor*inputMatrix(col,row);
    6542             :                 }
    6543             : 
    6544           0 :                 baseline_index += 1;
    6545             :         }
    6546             : 
    6547           0 :         return;
    6548           0 : }
    6549             : 
    6550             : 
    6551             : // ----------------------------------------------------------------------------------------
    6552             : // Fill main (data) columns which have to be combined together to produce bigger SPWs
    6553             : // ----------------------------------------------------------------------------------------
    6554        1771 : void MSTransformManager::fillDataCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6555             : {
    6556        1771 :         ArrayColumn<bool> *outputFlagCol=NULL;
    6557        4760 :         for (dataColMap::iterator iter = dataColMap_p.begin();iter != dataColMap_p.end();iter++)
    6558             :         {
    6559             :                 // Get applicable *_SPECTRUM (copy constructor uses reference semantics)
    6560             :                 // If channel average or combine, otherwise no need to copy
    6561        2989 :                 const Cube<Float> &applicableSpectrum = getApplicableSpectrum(vb,iter->first);
    6562             : 
    6563             :                 // Apply transformations
    6564        2989 :                 switch (iter->first)
    6565             :                 {
    6566         691 :                         case MS::DATA:
    6567             :                         {
    6568         691 :                                 if (mainColumn_p == MS::DATA)
    6569             :                                 {
    6570         691 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6571         691 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6572             :                                 }
    6573             :                                 else
    6574             :                                 {
    6575           0 :                                         outputFlagCol = NULL;
    6576             :                                 }
    6577             : 
    6578         691 :                                 setTileShape(rowRef,outputMsCols_p->data());
    6579         691 :                                 transformCubeOfData(vb,rowRef,vb->visCube(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6580             : 
    6581         691 :                                 break;
    6582             :                         }
    6583        1689 :                         case MS::CORRECTED_DATA:
    6584             :                         {
    6585        1689 :                                 if (mainColumn_p == MS::CORRECTED_DATA)
    6586             :                                 {
    6587        1080 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6588        1080 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6589             :                                 }
    6590             :                                 else
    6591             :                                 {
    6592         609 :                                         outputFlagCol = NULL;
    6593             :                                 }
    6594             : 
    6595        1689 :                                 if (iter->second == MS::DATA)
    6596             :                                 {
    6597        1080 :                                         setTileShape(rowRef,outputMsCols_p->data());
    6598        1080 :                                         transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6599             :                                 }
    6600             :                                 else
    6601             :                                 {
    6602         609 :                                         setTileShape(rowRef,outputMsCols_p->correctedData());
    6603         609 :                                         transformCubeOfData(vb,rowRef,vb->visCubeCorrected(),outputMsCols_p->correctedData(), outputFlagCol,applicableSpectrum);
    6604             :                                 }
    6605             : 
    6606        1689 :                                 break;
    6607             :                         }
    6608         609 :                         case MS::MODEL_DATA:
    6609             :                         {
    6610         609 :                                 if (mainColumn_p == MS::MODEL_DATA)
    6611             :                                 {
    6612           0 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6613           0 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6614             :                                 }
    6615             :                                 else
    6616             :                                 {
    6617         609 :                                         outputFlagCol = NULL;
    6618             :                                 }
    6619             : 
    6620         609 :                                 if (produceModel_p)
    6621             :                                 {
    6622             :                                     // irrespective of wheter iter->second == MS::DATA
    6623             :                                     // or iter->second == MS::CORRECTED_DATA
    6624           0 :                                     setTileShape(rowRef,outputMsCols_p->modelData());
    6625           0 :                                     transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
    6626         609 :                                 } else if (iter->second == MS::DATA) {
    6627           0 :                                         setTileShape(rowRef,outputMsCols_p->data());
    6628           0 :                                         transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->data(), outputFlagCol,applicableSpectrum);
    6629             :                                 }
    6630             :                                 else
    6631             :                                 {
    6632         609 :                                         setTileShape(rowRef,outputMsCols_p->modelData());
    6633         609 :                                         transformCubeOfData(vb,rowRef,vb->visCubeModel(),outputMsCols_p->modelData(), outputFlagCol,applicableSpectrum);
    6634             :                                 }
    6635         609 :                                 break;
    6636             :                         }
    6637           0 :                         case MS::FLOAT_DATA:
    6638             :                         {
    6639           0 :                                 if (mainColumn_p == MS::FLOAT_DATA)
    6640             :                                 {
    6641           0 :                                         outputFlagCol = &(outputMsCols_p->flag());
    6642           0 :                                         setTileShape(rowRef,outputMsCols_p->flag());
    6643             :                                 }
    6644             :                                 else
    6645             :                                 {
    6646           0 :                                         outputFlagCol = NULL;
    6647             :                                 }
    6648             : 
    6649           0 :                                 setTileShape(rowRef,outputMsCols_p->floatData());
    6650           0 :                                 transformCubeOfData(vb,rowRef,vb->visCubeFloat(),outputMsCols_p->floatData(), outputFlagCol,applicableSpectrum);
    6651             : 
    6652           0 :                                 break;
    6653             :                         }
    6654           0 :                         case MS::LAG_DATA:
    6655             :                         {
    6656             :                                 // jagonzal: TODO
    6657           0 :                                 break;
    6658             :                         }
    6659           0 :                         default:
    6660             :                         {
    6661             :                                 // jagonzal: TODO
    6662           0 :                                 break;
    6663             :                         }
    6664             :                 }
    6665             :         }
    6666             : 
    6667             :     // Special case for flag category
    6668        1771 :     if (inputFlagCategoryAvailable_p)
    6669             :     {
    6670           0 :         if (spectrumReshape_p)
    6671             :         {
    6672           0 :                 IPosition transformedCubeShape = getShape(); //[nC,nF,nR]
    6673           0 :                 IPosition inputFlagCategoryShape = vb->flagCategory().shape(); // [nC,nF,nCategories,nR]
    6674           0 :                 IPosition flagCategoryShape(4,  inputFlagCategoryShape(1),
    6675           0 :                                                                                 transformedCubeShape(2),
    6676           0 :                                                                                 inputFlagCategoryShape(2),
    6677           0 :                                                                                 transformedCubeShape(2));
    6678           0 :                 Array<bool> flagCategory(flagCategoryShape,false);
    6679             : 
    6680           0 :                 outputMsCols_p->flagCategory().putColumnCells(rowRef, flagCategory);
    6681           0 :         }
    6682             :         else
    6683             :         {
    6684           0 :                 outputMsCols_p->flagCategory().putColumnCells(rowRef, vb->flagCategory());
    6685             :         }
    6686             :     }
    6687             : 
    6688        1771 :         return;
    6689             : }
    6690             : 
    6691             : // ----------------------------------------------------------------------------------------
    6692             : // Fill weight cols (WEIGHT_SPECTRUM and SIGMA_SPECTRUM) as well as WEIGHT/SIGMA which have to be derived from it using median
    6693             : // ----------------------------------------------------------------------------------------
    6694        1771 : void MSTransformManager::fillWeightCols(vi::VisBuffer2 *vb,RefRows &rowRef)
    6695             : {
    6696             :         // WEIGHT_SPECTRUM and SIGMA_SPECTRUM are only filled if requested or when WEIGHT_SPECTRUM is present in the input MS
    6697             :         // But WEIGHT/SIGMA have always to be derived from in-memory WEIGHT_SPECTRUM/SIGMA_SPECTRUM
    6698        1771 :         if (flushWeightSpectrum_p or spectrumTransformation_p or userBufferMode_p)
    6699             :         {
    6700             :                 // Switch aux Weight propagation off
    6701         591 :                 propagateWeights(false);
    6702             : 
    6703             :                 // Switch average and smooth kernels
    6704         591 :                 setChannelAverageKernel(MSTransformations::flagCumSumNonZero);
    6705         591 :                 setSmoothingKernel(MSTransformations::plainSmoothSpectrum);
    6706         591 :                 setSmoothingFourierKernel(MSTransformations::plainSmoothSpectrum);
    6707             : 
    6708             :                 // Dummy auxiliary weightSpectrum
    6709         591 :                 const Cube<Float> applicableSpectrum;
    6710             : 
    6711         591 :                 if (spectrumTransformation_p)
    6712             :                 {
    6713             :                         // For SPW separation:
    6714             :                         // Prepare RowReference for spectrum transformations
    6715             :                         // (all data is flushed at once instead of blocks)
    6716         589 :                         RefRows rowRefSpectrum(rowRef.firstRow(), rowRef.firstRow() + nRowsToAdd_p-1);
    6717             : 
    6718             :                         // Switch on buffer mode
    6719         589 :                         Cube<Float> transformedSpectrum;
    6720         589 :                         Cube<bool> transformedFlag;
    6721         589 :                         if (not userBufferMode_p)
    6722             :                         {
    6723         589 :                                 setBufferMode(true);
    6724         589 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6725         589 :                                 transformedSpectrum.resize(getShape(),false);
    6726         589 :                                 weightSpectrum_p = &transformedSpectrum;
    6727         589 :                                 transformedFlag.resize(getShape(),false);
    6728         589 :                                 flagCube_p = &transformedFlag; // Not used for the output but to extract the average/median
    6729             :                         }
    6730             : 
    6731             : 
    6732             :                         // Multiple column operation
    6733         589 :                         if (doingData_p and doingCorrected_p)
    6734             :                         {
    6735             :                                 // Transform WEIGHT_SPECTRUM but don't derive SIGMA_SPECTRUM from it
    6736         537 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6737             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6738             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6739         537 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6740             : 
    6741             :                                 // Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
    6742         537 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
    6743             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6744             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6745         537 :                                                                                         MSTransformations::transformWeightIntoSigma,flushWeightSpectrum_p);
    6746             :                         }
    6747             :                         // In case of time average we can use directly WEIGHT_SPECTRUM because
    6748             :                         // AveragingTvi2 derives it from the input SIGMA_SPECTRUM or WEIGHT_SPECTRUM
    6749             :                         // depending on the selected DATA column
    6750          52 :                         else if (timeAverage_p)
    6751             :                         {
    6752             :                                 // Transform WEIGHT_SPECTRUM
    6753          12 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6754             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6755             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6756          12 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6757             : 
    6758             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6759          12 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6760             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6761             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6762          12 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6763             :                         }
    6764             :                         // DATA to DATA: Convert SIGMA_SPECTRUM to WEIGHT format, transform it and derive SIGMA_SPECTRUM from it
    6765          40 :                         else if (doingData_p)
    6766             :                         {
    6767             :                                 // Transform WEIGHT_SPECTRUM
    6768          40 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFromSigmaSpectrum(vb),
    6769             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6770             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6771          40 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6772             : 
    6773             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6774          40 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6775             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6776             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6777          40 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6778             :                         }
    6779             :                         // CORRECTED to DATA: Transform WEIGHT_SPECTRUM and derive SIGMA_SPECTRUM from it
    6780           0 :                         else if (doingCorrected_p) // CORRECTED to DATA
    6781             :                         {
    6782             :                                 // Transform WEIGHT_SPECTRUM
    6783           0 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6784             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6785             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6786           0 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6787             : 
    6788             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6789           0 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6790             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6791             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6792           0 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6793             :                         }
    6794             :                         // MODEL to DATA: Calculate WEIGHT_SPECTRUM using FLAG and derive SIGMA_SPECTRUM from it
    6795           0 :                         else if (doingModel_p)
    6796             :                         {
    6797             :                                 // Transform WEIGHT_SPECTRUM
    6798           0 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,getWeightSpectrumFlat(vb),
    6799             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),
    6800             :                                                                                         getOutputWeightColumn(vb,MS::WEIGHT),
    6801           0 :                                                                                         MSTransformations::transformWeight,flushWeightSpectrum_p);
    6802             : 
    6803             :                                 // Derive SIGMA_SPECTRUM from WEIGHT_SPECTRUM
    6804           0 :                                 transformAndWriteSpectrum(      vb,rowRefSpectrum,vb->weightSpectrum(),
    6805             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),
    6806             :                                                                                         getOutputWeightColumn(vb,MS::SIGMA),
    6807           0 :                                                                                         MSTransformations::weightIntoSigma,flushWeightSpectrum_p);
    6808             :                         }
    6809             : 
    6810             :                         // Switch off buffer mode
    6811         589 :                         if (not userBufferMode_p)
    6812             :                         {
    6813         589 :                                 setBufferMode(false);
    6814         589 :                                 weightSpectrum_p = NULL;
    6815             :                         }
    6816         589 :                 }
    6817             :                 // Within AveragingTvi2 SIGMA_SPECTRUM is already re-defined to 1/sqrt(WEIGHT_SPECTRUM) if CORRECTED->DATA
    6818             :                 // or obtained from the input SIGMA_SPECTRUM in the case of DATA->DATA or multiple column operation
    6819           2 :                 else if (timeAverage_p)
    6820             :                 {
    6821             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6822           0 :                         if (userBufferMode_p)
    6823             :                         {
    6824           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6825             :                         }
    6826             :                         else
    6827             :                         {
    6828           0 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6829             :                         }
    6830           0 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6831             : 
    6832           0 :                         if (userBufferMode_p)
    6833             :                         {
    6834           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6835             :                         }
    6836             :                         else
    6837             :                         {
    6838           0 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6839             :                         }
    6840           0 :                         transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6841             :                 }
    6842             :                 // When CORRECTED becomes DATA, then SIGMA_SPECTRUM has to be re-defined to 1/sqrt(WEIGHT_SPECTRUM)
    6843           2 :                 else if (correctedToData_p)
    6844             :                 {
    6845             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6846           0 :                         if (userBufferMode_p)
    6847             :                         {
    6848           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6849             :                         }
    6850             :                         else
    6851             :                         {
    6852           0 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6853             :                         }
    6854           0 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6855             : 
    6856           0 :                         if (userBufferMode_p)
    6857             :                         {
    6858           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6859             :                         }
    6860             :                         else
    6861             :                         {
    6862           0 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6863             :                         }
    6864             :                         // VI/VB only allocates and populates sigmaSpectrum on request
    6865             :                         // But its contents are not usable for this case
    6866             :                         // So we should just create a local storage
    6867           0 :                         Cube<Float> sigmaSpectrum;
    6868           0 :                         sigmaSpectrum = vb->weightSpectrum(); // Copy constructor does not use reference semantics, but deep copy
    6869             :                         // Apply transformation
    6870           0 :                         arrayTransformInPlace(sigmaSpectrum, vi::AveragingTvi2::weightToSigma);
    6871             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6872           0 :                         transformCubeOfData(vb,rowRef,sigmaSpectrum,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6873           0 :                 }
    6874             :                 // Pure split operation
    6875             :                 else
    6876             :                 {
    6877             :                         // TransformCubeOfData is either copyCubeOfData or separateCubeOfData
    6878           2 :                         if (userBufferMode_p)
    6879             :                         {
    6880           0 :                                 dataBuffer_p = MSTransformations::weightSpectrum;
    6881             :                         }
    6882             :                         else
    6883             :                         {
    6884           2 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM));
    6885             :                         }
    6886           2 :                         transformCubeOfData(vb,rowRef,vb->weightSpectrum(),getOutputWeightColumn(vb,MS::WEIGHT_SPECTRUM),NULL,applicableSpectrum);
    6887             : 
    6888           2 :                         if (userBufferMode_p)
    6889             :                         {
    6890           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6891             :                         }
    6892             :                         else
    6893             :                         {
    6894           2 :                                 setTileShape(rowRef,getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM));
    6895             :                         }
    6896           2 :                         transformCubeOfData(vb,rowRef,vb->sigmaSpectrum(),getOutputWeightColumn(vb,MS::SIGMA_SPECTRUM),NULL,applicableSpectrum);
    6897             :                 }
    6898             : 
    6899             :                 // Switch aux Weight propagation on
    6900         591 :                 propagateWeights(propagateWeights_p);
    6901             : 
    6902             :                 // Reset average and smooth kernels
    6903         591 :                 setChannelAverageKernel(weightmode_p);
    6904         591 :                 setSmoothingKernel(smoothmode_p);
    6905         591 :     setSmoothingFourierKernel(MSTransformations::plainSmooth);
    6906         591 :         }
    6907             : 
    6908        1771 :         return;
    6909             : }
    6910             : 
    6911             : 
    6912             : // ----------------------------------------------------------------------------------------
    6913             : // Set tile shape
    6914             : // ----------------------------------------------------------------------------------------
    6915        4764 : template <class T> void MSTransformManager::setTileShape( RefRows &rowRef,
    6916             :                                                                                                                         ArrayColumn<T> &outputDataCol)
    6917             : {
    6918        4764 :         IPosition outputCubeShape = getShape();
    6919        4764 :         size_t nCorr = outputCubeShape(0);
    6920        4764 :         size_t nChan = outputCubeShape(1);
    6921        4764 :         ssize_t nRows = 1048576 / (sizeof(T)*nCorr*nChan);
    6922        4764 :         IPosition outputPlaneShape(2,nCorr,nChan);
    6923        4764 :         IPosition tileShape(3,nCorr,nChan,nRows);
    6924             : 
    6925        4764 :         outputDataCol.setShape(rowRef.firstRow(),outputPlaneShape,tileShape);
    6926             : 
    6927        9528 :         return;
    6928        4764 : }
    6929             : 
    6930             : // explicit instatiation for the use from SDMSManager
    6931             : template void MSTransformManager::setTileShape<Float>(RefRows &, ArrayColumn<Float> &);
    6932             : template void MSTransformManager::setTileShape<bool>(RefRows &, ArrayColumn<bool> &);
    6933             : template void MSTransformManager::setTileShape<Complex>(RefRows &, ArrayColumn<Complex> &);
    6934             : 
    6935             : // ----------------------------------------------------------------------------------------
    6936             : //
    6937             : // ----------------------------------------------------------------------------------------
    6938        1178 : void MSTransformManager::transformAndWriteSpectrum(     vi::VisBuffer2 *vb,
    6939             :                                                                                                         RefRows &rowRef,
    6940             :                                                                                                         const Cube<Float> &inputSpectrum,
    6941             :                                                                                                         ArrayColumn<Float> &outputCubeCol,
    6942             :                                                                                                         ArrayColumn<Float> &outputMatrixCol,
    6943             :                                                                                                         MSTransformations::weightTransformation weightTransformation,
    6944             :                                                                                                         bool  /* flushSpectrumCube */)
    6945             : {
    6946             :         // Dummy auxiliary weightSpectrum
    6947        1178 :         const Cube<Float> applicableSpectrum;
    6948             : 
    6949             :         // Check if weight scaling has to be applied
    6950        1178 :         Float weightScale = 0, sigmaScale = 0;
    6951        1178 :         if (refFrameTransformation_p)
    6952             :         {
    6953           0 :                 if ( (newWeightFactorMap_p.find(vb->spectralWindows()(0))  != newWeightFactorMap_p.end()) and
    6954           0 :                                 (newWeightFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6955             :                 {
    6956           0 :                         weightScale = newWeightFactorMap_p[vb->spectralWindows()(0)];
    6957             :                 }
    6958             : 
    6959           0 :                 if ( (newSigmaFactorMap_p.find(vb->spectralWindows()(0))  != newSigmaFactorMap_p.end()) and
    6960           0 :                                 (newSigmaFactorMap_p[vb->spectralWindows()(0)] != 1) )
    6961             :                 {
    6962           0 :                         sigmaScale = newSigmaFactorMap_p[vb->spectralWindows()(0)];
    6963             :                 }
    6964             :         }
    6965             : 
    6966             :         // Apply transformations
    6967        1178 :         switch (weightTransformation)
    6968             :         {
    6969         589 :                 case MSTransformations::transformWeight:
    6970             :                 {
    6971         589 :                         dataBuffer_p = MSTransformations::weightSpectrum;
    6972         589 :                         transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6973             : 
    6974         589 :                         if (weightScale > 0) *weightSpectrum_p *= weightScale;
    6975             : 
    6976         589 :                         break;
    6977             :                 }
    6978         537 :                 case MSTransformations::transformWeightIntoSigma:
    6979             :                 {
    6980         537 :                         if (userBufferMode_p)
    6981             :                         {
    6982           0 :                                 dataBuffer_p = MSTransformations::sigmaSpectrum;
    6983           0 :                                 transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6984           0 :                                 arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
    6985             : 
    6986           0 :                                 if (sigmaScale > 0) *sigmaSpectrum_p *= sigmaScale;
    6987             :                         }
    6988             :                         else
    6989             :                         {
    6990         537 :                                 transformCubeOfData(vb,rowRef,inputSpectrum,outputCubeCol,NULL,applicableSpectrum);
    6991         537 :                                 arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
    6992             : 
    6993         537 :                                 if (sigmaScale > 0) *weightSpectrum_p *= sigmaScale;
    6994             :                         }
    6995             : 
    6996         537 :                         break;
    6997             :                 }
    6998          52 :                 case MSTransformations::weightIntoSigma:
    6999             :                 {
    7000          52 :                         if (userBufferMode_p)
    7001             :                         {
    7002             :                                 // WeightSpectrum is always transformed before sigmaSpectrum
    7003             :                                 // so copy weightSpectrum into sigmaSpectrum
    7004           0 :                                 sigmaSpectrum_p->operator =(*weightSpectrum_p);
    7005           0 :                                 arrayTransformInPlace (*sigmaSpectrum_p,vi::AveragingTvi2::weightToSigma);
    7006             : 
    7007             :                                 // No need to scale in this case as it already happened before
    7008             :                         }
    7009             :                         else
    7010             :                         {
    7011             :                                 // WeightSpectrum is always transformed before sigmaSpectrum
    7012             :                                 // so transform directly weightSpectrum into sigmaSpectrum
    7013          52 :                                 arrayTransformInPlace (*weightSpectrum_p,vi::AveragingTvi2::weightToSigma);
    7014             : 
    7015             :                                 // No need to scale in this case as it already happened before
    7016             :                         }
    7017          52 :                         break;
    7018             :                 }
    7019             :         }
    7020             : 
    7021             :         // Write resulting cube
    7022        1178 :         if ( (not userBufferMode_p) and flushWeightSpectrum_p)
    7023             :         {
    7024           0 :                 setTileShape(rowRef,outputCubeCol);
    7025           0 :                 writeCube(*weightSpectrum_p,outputCubeCol,rowRef);
    7026             :         }
    7027             : 
    7028             :         // Extract median matrix (nCorr x nRow)
    7029             :         // When separating SPWs this procedure computes the mean of each separated SPW
    7030             :         // Matrix<Float> medians = partialMedians(*weightSpectrum_p,IPosition(1,1),true);
    7031        1178 :         if (userBufferMode_p)
    7032             :         {
    7033           0 :                 switch (weightTransformation)
    7034             :                 {
    7035           0 :                         case MSTransformations::transformWeight:
    7036             :                         {
    7037           0 :                                 weight_p->operator =(vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p));
    7038           0 :                                 break;
    7039             :                         }
    7040           0 :                         case MSTransformations::transformWeightIntoSigma:
    7041             :                         {
    7042           0 :                                 sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
    7043           0 :                                 break;
    7044             :                         }
    7045           0 :                         case MSTransformations::weightIntoSigma:
    7046             :                         {
    7047           0 :                                 sigma_p->operator =(vi::AveragingTvi2::average(*sigmaSpectrum_p,*flagCube_p));
    7048           0 :                                 break;
    7049             :                         }
    7050             :                 }
    7051             :         }
    7052             :         else
    7053             :         {
    7054        1178 :                 Matrix<Float> means = vi::AveragingTvi2::average(*weightSpectrum_p,*flagCube_p);
    7055        1178 :                 writeMatrix(means,outputMatrixCol,rowRef,1);
    7056        1178 :         }
    7057             : 
    7058        2356 :         return;
    7059        1178 : }
    7060             : 
    7061             : // -----------------------------------------------------------------------
    7062             : // Get *_SPECTRUM column to use depending on the input col
    7063             : // -----------------------------------------------------------------------
    7064        2989 : const Cube<Float>& MSTransformManager::getApplicableSpectrum(vi::VisBuffer2 *vb, MS::PredefinedColumns datacol)
    7065             : {
    7066        2989 :         if (propagateWeights_p)
    7067             :         {
    7068          12 :                 switch (datacol)
    7069             :                 {
    7070          12 :                         case MS::DATA:
    7071             :                         {
    7072             :                                 // NOTE: There is room for optimization here if in the case of
    7073             :                                 // A.- Time average and single column operation
    7074             :                                 // B.- Single column in the input (George denied this)
    7075             :                                 // C.- Time average should not convert SIGMA_SPECTRUM to WEIGHT format if there is chan.avg downstream
    7076             :                                 // D.- SIGMA_SPECTRUM should be in WEIGHT format
    7077          12 :                                 return getWeightSpectrumFromSigmaSpectrum(vb);
    7078             :                                 break;
    7079             :                         }
    7080           0 :                         case MS::CORRECTED_DATA:
    7081             :                         {
    7082           0 :                                 return vb->weightSpectrum();
    7083             :                                 break;
    7084             :                         }
    7085           0 :                         case MS::MODEL_DATA:
    7086             :                         {
    7087             :                                 // Return either WEIGHT_SPECTRUM or SIGMA_SPECTRUM depending on the other accompany col
    7088           0 :                                 if (doingCorrected_p)
    7089             :                                 {
    7090           0 :                                         return vb->weightSpectrum();
    7091             :                                 }
    7092           0 :                                 else if (doingData_p)
    7093             :                                 {
    7094           0 :                                         return getWeightSpectrumFromSigmaSpectrum(vb);
    7095             :                                 }
    7096             :                                 // When doing only MODEL_DATA only FLAG cube is used, and applicable weightSpectrum must be flat unit
    7097             :                                 // The same convention is applied in VbAvg::accumulateElementForCubes for time average
    7098             :                                 else
    7099             :                                 {
    7100           0 :                                         return getWeightSpectrumFlat(vb);
    7101             :                                 }
    7102             : 
    7103             :                                 break;
    7104             :                         }
    7105           0 :                         default:
    7106             :                         {
    7107           0 :                                 return vb->weightSpectrum();
    7108             :                                 break;
    7109             :                         }
    7110             :                 }
    7111             :         }
    7112             :         else
    7113             :         {
    7114        2977 :                 return weightSpectrumCubeDummy_p;
    7115             :         }
    7116             : }
    7117             : 
    7118             : // -----------------------------------------------------------------------
    7119             : // Get output weight column
    7120             : // -----------------------------------------------------------------------
    7121        2364 : ArrayColumn<Float>&  MSTransformManager::getOutputWeightColumn(vi::VisBuffer2 *, MS::PredefinedColumns datacol)
    7122             : {
    7123        2364 :         if (userBufferMode_p)
    7124             :         {
    7125           0 :                 return dummyWeightCol_p;
    7126             :         }
    7127             :         else
    7128             :         {
    7129        2364 :                 switch (datacol)
    7130             :                 {
    7131         593 :                         case MS::WEIGHT_SPECTRUM:
    7132             :                         {
    7133         593 :                                 return outputMsCols_p->weightSpectrum();
    7134             :                                 break;
    7135             :                         }
    7136         593 :                         case MS::SIGMA_SPECTRUM:
    7137             :                         {
    7138         593 :                                 return outputMsCols_p->sigmaSpectrum();
    7139             :                                 break;
    7140             :                         }
    7141         589 :                         case MS::WEIGHT:
    7142             :                         {
    7143         589 :                                 return outputMsCols_p->weight();
    7144             :                                 break;
    7145             :                         }
    7146         589 :                         case MS::SIGMA:
    7147             :                         {
    7148         589 :                                 return outputMsCols_p->sigma();
    7149             :                                 break;
    7150             :                         }
    7151           0 :                         default:
    7152             :                         {
    7153           0 :                                 return outputMsCols_p->weight();
    7154             :                                 break;
    7155             :                         }
    7156             :                 }
    7157             :         }
    7158             : }
    7159             : 
    7160             : 
    7161             : // -----------------------------------------------------------------------
    7162             : // Pupulate weightSpectrum derived from sigmaSpectrum
    7163             : // -----------------------------------------------------------------------
    7164         589 : const Cube<Float>& MSTransformManager::getWeightSpectrumFromSigmaSpectrum(vi::VisBuffer2 *vb)
    7165             : {
    7166         589 :         if (weightSpectrumFromSigmaFilled_p)
    7167             :         {
    7168           0 :                 return weightSpectrumCube_p;
    7169             :         }
    7170             :         else
    7171             :         {
    7172         589 :                 weightSpectrumCube_p.resize(vb->getShape(),false);
    7173         589 :                 weightSpectrumCube_p = vb->sigmaSpectrum(); // = Operator makes a copy
    7174         589 :                 arrayTransformInPlace (weightSpectrumCube_p,vi::AveragingTvi2::sigmaToWeight);
    7175         589 :                 weightSpectrumFromSigmaFilled_p = true;
    7176         589 :                 return weightSpectrumCube_p;
    7177             :         }
    7178             : }
    7179             : 
    7180             : // -----------------------------------------------------------------------
    7181             : // Populate a synthetic flat unit weightSpectrum to be use for MODEL_DATA
    7182             : // -----------------------------------------------------------------------
    7183           0 : const Cube<Float>& MSTransformManager::getWeightSpectrumFlat(vi::VisBuffer2 *vb)
    7184             : {
    7185           0 :         if (weightSpectrumFlatFilled_p)
    7186             :         {
    7187           0 :                 return weightSpectrumCubeFlat_p;
    7188             :         }
    7189           0 :         else if (weightSpectrumCubeFlat_p.shape().isEqual(vb->getShape()))
    7190             :         {
    7191           0 :                 weightSpectrumFlatFilled_p = true;
    7192           0 :                 return weightSpectrumCubeFlat_p;
    7193             :         }
    7194             :         else
    7195             :         {
    7196           0 :                 weightSpectrumCubeFlat_p.resize(vb->getShape(),false);
    7197           0 :                 weightSpectrumCubeFlat_p = 1.0f;
    7198           0 :                 weightSpectrumFlatFilled_p = true;
    7199           0 :                 return weightSpectrumCubeFlat_p;
    7200             :         }
    7201             : }
    7202             : 
    7203             : // -----------------------------------------------------------------------
    7204             : // Generic method to write a Matrix from a VisBuffer into a ArrayColumn
    7205             : // -----------------------------------------------------------------------
    7206        5313 : template <class T> void MSTransformManager::writeMatrix(  const Matrix<T> &inputMatrix,
    7207             :                                                                                                                                 ArrayColumn<T> &outputCol,
    7208             :                                                                                                                                 RefRows &rowRef,
    7209             :                                                                                                                                 uInt nBlocks)
    7210             : {
    7211        5313 :         if (nBlocks == 1)
    7212             :         {
    7213        5313 :                  outputCol.putColumnCells(rowRef, inputMatrix);
    7214             :         }
    7215             :         else
    7216             :         {
    7217             :                 // jagonzal (CAS-8492): Huge bug, each input row must
    7218             :                 // be copied n times not the whole matrix n times
    7219           0 :                 uInt outRowIdx = 0;
    7220           0 :                 size_t nInputRows = inputMatrix.shape()(1);
    7221           0 :                 Matrix<T> outputMatrix(IPosition(2,3,nInputRows*nBlocks));
    7222           0 :                 for (size_t inputRowIdx = 0; inputRowIdx<nInputRows; inputRowIdx++)
    7223             :                 {
    7224           0 :                         for (uInt blockIdx = 0; blockIdx<nBlocks; blockIdx++)
    7225             :                         {
    7226           0 :                                 outputMatrix.column(outRowIdx) = inputMatrix.column(inputRowIdx);
    7227           0 :                                 outRowIdx += 1;
    7228             :                         }
    7229             :                 }
    7230             : 
    7231           0 :                 RefRows outRowRef(rowRef.firstRow(),rowRef.firstRow()+nInputRows*nBlocks-1);
    7232           0 :                 outputCol.putColumnCells(outRowRef, outputMatrix);
    7233             : 
    7234             :                 /*
    7235             :                 uInt offset = 0;
    7236             :                 for (uInt block_i=0;block_i<nBlocks;block_i++)
    7237             :                 {
    7238             :                         uInt startRow_i = rowRef.firstRow()+offset;
    7239             :                         RefRows rowRef_i(startRow_i, startRow_i+inputMatrix.shape()(1)-1);
    7240             :                     outputCol.putColumnCells(rowRef_i, inputMatrix);
    7241             :                     offset += inputMatrix.shape()(1);
    7242             :                 }
    7243             :                 */
    7244           0 :         }
    7245        5313 :         return;
    7246             : }
    7247             : 
    7248             : // -----------------------------------------------------------------------
    7249             : // Generic method to write a Cube from a VisBuffer into a ArrayColumn
    7250             : // -----------------------------------------------------------------------
    7251        2512 : template <class T> void MSTransformManager::writeCube(    const Cube<T> &inputCube,
    7252             :                                                                                                                         ArrayColumn<T> &outputCol,
    7253             :                                                                                                                         RefRows &rowRef)
    7254             : {
    7255        2512 :         IPosition shape = inputCube.shape();
    7256        2512 :         shape(2) = rowRef.nrows();
    7257             :         bool deleteIt;
    7258        2512 :     Array<T> outputArray(shape,const_cast<T*>(inputCube.getStorage(deleteIt)),SHARE);
    7259        2512 :     outputCol.putColumnCells(rowRef, outputArray);
    7260             : 
    7261        5024 :         return;
    7262        2512 : }
    7263             : 
    7264             : // explicit instatiation for the use from SDMSManager
    7265             : template void MSTransformManager::writeCube<bool>(const Cube<bool> &, ArrayColumn<bool> &, RefRows &);
    7266             : 
    7267             : // -----------------------------------------------------------------------
    7268             : //
    7269             : // -----------------------------------------------------------------------
    7270        2989 : void MSTransformManager::transformCubeOfData(   vi::VisBuffer2 *vb,
    7271             :                                                                                                         RefRows &rowRef,
    7272             :                                                                                                         const Cube<Complex> &inputDataCube,
    7273             :                                                                                                         ArrayColumn<Complex> &outputDataCol,
    7274             :                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7275             :                                                                                                         const Cube<Float> &inputWeightCube)
    7276             : {
    7277        2989 :         (*this.*transformCubeOfDataComplex_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
    7278        2989 :         return;
    7279             : }
    7280             : 
    7281             : // -----------------------------------------------------------------------
    7282             : //
    7283             : // -----------------------------------------------------------------------
    7284        1130 : void MSTransformManager::transformCubeOfData(   vi::VisBuffer2 *vb,
    7285             :                                                                                                         RefRows &rowRef,
    7286             :                                                                                                         const Cube<Float> &inputDataCube,
    7287             :                                                                                                         ArrayColumn<Float> &outputDataCol,
    7288             :                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7289             :                                                                                                         const Cube<Float> &inputWeightCube)
    7290             : {
    7291        1130 :         (*this.*transformCubeOfDataFloat_p)(vb,rowRef,inputDataCube,outputDataCol,outputFlagCol,inputWeightCube);
    7292        1130 :         return;
    7293             : }
    7294             : 
    7295             : // -----------------------------------------------------------------------
    7296             : //
    7297             : // -----------------------------------------------------------------------
    7298        1330 : template <class T> void MSTransformManager::copyCubeOfData(       vi::VisBuffer2 *vb,
    7299             :                                                                                                                                 RefRows &rowRef,
    7300             :                                                                                                                                 const Cube<T> &inputDataCube,
    7301             :                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7302             :                                                                                                                                 ArrayColumn<bool> *outputFlagCol,
    7303             :                                                                                                                                 const Cube<Float> & /* inputWeightCube */)
    7304             : {
    7305        1330 :         writeCube(inputDataCube,outputDataCol,rowRef);
    7306        1330 :         if (outputFlagCol != NULL)
    7307             :         {
    7308        1182 :                 writeCube(vb->flagCube(),*outputFlagCol,rowRef);
    7309             :         }
    7310             : 
    7311        1330 :         return;
    7312             : }
    7313             : 
    7314             : // -----------------------------------------------------------------------
    7315             : // combine - for combinespws=True
    7316             : // -----------------------------------------------------------------------
    7317           0 : template <class T> void MSTransformManager::combineCubeOfData(    vi::VisBuffer2 *vb,
    7318             :                                                                                                                                         RefRows &rowRef,
    7319             :                                                                                                                                         const Cube<T> &inputDataCube,
    7320             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7321             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7322             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7323             : {
    7324             :         // Write flag column too?
    7325           0 :         if (outputFlagCol != NULL)
    7326             :         {
    7327           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7328           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7329           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7330             :         }
    7331             :         else
    7332             :         {
    7333           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7334           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7335           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7336             :         }
    7337             : 
    7338             :         // Get input flag cube
    7339           0 :         const Cube<bool> inputFlagCube = vb->flagCube();
    7340             : 
    7341             :         // Get input SPWs and exposures
    7342           0 :         Vector<Int> spws = vb->spectralWindows();
    7343           0 :         Vector<Double> exposures = vb->exposure();
    7344             : 
    7345             :         // Get input cube shape
    7346           0 :         IPosition inputCubeShape = inputDataCube.shape();
    7347           0 :         uInt nInputCorrelations = inputCubeShape(0);
    7348             : 
    7349             :         // Initialize input planes
    7350           0 :         IPosition inputPlaneShape(2,nInputCorrelations, numOfCombInputChanMap_p[0]);
    7351           0 :         Matrix<Double> normalizingFactorPlane(inputPlaneShape);
    7352           0 :         Matrix<T> inputPlaneData(inputPlaneShape);
    7353           0 :         Matrix<bool> inputPlaneFlags(inputPlaneShape,false);
    7354           0 :         Matrix<Float> inputPlaneWeights(inputPlaneShape);
    7355             : 
    7356             :         // Initialize output planes
    7357           0 :         IPosition outputPlaneShape(2,nInputCorrelations, inputOutputSpwMap_p[0].second.NUM_CHAN);
    7358           0 :         Matrix<T> outputPlaneData(outputPlaneShape);
    7359           0 :         Matrix<bool> outputPlaneFlags(outputPlaneShape);
    7360             : 
    7361           0 :         Int spw = 0;
    7362             :         Double weight;
    7363             :         uInt inputChannel;
    7364             :         bool inputChanelFlag;
    7365             :         Double normalizingFactor;
    7366           0 :         uInt row = 0, baseline_index = 0;
    7367           0 :         vector<uInt> baselineRows;
    7368           0 :         map<Int, uInt> spwRowMap;
    7369           0 :         map<Int, uInt>::iterator spwRowMapIter;
    7370           0 :         map<Int, uInt> spwFractionCountsMap;
    7371           0 :         bool unityContributors = false;
    7372           0 :         vector< channelContribution > contributions;
    7373           0 :         vector< channelContribution >::iterator contributionsIter;
    7374           0 :         map < Int , map < uInt, bool > > removeContributionsMap;
    7375             : 
    7376           0 :         bool combinationOfSPWsWithDifferentExposure = false;
    7377           0 :         Double exposure = 0;
    7378             : 
    7379           0 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7380           0 :         for (baselineMap::iterator iter = baselineMap_p.begin(); iter != baselineMap_p.end(); iter++)
    7381             :         {
    7382             :                 // Initialize input plane
    7383           0 :                 inputPlaneData = 0.0;
    7384             : 
    7385             :                 // Initialize weights plane
    7386           0 :                 inputPlaneWeights = 0.0;
    7387             : 
    7388             :                 // Initialize normalizing factor plane
    7389           0 :                 normalizingFactorPlane = 0.0;
    7390             : 
    7391             :                 // Fill input plane to benefit from contiguous access to the input cube
    7392           0 :                 baselineRows = iter->second;
    7393             : 
    7394             :                 // Create spw-row map for this baseline and initialize detection of SPWs with different exposure
    7395           0 :                 spwRowMap.clear();
    7396           0 :                 if (combinationOfSPWsWithDifferentExposure_p and (inputWeightCube.shape().isEqual(inputCubeShape)))
    7397             :                 {
    7398           0 :                         combinationOfSPWsWithDifferentExposure = true;
    7399           0 :                         addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
    7400           0 :                         for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    7401             :                         {
    7402           0 :                                 row = *iter_row;
    7403           0 :                                 spw = spws(row);
    7404           0 :                                 spwRowMap[spw]=row;
    7405             :                         }
    7406             :                 }
    7407             :                 else
    7408             :                 {
    7409           0 :                         exposure = exposures(*baselineRows.begin());
    7410           0 :                         combinationOfSPWsWithDifferentExposure = false;
    7411           0 :                         for (vector<uInt>::iterator iter_row = baselineRows.begin();iter_row != baselineRows.end(); iter_row++)
    7412             :                         {
    7413           0 :                                 row = *iter_row;
    7414           0 :                                 spw = spws(row);
    7415           0 :                                 spwRowMap[spw]=row;
    7416             : 
    7417             :                                 // In the case of *_SPECTRUM inputWeightCube is dummy
    7418           0 :                                 if ((abs(exposure - exposures(row)) > FLT_EPSILON) and (inputWeightCube.shape().isEqual(inputCubeShape)))
    7419             :                                 {
    7420           0 :                                         combinationOfSPWsWithDifferentExposure = true;
    7421             :                                 }
    7422             :                         }
    7423             : 
    7424           0 :                         if (combinationOfSPWsWithDifferentExposure)
    7425             :                         {
    7426           0 :                                 combinationOfSPWsWithDifferentExposure_p = true;
    7427           0 :                                 addWeightSpectrumContribution_p = &MSTransformManager::addWeightSpectrumContribution;
    7428           0 :                                 if (inputWeightSpectrumAvailable_p)
    7429             :                                 {
    7430           0 :                                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    7431             :                                                                 << "Detected combination of SPWs with different EXPOSURE "<< endl
    7432             :                                                                 << "Will use WEIGHT_SPECTRUM to combine them "<< endl
    7433           0 :                                                                 << LogIO::POST;
    7434             :                                 }
    7435             :                                 else
    7436             :                                 {
    7437           0 :                                         logger_p        << LogIO::WARN << LogOrigin("MSTransformManager", __FUNCTION__)
    7438             :                                                                 << "Detected combination of SPWs with different EXPOSURE "<< endl
    7439             :                                                                 << "Will use WEIGHT to combine them (WEIGHT_SPECTRUM not available)"<< endl
    7440           0 :                                                                 << LogIO::POST;
    7441             :                                 }
    7442             :                         }
    7443             :                         else
    7444             :                         {
    7445           0 :                                 addWeightSpectrumContribution_p = &MSTransformManager::dontAddWeightSpectrumContribution;
    7446             :                         }
    7447             :                 }
    7448             : 
    7449             : 
    7450           0 :                 for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
    7451             :                 {
    7452           0 :                         contributions = inputOutputChanFactorMap_p[outputChannel];
    7453             : 
    7454           0 :                         for (uInt pol = 0; pol < inputDataCube.shape()(0); pol++)
    7455             :                         {
    7456           0 :                                 spwFractionCountsMap.clear();
    7457           0 :                                 unityContributors = false;
    7458             : 
    7459             :                                 // Go through list of contributors for this output channel and polarization and gather flags info
    7460           0 :                                 for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
    7461             :                                 {
    7462           0 :                                         inputChannel = contributionsIter->inpChannel;
    7463           0 :                                         weight = contributionsIter->weight;
    7464             : 
    7465             :                                         // Add WEIGHT_SPECTRUM to the contribution
    7466           0 :                                         (*this.*addWeightSpectrumContribution_p)(weight,pol,inputChannel,row,inputWeightCube);
    7467             : 
    7468             :                                         // Find row for this input channel
    7469           0 :                                         spw = contributionsIter->inpSpw;
    7470           0 :                                         spwRowMapIter = spwRowMap.find(spw);
    7471           0 :                                         if (spwRowMapIter != spwRowMap.end())
    7472             :                                         {
    7473           0 :                                                 row = spwRowMap[spw];
    7474             : 
    7475             :                                                 // Fill flags info
    7476           0 :                                                 inputChanelFlag = inputFlagCube(pol,inputChannel,row);
    7477           0 :                                                 contributionsIter->flag = inputChanelFlag;
    7478             : 
    7479             :                                                 // Count input channel if it is not flagged and has non-unity overlapping fraction
    7480           0 :                                                 if (weight<1.0)
    7481             :                                                 {
    7482           0 :                                                         if (!inputChanelFlag) spwFractionCountsMap[spw] += 1;
    7483             :                                                 }
    7484             :                                                 // Count if we have valid unity contributors, otherwise we don't discard non-unity contributors
    7485             :                                                 else
    7486             :                                                 {
    7487           0 :                                                         unityContributors = true;
    7488             :                                                 }
    7489             :                                         }
    7490             :                                         else
    7491             :                                         {
    7492             :                                                 // Fill flags info
    7493           0 :                                                 contributionsIter->flag = true;
    7494             :                                         }
    7495             :                                 }
    7496             : 
    7497             :                                 // Remove contributions from SPWs with odd numbers of contributors with non-unity
    7498             :                                 // overlap fraction which could influence the averaging asymmetrically
    7499           0 :                                 for (contributionsIter = contributions.begin(); contributionsIter != contributions.end(); contributionsIter++)
    7500             :                                 {
    7501           0 :                                         inputChannel = contributionsIter->inpChannel;
    7502           0 :                                         weight = contributionsIter->weight;
    7503           0 :                                         spw = contributionsIter->inpSpw;
    7504             : 
    7505             :                                         // Find row for this input channel
    7506           0 :                                         if (!contributionsIter->flag)
    7507             :                                         {
    7508             :                                                 // jagonzal: Caution, accessing the map populates it!!!
    7509           0 :                                                 row = spwRowMap[spw];
    7510             : 
    7511           0 :                                                 if ((spwFractionCountsMap[spw] % 2 == 0) or (weight >= 1.0) or (!unityContributors))
    7512             :                                                 {
    7513           0 :                                                         inputPlaneData(pol,outputChannel) += weight*inputDataCube(pol,inputChannel,row);
    7514           0 :                                                         normalizingFactorPlane(pol,outputChannel) += weight;
    7515           0 :                                                         (*this.*fillWeightsPlane_p)(pol,inputChannel,outputChannel,row,inputWeightCube,inputPlaneWeights,weight);
    7516             :                                                 }
    7517             :                                         }
    7518             :                                 }
    7519             :                         }
    7520             :                 }
    7521             : 
    7522             :                 // Normalize combined data and determine input plane flags
    7523           0 :                 inputPlaneFlags = false;
    7524           0 :                 for (uInt outputChannel = 0; outputChannel < numOfCombInputChanMap_p[0]; outputChannel++)
    7525             :                 {
    7526           0 :                         for (uInt pol = 0; pol < nInputCorrelations; pol++)
    7527             :                         {
    7528           0 :                                 normalizingFactor = normalizingFactorPlane(pol,outputChannel);
    7529           0 :                                 if (normalizingFactor >= 0.999999) // we lose a couple significant digits in the subtractions
    7530             :                                 {
    7531           0 :                                         inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7532             : 
    7533             :                                         // Normalize weights plane
    7534           0 :                                         (*this.*normalizeWeightsPlane_p)(pol,outputChannel,inputPlaneWeights,normalizingFactorPlane);
    7535             :                                 }
    7536           0 :                                 else if (normalizingFactor > 0)
    7537             :                                 {
    7538           0 :                                         inputPlaneData(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7539           0 :                                         inputPlaneFlags(pol,outputChannel) = true;
    7540             :                                 }
    7541             :                                 else
    7542             :                                 {
    7543           0 :                                         inputPlaneFlags(pol,outputChannel) = true;
    7544             :                                 }
    7545             :                         }
    7546             :                 }
    7547             : 
    7548             :                 // Initialize output flags plane
    7549           0 :                 outputPlaneFlags = false;
    7550             : 
    7551             :                 // Transform input planes and write them
    7552           0 :                 transformAndWritePlaneOfData(   0,rowRef.firstRow()+baseline_index*nspws_p,
    7553             :                                                                                 inputPlaneData,inputPlaneFlags,inputPlaneWeights,
    7554             :                                                                                 outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
    7555             : 
    7556             : 
    7557           0 :                 relativeRow_p += nspws_p;
    7558           0 :                 baseline_index += 1;
    7559             :         }
    7560             : 
    7561           0 :         return;
    7562           0 : }
    7563             : 
    7564             : // -----------------------------------------------------------------------
    7565             : //
    7566             : // -----------------------------------------------------------------------
    7567           0 : void MSTransformManager::addWeightSpectrumContribution( Double &weight,
    7568             :                                                                                                                         uInt &pol,
    7569             :                                                                                                                         uInt &inputChannel,
    7570             :                                                                                                                         uInt &row,
    7571             :                                                                                                                         const Cube<Float> &inputWeightsCube)
    7572             : {
    7573           0 :         weight *= inputWeightsCube(pol,inputChannel,row);
    7574             : 
    7575           0 :         return;
    7576             : }
    7577             : 
    7578             : // -----------------------------------------------------------------------
    7579             : //
    7580             : // -----------------------------------------------------------------------
    7581           0 : void MSTransformManager::dontAddWeightSpectrumContribution(     Double &,
    7582             :                                                                                                                                 uInt &,
    7583             :                                                                                                                                 uInt &,
    7584             :                                                                                                                                 uInt &,
    7585             :                                                                                                                                 const Cube<Float> &)
    7586             : {
    7587           0 :         return;
    7588             : }
    7589             : 
    7590             : // -----------------------------------------------------------------------
    7591             : //
    7592             : // -----------------------------------------------------------------------
    7593           0 : void MSTransformManager::fillWeightsPlane(      uInt pol,
    7594             :                                                                                                 uInt inputChannel,
    7595             :                                                                                                 uInt outputChannel,
    7596             :                                                                                                 uInt inputRow,
    7597             :                                                                                                 const Cube<Float> &inputWeightsCube,
    7598             :                                                                                                 Matrix<Float> &inputWeightsPlane,
    7599             :                                                                                                 Double factor)
    7600             : {
    7601           0 :         inputWeightsPlane(pol,outputChannel) += factor*inputWeightsCube(pol,inputChannel,inputRow);
    7602             : 
    7603           0 :         return;
    7604             : }
    7605             : 
    7606             : // -----------------------------------------------------------------------
    7607             : //
    7608             : // -----------------------------------------------------------------------
    7609           0 : void MSTransformManager::normalizeWeightsPlane( uInt pol,
    7610             :                                                                                                         uInt outputChannel,
    7611             :                                                                                                         Matrix<Float> &inputPlaneWeights,
    7612             :                                                                                                         Matrix<Double> &normalizingFactorPlane)
    7613             : {
    7614           0 :         inputPlaneWeights(pol,outputChannel) /= normalizingFactorPlane(pol,outputChannel);
    7615             : 
    7616           0 :         return;
    7617             : }
    7618             : 
    7619             : // -----------------------------------------------------------------------
    7620             : //
    7621             : // -----------------------------------------------------------------------
    7622        2789 : template <class T> void MSTransformManager::averageCubeOfData(    vi::VisBuffer2 *vb,
    7623             :                                                                                                                                         RefRows &rowRef,
    7624             :                                                                                                                                         const Cube<T> &inputDataCube,
    7625             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7626             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7627             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7628             : {
    7629             :         // Get input spw and flag and weight cubes
    7630        2789 :         Int inputSpw = vb->spectralWindows()(0);
    7631        2789 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7632             : 
    7633             :         // Define output plane shape
    7634        2789 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), numOfOutChanMap_p[inputSpw]);
    7635             : 
    7636        2789 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7637             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7638             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7639             : 
    7640        5578 :         return;
    7641        2789 : }
    7642             : 
    7643             : // -----------------------------------------------------------------------
    7644             : //
    7645             : // -----------------------------------------------------------------------
    7646           0 : template <class T> void MSTransformManager::smoothCubeOfData(     vi::VisBuffer2 *vb,
    7647             :                                                                                                                                         RefRows &rowRef,
    7648             :                                                                                                                                         const Cube<T> &inputDataCube,
    7649             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7650             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7651             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7652             : {
    7653             :         // Get input spw and flag cube
    7654           0 :         Int inputSpw = vb->spectralWindows()(0);
    7655           0 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7656             : 
    7657             :         // Define output plane shape
    7658           0 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputDataCube.shape()(1));
    7659             : 
    7660             :         // Transform cube
    7661           0 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7662             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7663             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7664             : 
    7665           0 :         return;
    7666           0 : }
    7667             : 
    7668             : // -----------------------------------------------------------------------
    7669             : //
    7670             : // -----------------------------------------------------------------------
    7671           0 : template <class T> void MSTransformManager::regridCubeOfData(     vi::VisBuffer2 *vb,
    7672             :                                                                                                                                         RefRows &rowRef,
    7673             :                                                                                                                                         const Cube<T> &inputDataCube,
    7674             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7675             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7676             :                                                                                                                                         const Cube<Float> &inputWeightCube)
    7677             : {
    7678             :         // Get input spw and flag cube
    7679           0 :         Int inputSpw = vb->spectralWindows()(0);
    7680           0 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7681             : 
    7682             :         // Define output plane shape
    7683           0 :         IPosition outputPlaneShape = IPosition(2,inputDataCube.shape()(0), inputOutputSpwMap_p[inputSpw].second.NUM_CHAN);
    7684             : 
    7685             :         // Transform cube
    7686           0 :         transformAndWriteCubeOfData(    inputSpw, rowRef,
    7687             :                                                                         inputDataCube, inputFlagsCube, inputWeightCube,
    7688             :                                                                         outputPlaneShape, outputDataCol, outputFlagCol);
    7689             : 
    7690           0 :         return;
    7691           0 : }
    7692             : 
    7693             : // -----------------------------------------------------------------------
    7694             : //
    7695             : // -----------------------------------------------------------------------
    7696        2789 : template <class T> void MSTransformManager::transformAndWriteCubeOfData(  Int inputSpw,
    7697             :                                                                                                                                                                 RefRows &rowRef,
    7698             :                                                                                                                                                                 const Cube<T> &inputDataCube,
    7699             :                                                                                                                                                                 const Cube<bool> &inputFlagsCube,
    7700             :                                                                                                                                                                 const Cube<Float> &inputWeightsCube,
    7701             :                                                                                                                                                                 IPosition &outputPlaneShape,
    7702             :                                                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7703             :                                                                                                                                                                 ArrayColumn<bool> *outputFlagCol)
    7704             : {
    7705        5578 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    7706             :                  << "Shape of input data cube: " << inputDataCube.shape()
    7707             :                  << ", output plane shape: " << outputPlaneShape
    7708        5578 :                  << LogIO::POST;
    7709             : 
    7710             :         // Write flag column too?
    7711        2789 :         if (outputFlagCol != NULL)
    7712             :         {
    7713         589 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7714         589 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7715         589 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7716             :         }
    7717             :         else
    7718             :         {
    7719        2200 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7720        2200 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7721        2200 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7722             :         }
    7723             : 
    7724             :         // Get input number of rows
    7725        2789 :         uInt nInputRows = inputDataCube.shape()(2);
    7726             : 
    7727             :         // Initialize input planes
    7728        2789 :         Matrix<T> inputPlaneData;
    7729        2789 :         Matrix<bool> inputPlaneFlags;
    7730        2789 :         Matrix<Float> inputPlaneWeights;
    7731             : 
    7732             :         // Initialize output planes
    7733        2789 :         Matrix<T> outputPlaneData(outputPlaneShape);
    7734        2789 :         Matrix<bool> outputPlaneFlags(outputPlaneShape);
    7735             : 
    7736             :         // Iterate row by row in order to extract a plane
    7737        2789 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7738       19003 :         for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
    7739             :         {
    7740             :                 // Initialize output flags plane
    7741       16214 :                 outputPlaneFlags = false;
    7742             : 
    7743             :                 // Fill input planes by reference
    7744       16214 :                 inputPlaneData = inputDataCube.xyPlane(rowIndex);
    7745       16214 :                 inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
    7746       16214 :                 (*this.*setWeightsPlaneByReference_p)(rowIndex,inputWeightsCube,inputPlaneWeights);
    7747             : 
    7748             :                 // Transform input planes and write them
    7749       16214 :                 transformAndWritePlaneOfData(   inputSpw,rowRef.firstRow()+rowIndex*nspws_p,
    7750             :                                                                                 inputPlaneData,inputPlaneFlags,inputPlaneWeights,
    7751             :                                                                                 outputPlaneData,outputPlaneFlags,outputDataCol,outputFlagCol);
    7752             : 
    7753       16214 :                 relativeRow_p += nspws_p;
    7754             :         }
    7755             : 
    7756        5578 :         return;
    7757        2789 : }
    7758             : 
    7759             : // -----------------------------------------------------------------------
    7760             : //
    7761             : // -----------------------------------------------------------------------
    7762           0 : template <class T> void MSTransformManager::separateCubeOfData(   vi::VisBuffer2 *vb,
    7763             :                                                                                                                                         RefRows &rowRef,
    7764             :                                                                                                                                         const Cube<T> &inputDataCube,
    7765             :                                                                                                                                         ArrayColumn<T> &outputDataCol,
    7766             :                                                                                                                                         ArrayColumn<bool> *outputFlagCol,
    7767             :                                                                                                                                         const Cube<Float> & /* inputWeightCube */)
    7768             : {
    7769             :         // Write flag column too?
    7770           0 :         if (outputFlagCol != NULL)
    7771             :         {
    7772           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::writeOutputFlagsPlaneSlices;
    7773           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::writeOutputFlagsPlaneReshapedSlices;
    7774           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::writeOutputFlagsPlane;
    7775             :         }
    7776             :         else
    7777             :         {
    7778           0 :                 writeOutputFlagsPlaneSlices_p = &MSTransformManager::dontWriteOutputFlagsPlaneSlices;
    7779           0 :                 writeOutputFlagsPlaneReshapedSlices_p = &MSTransformManager::dontWriteOutputPlaneReshapedSlices;
    7780           0 :                 writeOutputFlagsPlane_p = &MSTransformManager::dontWriteOutputFlagsPlane;
    7781             :         }
    7782             : 
    7783             :         // Get input flags, spw and number of rows
    7784           0 :         uInt nInputRows = inputDataCube.shape()(2);
    7785           0 :         const Cube<bool> inputFlagsCube = vb->flagCube();
    7786             : 
    7787             :         // Initialize input planes
    7788           0 :         Matrix<T> inputPlaneData;
    7789           0 :         Matrix<bool> inputPlaneFlags;
    7790             : 
    7791             :         // Iterate row by row in order to extract a plane
    7792           0 :         relativeRow_p = 0; // Initialize relative row for buffer mode
    7793           0 :         for (uInt rowIndex=0; rowIndex < nInputRows; rowIndex++)
    7794             :         {
    7795             :                 // Fill input planes by reference
    7796           0 :                 inputPlaneData = inputDataCube.xyPlane(rowIndex);
    7797           0 :                 inputPlaneFlags = inputFlagsCube.xyPlane(rowIndex);
    7798             : 
    7799             :                 // Directly write output plane
    7800           0 :                 writeOutputPlanes(      rowRef.firstRow()+rowIndex*nspws_p,
    7801             :                                                         inputPlaneData,inputPlaneFlags,
    7802             :                                                         outputDataCol,*outputFlagCol);
    7803             : 
    7804           0 :                 relativeRow_p += nspws_p;
    7805             :         }
    7806             : 
    7807           0 :         return;
    7808           0 : }
    7809             : 
    7810             : // -----------------------------------------------------------------------
    7811             : //
    7812             : // -----------------------------------------------------------------------
    7813          12 : void MSTransformManager::setWeightsPlaneByReference(    uInt inputRow,
    7814             :                                                                                                                         const Cube<Float> &inputWeightsCube,
    7815             :                                                                                                                         Matrix<Float> &inputWeightsPlane)
    7816             : {
    7817          12 :         inputWeightsPlane = inputWeightsCube.xyPlane(inputRow);
    7818          12 : }
    7819             : 
    7820             : // -----------------------------------------------------------------------
    7821             : //
    7822             : // -----------------------------------------------------------------------
    7823       16214 : template <class T> void MSTransformManager::transformAndWritePlaneOfData( Int inputSpw,
    7824             :                                                                                                                                                                 uInt row,
    7825             :                                                                                                                                                                 Matrix<T> &inputDataPlane,
    7826             :                                                                                                                                                                 Matrix<bool> &inputFlagsPlane,
    7827             :                                                                                                                                                                 Matrix<Float> &inputWeightsPlane,
    7828             :                                                                                                                                                                 Matrix<T> &outputDataPlane,
    7829             :                                                                                                                                                                 Matrix<bool> &outputFlagsPlane,
    7830             :                                                                                                                                                                 ArrayColumn<T> &outputDataCol,
    7831             :                                                                                                                                                                 ArrayColumn<bool> *outputFlagCol)
    7832             : {
    7833             :         // Get input number of correlations
    7834       16214 :         uInt nCorrs = inputDataPlane.shape()(0);
    7835             : 
    7836             :         // Get output plane shape
    7837       16214 :         IPosition outputPlaneShape = outputDataPlane.shape();
    7838             : 
    7839             :         // Initialize vectors
    7840       16214 :         Vector<T> inputDataStripe;
    7841       16214 :         Vector<bool> inputFlagsStripe;
    7842       16214 :         Vector<Float> inputWeightsStripe;
    7843       16214 :         Vector<T> outputDataStripe;
    7844       16214 :         Vector<bool> outputFlagsStripe;
    7845             : 
    7846             :         // Iterate correlation by correlation in order to extract a vector
    7847       81070 :         for (uInt corrIndex=0; corrIndex < nCorrs; corrIndex++)
    7848             :         {
    7849             :                 // Fill input stripes by reference
    7850       64856 :                 inputDataStripe.reference(inputDataPlane.row(corrIndex));
    7851       64856 :                 inputFlagsStripe.reference(inputFlagsPlane.row(corrIndex));
    7852       64856 :                 (*this.*setWeightStripeByReference_p)(corrIndex,inputWeightsPlane,inputWeightsStripe);
    7853             : 
    7854             :                 // Fill output stripes by reference
    7855       64856 :                 outputDataStripe.reference(outputDataPlane.row(corrIndex));
    7856       64856 :                 outputFlagsStripe.reference(outputFlagsPlane.row(corrIndex));
    7857             : 
    7858       64856 :                 transformStripeOfData(inputSpw,inputDataStripe,inputFlagsStripe,
    7859             :                                 inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    7860             :         }
    7861             : 
    7862             :         // Write output planes
    7863       16214 :         writeOutputPlanes(row,outputDataPlane,outputFlagsPlane,outputDataCol,*outputFlagCol);
    7864       16214 : }
    7865             : 
    7866             : // -----------------------------------------------------------------------
    7867             : //
    7868             : // -----------------------------------------------------------------------
    7869        9718 : void MSTransformManager::writeOutputPlanes(     uInt row,
    7870             :                                                                                         Matrix<Complex> &outputDataPlane,
    7871             :                                                                                         Matrix<bool> &outputFlagsPlane,
    7872             :                                                                                         ArrayColumn<Complex> &outputDataCol,
    7873             :                                                                                         ArrayColumn<bool> &outputFlagCol)
    7874             : {
    7875        9718 :         (*this.*writeOutputPlanesComplex_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
    7876        9718 : }
    7877             : 
    7878             : // -----------------------------------------------------------------------
    7879             : //
    7880             : // -----------------------------------------------------------------------
    7881        6496 : void MSTransformManager::writeOutputPlanes(     uInt row,
    7882             :                                                                                         Matrix<Float> &outputDataPlane,
    7883             :                                                                                         Matrix<bool> &outputFlagsPlane,
    7884             :                                                                                         ArrayColumn<Float> &outputDataCol,
    7885             :                                                                                         ArrayColumn<bool> &outputFlagCol)
    7886             : {
    7887        6496 :         (*this.*writeOutputPlanesFloat_p)(row,outputDataPlane,outputFlagsPlane,outputDataCol,outputFlagCol);
    7888        6496 : }
    7889             : 
    7890             : // -----------------------------------------------------------------------
    7891             : //
    7892             : // -----------------------------------------------------------------------
    7893           0 : void MSTransformManager::setOutputbuffer(Cube<Complex> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
    7894             : {
    7895           0 :         switch (dataBuffer_p)
    7896             :         {
    7897           0 :                 case MSTransformations::visCube:
    7898             :                 {
    7899           0 :                         dataBufferPointer=visCube_p;
    7900           0 :                         if (userBufferMode_p)
    7901             :                         {
    7902           0 :                                 flagBufferPointer = flagCube_p;
    7903             :                         }
    7904             :                         else
    7905             :                         {
    7906           0 :                                 flagBufferPointer = NULL;
    7907             :                         }
    7908           0 :                         break;
    7909             :                 }
    7910           0 :                 case MSTransformations::visCubeCorrected:
    7911             :                 {
    7912           0 :                         dataBufferPointer=visCubeCorrected_p;
    7913           0 :                         if (userBufferMode_p)
    7914             :                         {
    7915           0 :                                 flagBufferPointer = flagCube_p;
    7916             :                         }
    7917             :                         else
    7918             :                         {
    7919           0 :                                 flagBufferPointer = NULL;
    7920             :                         }
    7921           0 :                         break;
    7922             :                 }
    7923           0 :                 case MSTransformations::visCubeModel:
    7924             :                 {
    7925           0 :                         dataBufferPointer=visCubeModel_p;
    7926           0 :                         if (userBufferMode_p)
    7927             :                         {
    7928           0 :                                 flagBufferPointer = flagCube_p;
    7929             :                         }
    7930             :                         else
    7931             :                         {
    7932           0 :                                 flagBufferPointer = NULL;
    7933             :                         };
    7934           0 :                         break;
    7935             :                 }
    7936           0 :                 default:
    7937             :                 {
    7938           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    7939             :                                         << " Data buffer not specified"
    7940           0 :                                         << LogIO::POST;
    7941           0 :                         dataBufferPointer=NULL;
    7942           0 :                         flagBufferPointer=NULL;
    7943           0 :                         break;
    7944             :                 }
    7945             :         }
    7946             : 
    7947           0 :         return;
    7948             : }
    7949             : 
    7950             : // -----------------------------------------------------------------------
    7951             : //
    7952             : // -----------------------------------------------------------------------
    7953        6496 : void MSTransformManager::setOutputbuffer(Cube<Float> *& dataBufferPointer,Cube<bool> *& flagBufferPointer)
    7954             : {
    7955        6496 :         switch (dataBuffer_p)
    7956             :         {
    7957           0 :                 case MSTransformations::visCubeFloat:
    7958             :                 {
    7959           0 :                         dataBufferPointer=visCubeFloat_p;
    7960           0 :                         if (userBufferMode_p)
    7961             :                         {
    7962           0 :                                 flagBufferPointer = flagCube_p;
    7963             :                         }
    7964             :                         else
    7965             :                         {
    7966           0 :                                 flagBufferPointer = NULL;
    7967             :                         };
    7968           0 :                         break;
    7969             :                 }
    7970        6496 :                 case MSTransformations::weightSpectrum:
    7971             :                 {
    7972        6496 :                         dataBufferPointer=weightSpectrum_p;
    7973             :                         // In buffer mode we already have a memory resident flagCube
    7974             :                         // And the vector transformations use vectors from a dynamically initialize matrixes
    7975        6496 :                         if (userBufferMode_p)
    7976             :                         {
    7977           0 :                                 flagBufferPointer=NULL;
    7978             :                         }
    7979             :                         else
    7980             :                         {
    7981        6496 :                                 flagBufferPointer = flagCube_p;
    7982             :                         }
    7983        6496 :                         break;
    7984             :                 }
    7985           0 :                 case MSTransformations::sigmaSpectrum:
    7986             :                 {
    7987           0 :                         dataBufferPointer=sigmaSpectrum_p;
    7988             :                         // In buffer mode we already have a memory resident flagCube
    7989             :                         // And the vector transformations use vectors from a dynamically initialize matrixes
    7990           0 :                         if (userBufferMode_p)
    7991             :                         {
    7992           0 :                                 flagBufferPointer=NULL;
    7993             :                         }
    7994             :                         else
    7995             :                         {
    7996           0 :                                 flagBufferPointer = flagCube_p;
    7997             :                         }
    7998           0 :                         break;
    7999             :                 }
    8000           0 :                 default:
    8001             :                 {
    8002           0 :                         logger_p << LogIO::SEVERE << LogOrigin("MSTransformManager", __FUNCTION__)
    8003             :                                         << " Data buffer not specified"
    8004           0 :                                         << LogIO::POST;
    8005           0 :                         dataBufferPointer=NULL;
    8006           0 :                         flagBufferPointer = NULL;
    8007           0 :                         break;
    8008             :                 }
    8009             :         }
    8010             : 
    8011        6496 :         return;
    8012             : }
    8013             : 
    8014             : // -----------------------------------------------------------------------
    8015             : //
    8016             : // -----------------------------------------------------------------------
    8017        6496 : template <class T> void  MSTransformManager::bufferOutputPlanes(  uInt ,
    8018             :                                                                                                                                         Matrix<T> &outputDataPlane,
    8019             :                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8020             :                                                                                                                                         ArrayColumn<T> &,
    8021             :                                                                                                                                         ArrayColumn<bool> &)
    8022             : {
    8023             :         // Get buffer pointers
    8024             :         Cube<T> *dataBufferPointer;
    8025             :         Cube<bool> *flagBufferPointer;
    8026        6496 :         setOutputbuffer(dataBufferPointer,flagBufferPointer);
    8027             : 
    8028             :         // Copy data to buffer
    8029        6496 :         dataBufferPointer->xyPlane(relativeRow_p) = outputDataPlane;
    8030             : 
    8031             :         // Copy flags to buffer
    8032        6496 :         if (flagBufferPointer != NULL)
    8033             :         {
    8034        6496 :                 flagBufferPointer->xyPlane(relativeRow_p) = outputFlagsPlane;
    8035             :         }
    8036             : 
    8037       12992 :         return;
    8038             : }
    8039             : 
    8040             : // -----------------------------------------------------------------------
    8041             : //
    8042             : // -----------------------------------------------------------------------
    8043           0 : template <class T> void MSTransformManager::bufferOutputPlanesInSlices(   uInt,
    8044             :                                                                                                                                                 Matrix<T> &outputDataPlane,
    8045             :                                                                                                                                                 Matrix<bool> &outputFlagsPlane,
    8046             :                                                                                                                                                 ArrayColumn<T> & /* outputDataCol */,
    8047             :                                                                                                                                                 ArrayColumn<bool> & /* outputFlagCol */)
    8048             : {
    8049             :         // Get buffer pointers
    8050             :         Cube<T> *dataBufferPointer;
    8051             :         Cube<bool> *flagBufferPointer;
    8052           0 :         setOutputbuffer(dataBufferPointer,flagBufferPointer);
    8053             : 
    8054             :         // Copy data to buffer
    8055           0 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8056           0 :         uInt nCorrs = outputPlaneShape(0);
    8057           0 :         IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
    8058           0 :         Slice sliceX(0,nCorrs);
    8059             : 
    8060             :         uInt spw_i;
    8061           0 :         uInt nspws = nspws_p-1;
    8062           0 :         for (spw_i=0;spw_i<nspws;spw_i++)
    8063             :         {
    8064           0 :                 uInt outRow = relativeRow_p+spw_i;
    8065           0 :                 Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    8066           0 :                 Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
    8067           0 :                 dataBufferPointer->xyPlane(outRow) = outputPlane_i;
    8068             : 
    8069           0 :                 if (flagBufferPointer != NULL)
    8070             :                 {
    8071           0 :                         Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
    8072           0 :                         flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
    8073           0 :                 }
    8074             :         }
    8075             : 
    8076           0 :         uInt outRow = relativeRow_p+spw_i;
    8077           0 :         Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    8078           0 :         Matrix<T> outputPlane_i = outputDataPlane(sliceX,sliceY);
    8079           0 :         outputPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
    8080             :         // jagonzal (CAS-7435): We have to set the new values to 0
    8081           0 :         Slice sliceTail(tailOfChansforLastSpw_p,chansPerOutputSpw_p-tailOfChansforLastSpw_p);
    8082           0 :         outputPlane_i(sliceX,sliceTail) = 0; // Slices use reference semantics.
    8083           0 :         dataBufferPointer->xyPlane(outRow) = outputPlane_i;
    8084             : 
    8085           0 :         if (flagBufferPointer != NULL)
    8086             :         {
    8087           0 :                 Matrix<bool> outputFlagPlane_i = outputFlagsPlane(sliceX,sliceY);
    8088           0 :                 outputFlagPlane_i.resize(outputPlaneShape_i,true); // Resize uses a new storage and copies the old values to it
    8089             :                 // jagonzal (CAS-7435): We have to set the new values to 0
    8090           0 :                 outputFlagPlane_i(sliceX,sliceTail) = true; // Slices use reference semantics.
    8091           0 :                 flagBufferPointer->xyPlane(outRow) = outputFlagPlane_i;
    8092           0 :         }
    8093             : 
    8094           0 :         return;
    8095           0 : }
    8096             : 
    8097             : // -----------------------------------------------------------------------
    8098             : //
    8099             : // -----------------------------------------------------------------------
    8100        9718 : template <class T> void MSTransformManager::writeOutputPlanesInBlock(     uInt row,
    8101             :                                                                                                                                                         Matrix<T> &outputDataPlane,
    8102             :                                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8103             :                                                                                                                                                         ArrayColumn<T> &outputDataCol,
    8104             :                                                                                                                                                         ArrayColumn<bool> &outputFlagCol)
    8105             : {
    8106        9718 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8107        9718 :         outputDataCol.setShape(row,outputPlaneShape);
    8108        9718 :         outputDataCol.put(row, outputDataPlane);
    8109        9718 :         (*this.*writeOutputFlagsPlane_p)(outputFlagsPlane,outputFlagCol, outputPlaneShape, row);
    8110        9718 : }
    8111             : 
    8112             : 
    8113             : // -----------------------------------------------------------------------
    8114             : //
    8115             : // -----------------------------------------------------------------------
    8116        3274 : void MSTransformManager::writeOutputFlagsPlane( Matrix<bool> &outputPlane,
    8117             :                                                                                                         ArrayColumn<bool> &outputCol,
    8118             :                                                                                                         IPosition &outputPlaneShape,
    8119             :                                                                                                         uInt &outputRow)
    8120             : {
    8121        3274 :         outputCol.setShape(outputRow,outputPlaneShape);
    8122        3274 :         outputCol.put(outputRow, outputPlane);
    8123        3274 : }
    8124             : 
    8125             : // -----------------------------------------------------------------------
    8126             : //
    8127             : // -----------------------------------------------------------------------
    8128           0 : template <class T> void MSTransformManager::writeOutputPlanesInSlices(    uInt row,
    8129             :                                                                                                                                                         Matrix<T> &outputDataPlane,
    8130             :                                                                                                                                                         Matrix<bool> &outputFlagsPlane,
    8131             :                                                                                                                                                         ArrayColumn<T> &outputDataCol,
    8132             :                                                                                                                                                         ArrayColumn<bool> &outputFlagCol)
    8133             : {
    8134           0 :         IPosition outputPlaneShape = outputDataPlane.shape();
    8135           0 :         uInt nCorrs = outputPlaneShape(0);
    8136           0 :         IPosition outputPlaneShape_i(2,nCorrs,chansPerOutputSpw_p);
    8137           0 :         Slice sliceX(0,nCorrs);
    8138             : 
    8139             :         uInt spw_i;
    8140           0 :         uInt nspws = nspws_p-1;
    8141           0 :         for (spw_i=0;spw_i<nspws;spw_i++)
    8142             :         {
    8143           0 :                 uInt outRow = row+spw_i;
    8144           0 :                 Slice sliceY(chansPerOutputSpw_p*spw_i,chansPerOutputSpw_p);
    8145           0 :                 writeOutputPlaneSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_i,outRow);
    8146           0 :                 (*this.*writeOutputFlagsPlaneSlices_p)( outputFlagsPlane,outputFlagCol,
    8147             :                                                                                                 sliceX,sliceY,outputPlaneShape_i,outRow);
    8148             :         }
    8149             : 
    8150           0 :         uInt outRow = row+spw_i;
    8151           0 :         IPosition outputPlaneShape_tail(2,nCorrs,tailOfChansforLastSpw_p);
    8152           0 :         Slice sliceY(chansPerOutputSpw_p*spw_i,tailOfChansforLastSpw_p);
    8153           0 :         writeOutputPlaneReshapedSlices(outputDataPlane,outputDataCol,sliceX,sliceY,outputPlaneShape_tail,outRow);
    8154           0 :         (*this.*writeOutputFlagsPlaneReshapedSlices_p)( outputFlagsPlane,outputFlagCol,
    8155             :                                                                                                         sliceX,sliceY,outputPlaneShape_tail,outRow);
    8156           0 : }
    8157             : 
    8158             : // -----------------------------------------------------------------------
    8159             : //
    8160             : // -----------------------------------------------------------------------
    8161           0 : void MSTransformManager::writeOutputFlagsPlaneSlices(   Matrix<bool> &outputPlane,
    8162             :                                                                                                                         ArrayColumn<bool> &outputCol,
    8163             :                                                                                                                         Slice &sliceX,
    8164             :                                                                                                                         Slice &sliceY,
    8165             :                                                                                                                         IPosition &outputPlaneShape,
    8166             :                                                                                                                         uInt &outputRow)
    8167             : {
    8168           0 :         writeOutputPlaneSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
    8169           0 : }
    8170             : 
    8171             : // -----------------------------------------------------------------------
    8172             : //
    8173             : // -----------------------------------------------------------------------
    8174           0 : void MSTransformManager::writeOutputFlagsPlaneReshapedSlices(   Matrix<bool> &outputPlane,
    8175             :                                                                                                                                         ArrayColumn<bool> &outputCol,
    8176             :                                                                                                                                         Slice &sliceX,
    8177             :                                                                                                                                         Slice &sliceY,
    8178             :                                                                                                                                         IPosition &outputPlaneShape,
    8179             :                                                                                                                                         uInt &outputRow)
    8180             : {
    8181           0 :         writeOutputPlaneReshapedSlices(outputPlane,outputCol,sliceX,sliceY,outputPlaneShape,outputRow);
    8182           0 : }
    8183             : 
    8184             : // -----------------------------------------------------------------------
    8185             : //
    8186             : // -----------------------------------------------------------------------
    8187           0 : template <class T> void MSTransformManager::writeOutputPlaneSlices(       Matrix<T> &outputPlane,
    8188             :                                                                                                                                                 ArrayColumn<T> &outputCol,
    8189             :                                                                                                                                                 Slice &sliceX,
    8190             :                                                                                                                                                 Slice &sliceY,
    8191             :                                                                                                                                                 IPosition &outputPlaneShape,
    8192             :                                                                                                                                                 uInt &outputRow)
    8193             : {
    8194           0 :         Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
    8195           0 :         outputCol.setShape(outputRow,outputPlaneShape);
    8196           0 :         outputCol.put(outputRow, outputPlane_i);
    8197           0 : }
    8198             : 
    8199             : // -----------------------------------------------------------------------
    8200             : //
    8201             : // -----------------------------------------------------------------------
    8202           0 : template <class T> void MSTransformManager::writeOutputPlaneReshapedSlices(       Matrix<T> &outputPlane,
    8203             :                                                                                                                                                                 ArrayColumn<T> &outputCol,
    8204             :                                                                                                                                                                 Slice &sliceX,
    8205             :                                                                                                                                                                 Slice &sliceY,
    8206             :                                                                                                                                                                 IPosition &outputPlaneShape,
    8207             :                                                                                                                                                                 uInt &outputRow)
    8208             : {
    8209           0 :         Matrix<T> outputPlane_i = outputPlane(sliceX,sliceY);
    8210           0 :         outputPlane_i.resize(outputPlaneShape,true);
    8211           0 :         outputCol.setShape(outputRow,outputPlaneShape);
    8212           0 :         outputCol.put(outputRow, outputPlane_i);
    8213           0 : }
    8214             : 
    8215             : // -----------------------------------------------------------------------
    8216             : //
    8217             : // -----------------------------------------------------------------------
    8218          48 : void MSTransformManager::setWeightStripeByReference(    uInt corrIndex,
    8219             :                                                                                                                         Matrix<Float> &inputWeightsPlane,
    8220             :                                                                                                                         Vector<Float> &inputWeightsStripe)
    8221             : {
    8222          48 :         inputWeightsStripe.reference(inputWeightsPlane.row(corrIndex));
    8223          48 : }
    8224             : 
    8225             : // -----------------------------------------------------------------------
    8226             : //
    8227             : // -----------------------------------------------------------------------
    8228       38872 : void MSTransformManager::transformStripeOfData(Int inputSpw,
    8229             :                                                const Vector<Complex> &inputDataStripe,
    8230             :                                                const Vector<bool> &inputFlagsStripe,
    8231             :                                                const Vector<Float> &inputWeightsStripe,
    8232             :                                                Vector<Complex> &outputDataStripe,
    8233             :                                                Vector<bool> &outputFlagsStripe)
    8234             : {
    8235       38872 :     if(!smooth_spw_p.empty())
    8236             :     {
    8237             :         // Skip this SPW if it is not found in the list of SPWs to smooth
    8238           0 :         if( std::find(smooth_spw_p.begin(), smooth_spw_p.end(), inputSpw) == smooth_spw_p.end())
    8239             :         {
    8240           0 :             outputDataStripe = inputDataStripe;
    8241           0 :             outputFlagsStripe = inputFlagsStripe;
    8242           0 :             return;
    8243             :         }
    8244             :     }
    8245             : 
    8246       38872 :     auto shapeBefore = outputDataStripe.shape();
    8247       38872 :     (*this.*transformStripeOfDataComplex_p)(inputSpw, inputDataStripe, inputFlagsStripe,
    8248             :                                             inputWeightsStripe, outputDataStripe,
    8249             :                                             outputFlagsStripe);
    8250       38872 :     auto shapeAfter = outputDataStripe.shape();
    8251       38872 :     if (shapeAfter != shapeBefore) {
    8252           0 :         ostringstream msg;
    8253             :         msg << "Shape of output complex data stripe changed after applying "
    8254           0 :             << "transformation. Output shape expected before transformation: "
    8255           0 :             << shapeBefore
    8256           0 :             << ". Output shape produced by transformation: " << shapeAfter;
    8257           0 :         logger_p << LogIO::DEBUG1 << LogOrigin("MSTransformManager",__FUNCTION__)
    8258           0 :                  << LogIO::POST;
    8259           0 :         throw AipsError(msg.str());
    8260           0 :     }
    8261       38872 : }
    8262             : 
    8263             : // -----------------------------------------------------------------------
    8264             : //
    8265             : // -----------------------------------------------------------------------
    8266       25984 : void MSTransformManager::transformStripeOfData(Int inputSpw,
    8267             :                                                const Vector<Float> &inputDataStripe,
    8268             :                                                const Vector<bool> &inputFlagsStripe,
    8269             :                                                const Vector<Float> &inputWeightsStripe,
    8270             :                                                Vector<Float> &outputDataStripe,
    8271             :                                                Vector<bool> &outputFlagsStripe)
    8272             : {
    8273       25984 :         (*this.*transformStripeOfDataFloat_p)(  inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8274             :                                                                                         outputDataStripe,outputFlagsStripe);
    8275       25984 : }
    8276             : 
    8277             : // -----------------------------------------------------------------------
    8278             : //
    8279             : // -----------------------------------------------------------------------
    8280       64856 : template <class T> void MSTransformManager::average(Int inputSpw,
    8281             :                                                     const Vector<T> &inputDataStripe,
    8282             :                                                     const Vector<bool> &inputFlagsStripe,
    8283             :                                                     const Vector<Float> &inputWeightsStripe,
    8284             :                                                     Vector<T> &outputDataStripe,
    8285             :                                                     Vector<bool> &outputFlagsStripe)
    8286             : {
    8287       64856 :         uInt width = freqbinMap_p[inputSpw];
    8288       64856 :         uInt startChan = 0;
    8289       64856 :         uInt outChanIndex = 0;
    8290       64856 :         uInt tail = inputDataStripe.size() % width;
    8291      204488 :         while (outChanIndex < outputDataStripe.size())
    8292             :         {
    8293      139632 :                 averageKernel(  inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8294             :                                                 outputDataStripe,outputFlagsStripe,startChan,outChanIndex,width);
    8295      139632 :                 startChan += width;
    8296      139632 :                 outChanIndex += 1;
    8297             :         }
    8298             : 
    8299             :         // jagonzal: The last channel is dropped when there are not enough input channels
    8300             :         //           to populate it only when there is no regridding afterwards
    8301       64856 :         if (tail and (outChanIndex <= outputDataStripe.size()-1) )
    8302             :         {
    8303           0 :                 averageKernel(  inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8304             :                                                 outputDataStripe,outputFlagsStripe,startChan,outChanIndex,tail);
    8305             :         }
    8306             : 
    8307       64856 :         return;
    8308             : }
    8309             : 
    8310             : // -----------------------------------------------------------------------
    8311             : //
    8312             : // -----------------------------------------------------------------------
    8313           0 : template <class T> void  MSTransformManager::simpleAverage(uInt width,
    8314             :                                                            const Vector<T> &inputData,
    8315             :                                                            Vector<T> &outputData)
    8316             : {
    8317             :         // Dummy variables
    8318           0 :         Vector<bool> inputFlags,outputFlags;
    8319           0 :         Vector<Float> inputWeights;
    8320             : 
    8321           0 :         uInt startChan = 0;
    8322           0 :         uInt outChanIndex = 0;
    8323           0 :         uInt tail = inputData.size() % width;
    8324           0 :         uInt limit = inputData.size() - tail;
    8325           0 :         while (startChan < limit)
    8326             :         {
    8327           0 :                 simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,width);
    8328           0 :                 startChan += width;
    8329           0 :                 outChanIndex += 1;
    8330             :         }
    8331             : 
    8332             :         // jagonzal: The last channel is dropped when there are not enough input channels
    8333             :         //           to populate it only when there is no regridding afterwards
    8334           0 :         if (tail and (outChanIndex <= outputData.size()-1) )
    8335             :         {
    8336           0 :                 simpleAverageKernel(inputData,inputFlags,inputWeights,outputData,outputFlags,startChan,outChanIndex,tail);
    8337             :         }
    8338             : 
    8339           0 :         return;
    8340           0 : }
    8341             : 
    8342             : // -----------------------------------------------------------------------
    8343             : //
    8344             : // -----------------------------------------------------------------------
    8345       82704 : void MSTransformManager::averageKernel(const Vector<Complex> &inputData,
    8346             :                                        const Vector<bool> &inputFlags,
    8347             :                                        const Vector<Float> &inputWeights,
    8348             :                                        Vector<Complex> &outputData,
    8349             :                                        Vector<bool> &outputFlags,
    8350             :                                        uInt startInputPos,
    8351             :                                        uInt outputPos,
    8352             :                                        uInt width)
    8353             : {
    8354       82704 :         (*this.*averageKernelComplex_p)(        inputData,inputFlags,inputWeights,
    8355             :                                                                                 outputData,outputFlags,startInputPos,outputPos,width);
    8356       82704 :         return;
    8357             : }
    8358             : 
    8359             : // -----------------------------------------------------------------------
    8360             : //
    8361             : // -----------------------------------------------------------------------
    8362       56928 : void MSTransformManager::averageKernel(const Vector<Float> &inputData,
    8363             :                                        const Vector<bool> &inputFlags,
    8364             :                                        const Vector<Float> &inputWeights,
    8365             :                                        Vector<Float> &outputData,
    8366             :                                        Vector<bool> &outputFlags,
    8367             :                                        uInt startInputPos,
    8368             :                                        uInt outputPos,
    8369             :                                                                                         uInt width)
    8370             : {
    8371       56928 :         (*this.*averageKernelFloat_p)(  inputData,inputFlags,inputWeights,
    8372             :                                                                         outputData,outputFlags,startInputPos,outputPos,width);
    8373       56928 :         return;
    8374             : }
    8375             : 
    8376             : // -----------------------------------------------------------------------
    8377             : //
    8378             : // -----------------------------------------------------------------------
    8379           0 : template <class T> void MSTransformManager::simpleAverageKernel(const Vector<T> &inputData,
    8380             :                                                                 const Vector<bool> &,
    8381             :                                                                 const Vector<Float> &,
    8382             :                                                                 Vector<T> &outputData,
    8383             :                                                                 Vector<bool> &,
    8384             :                                                                 uInt startInputPos,
    8385             :                                                                 uInt outputPos,
    8386             :                                                                                                                                         uInt width)
    8387             : {
    8388           0 :         uInt pos = startInputPos + 1;
    8389           0 :         uInt counts = 1;
    8390           0 :         T avg = inputData(startInputPos);
    8391           0 :         while (counts < width)
    8392             :         {
    8393           0 :                 avg += inputData(pos);
    8394           0 :                 counts += 1;
    8395           0 :                 pos += 1;
    8396             :         }
    8397             : 
    8398           0 :         if (counts > 0)
    8399             :         {
    8400           0 :                 avg /= counts;
    8401             :         }
    8402             : 
    8403           0 :         outputData(outputPos) = avg;
    8404             : 
    8405           0 :         return;
    8406             : }
    8407             : 
    8408             : // -----------------------------------------------------------------------
    8409             : //
    8410             : // -----------------------------------------------------------------------
    8411           0 : template <class T> void MSTransformManager::flagAverageKernel(const Vector<T> &inputData,
    8412             :                                                               const Vector<bool> &inputFlags,
    8413             :                                                               const Vector<Float> &,
    8414             :                                                               Vector<T> &outputData,
    8415             :                                                               Vector<bool> &outputFlags,
    8416             :                                                               uInt startInputPos,
    8417             :                                                               uInt outputPos,
    8418             :                                                               uInt width)
    8419             : {
    8420           0 :         uInt samples = 1;
    8421           0 :         uInt pos = startInputPos + 1;
    8422           0 :         uInt counts = !inputFlags(startInputPos);
    8423           0 :         T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
    8424           0 :         while (samples < width)
    8425             :         {
    8426           0 :                 avg += inputData(pos)*(!inputFlags(pos));
    8427           0 :                 counts += (!inputFlags(pos));
    8428           0 :                 samples += 1;
    8429           0 :                 pos += 1;
    8430             :         }
    8431             : 
    8432           0 :         if (counts > 0)
    8433             :         {
    8434           0 :                 avg /= counts;
    8435             :         }
    8436             :         else
    8437             :         {
    8438           0 :                 outputFlags(outputPos) = true;
    8439             :         }
    8440             : 
    8441           0 :         outputData(outputPos) = avg;
    8442             : 
    8443           0 :         return;
    8444             : }
    8445             : 
    8446             : // -----------------------------------------------------------------------
    8447             : //
    8448             : // -----------------------------------------------------------------------
    8449           0 : template <class T> void MSTransformManager::weightAverageKernel(const Vector<T> &inputData,
    8450             :                                                                 const Vector<bool> &,
    8451             :                                                                 const Vector<Float> &inputWeights,
    8452             :                                                                 Vector<T> &outputData,
    8453             :                                                                 Vector<bool> &outputFlags,
    8454             :                                                                 uInt startInputPos,
    8455             :                                                                 uInt outputPos,
    8456             :                                                                 uInt width)
    8457             : {
    8458           0 :         uInt samples = 1;
    8459           0 :         uInt pos = startInputPos + 1;
    8460           0 :         Float counts = inputWeights(startInputPos);
    8461           0 :         T avg = inputData(startInputPos)*inputWeights(startInputPos);
    8462           0 :         while (samples < width)
    8463             :         {
    8464           0 :                 avg += inputData(pos)*inputWeights(pos);
    8465           0 :                 counts += inputWeights(pos);
    8466           0 :                 samples += 1;
    8467           0 :                 pos += 1;
    8468             :         }
    8469             : 
    8470           0 :         if (counts > 0)
    8471             :         {
    8472           0 :                 avg /= counts;
    8473             :         }
    8474             :         else
    8475             :         {
    8476           0 :                 outputFlags(outputPos) = true;
    8477             :         }
    8478             : 
    8479           0 :         outputData(outputPos) = avg;
    8480             : 
    8481           0 :         return;
    8482             : }
    8483             : 
    8484             : // -----------------------------------------------------------------------
    8485             : //
    8486             : // -----------------------------------------------------------------------
    8487           0 : template <class T> void MSTransformManager::cumSumKernel(const Vector<T> &inputData,
    8488             :                                                          const Vector<bool> &,
    8489             :                                                          const Vector<Float> &,
    8490             :                                                          Vector<T> &outputData,
    8491             :                                                          Vector<bool> &,
    8492             :                                                          uInt startInputPos,
    8493             :                                                          uInt outputPos,
    8494             :                                                          uInt width)
    8495             : {
    8496           0 :         uInt pos = startInputPos + 1;
    8497           0 :         uInt counts = 1;
    8498           0 :         T avg = inputData(startInputPos);
    8499           0 :         while (counts < width)
    8500             :         {
    8501           0 :                 avg += inputData(pos);
    8502           0 :                 counts += 1;
    8503           0 :                 pos += 1;
    8504             :         }
    8505             : 
    8506           0 :         outputData(outputPos) = avg;
    8507             : 
    8508           0 :         return;
    8509             : }
    8510             : 
    8511             : // -----------------------------------------------------------------------
    8512             : //
    8513             : // -----------------------------------------------------------------------
    8514           0 : template <class T> void MSTransformManager::flagWeightAverageKernel(const Vector<T> &inputData,
    8515             :                                                                     const Vector<bool> &inputFlags,
    8516             :                                                                     const Vector<Float> &inputWeights,
    8517             :                                                                     Vector<T> &outputData,
    8518             :                                                                     Vector<bool> &outputFlags,
    8519             :                                                                     uInt startInputPos,
    8520             :                                                                     uInt outputPos,
    8521             :                                                                     uInt width)
    8522             : {
    8523           0 :         uInt samples = 1;
    8524           0 :         uInt pos = startInputPos + 1;
    8525           0 :         Float totalWeight = inputWeights(startInputPos)*(!inputFlags(startInputPos));
    8526           0 :         Float counts = totalWeight;
    8527           0 :         T avg = inputData(startInputPos)*totalWeight;
    8528           0 :         while (samples < width)
    8529             :         {
    8530           0 :                 totalWeight = inputWeights(pos)*(!inputFlags(pos));
    8531           0 :                 avg += inputData(pos)*totalWeight;
    8532           0 :                 counts += totalWeight;
    8533           0 :                 samples += 1;
    8534           0 :                 pos += 1;
    8535             :         }
    8536             : 
    8537           0 :         if (counts > 0)
    8538             :         {
    8539           0 :                 avg /= counts;
    8540             :         }
    8541             :         else
    8542             :         {
    8543           0 :                 outputFlags(outputPos) = true;
    8544             :         }
    8545             : 
    8546           0 :         outputData(outputPos) = avg;
    8547             : 
    8548           0 :         return;
    8549             : }
    8550             : 
    8551             : // -----------------------------------------------------------------------
    8552             : //
    8553             : // -----------------------------------------------------------------------
    8554           0 : template <class T> void MSTransformManager::flagCumSumKernel(const Vector<T> &inputData,
    8555             :                                                              const Vector<bool> &inputFlags,
    8556             :                                                              const Vector<Float> &,
    8557             :                                                              Vector<T> &outputData,
    8558             :                                                              Vector<bool> &,
    8559             :                                                              uInt startInputPos,
    8560             :                                                              uInt outputPos,
    8561             :                                                              uInt width)
    8562             : {
    8563           0 :         uInt samples = 1;
    8564           0 :         uInt pos = startInputPos + 1;
    8565           0 :         T avg = inputData(startInputPos)*(!inputFlags(startInputPos));
    8566           0 :         while (samples < width)
    8567             :         {
    8568           0 :                 avg += inputData(pos)*(!inputFlags(pos));
    8569           0 :                 samples += 1;
    8570           0 :                 pos += 1;
    8571             :         }
    8572             : 
    8573           0 :         outputData(outputPos) = avg;
    8574             : 
    8575           0 :         return;
    8576             : }
    8577             : 
    8578             : // -----------------------------------------------------------------------
    8579             : //
    8580             : // -----------------------------------------------------------------------
    8581       81168 : template <class T> void MSTransformManager::flagNonZeroAverageKernel(const Vector<T> &inputData,
    8582             :                                                                      const Vector<bool> &inputFlags,
    8583             :                                                                      const Vector<Float> & /* inputWeights */,
    8584             :                                                                      Vector<T> &outputData,
    8585             :                                                                      Vector<bool> &outputFlags,
    8586             :                                                                      uInt startInputPos,
    8587             :                                                                      uInt outputPos,
    8588             :                                                                      uInt width)
    8589             : {
    8590       81168 :         T avg = 0;
    8591       81168 :         uInt samples = 0;
    8592       81168 :         uInt inputPos = 0;
    8593       81168 :         bool accumulatorFlag = inputFlags(startInputPos);
    8594             : 
    8595     2565904 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8596             :         {
    8597             :                 // Get input index
    8598     2484736 :                 inputPos = startInputPos + sample_i;
    8599             : 
    8600             :                 // true/true or false/false
    8601     2484736 :                 if (accumulatorFlag == inputFlags(inputPos))
    8602             :                 {
    8603     2484736 :                         samples += 1;
    8604     2484736 :                         avg += inputData(inputPos);
    8605             :                 }
    8606             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8607           0 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8608             :                 {
    8609           0 :                         accumulatorFlag = false;
    8610           0 :                         samples = 1;
    8611           0 :                         avg = inputData(inputPos);
    8612             :                 }
    8613             :         }
    8614             : 
    8615             : 
    8616             :         // Apply normalization factor
    8617       81168 :         if (samples > 0)
    8618             :         {
    8619       81168 :                 avg /= samples;
    8620       81168 :                 outputData(outputPos) = avg;
    8621             :         }
    8622             :         // This should never happen
    8623             :         else
    8624             :         {
    8625           0 :                 accumulatorFlag = true;
    8626           0 :                 outputData(outputPos) = 0; // this should be a code error
    8627             :         }
    8628             : 
    8629             : 
    8630             :         // Set output flag (it is initialized to false)
    8631       81168 :         if (accumulatorFlag)
    8632             :         {
    8633         193 :                 outputFlags(outputPos) = true;
    8634             :         }
    8635             : 
    8636      162336 :         return;
    8637             : }
    8638             : 
    8639             : 
    8640             : // -----------------------------------------------------------------------
    8641             : //
    8642             : // -----------------------------------------------------------------------
    8643        1536 : template <class T> void MSTransformManager::flagWeightNonZeroAverageKernel(const Vector<T> &inputData,
    8644             :                                                                            const Vector<bool> &inputFlags,
    8645             :                                                                            const Vector<Float> &inputWeights,
    8646             :                                                                            Vector<T> &outputData,
    8647             :                                                                            Vector<bool> &outputFlags,
    8648             :                                                                            uInt startInputPos,
    8649             :                                                                            uInt outputPos,
    8650             :                                                                            uInt width)
    8651             : {
    8652        1536 :         T avg = 0;
    8653        1536 :         T normalization = 0;
    8654        1536 :         uInt inputPos = 0;
    8655        1536 :         bool accumulatorFlag = inputFlags(startInputPos);
    8656             : 
    8657        4608 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8658             :         {
    8659             :                 // Get input index
    8660        3072 :                 inputPos = startInputPos + sample_i;
    8661             : 
    8662             :                 // true/true or false/false
    8663        3072 :                 if (accumulatorFlag == inputFlags(inputPos))
    8664             :                 {
    8665        3072 :                         normalization += inputWeights(inputPos);
    8666        3072 :                         avg += inputData(inputPos)*inputWeights(inputPos);
    8667             :                 }
    8668             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8669           0 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8670             :                 {
    8671           0 :                         accumulatorFlag = false;
    8672           0 :                         normalization = inputWeights(inputPos);
    8673           0 :                         avg = inputData(inputPos)*inputWeights(inputPos);
    8674             :                 }
    8675             :         }
    8676             : 
    8677             : 
    8678             :         // Apply normalization factor
    8679        1536 :         if (normalization > 0)
    8680             :         {
    8681        1536 :                 avg /= normalization;
    8682        1536 :                 outputData(outputPos) = avg;
    8683             :         }
    8684             :         // If all weights are zero set accumulatorFlag to true
    8685             :         else
    8686             :         {
    8687           0 :                 accumulatorFlag = true;
    8688           0 :                 outputData(outputPos) = 0; // If all weights are zero then the avg is 0 too
    8689             :         }
    8690             : 
    8691             : 
    8692             :         // Set output flag (it is initialized to false)
    8693        1536 :         if (accumulatorFlag)
    8694             :         {
    8695          52 :                 outputFlags(outputPos) = true;
    8696             :         }
    8697             : 
    8698        3072 :         return;
    8699             : }
    8700             : 
    8701             : // -----------------------------------------------------------------------
    8702             : //
    8703             : // -----------------------------------------------------------------------
    8704       56928 : template <class T> void MSTransformManager::flagCumSumNonZeroKernel(const Vector<T> &inputData,
    8705             :                                                                     const Vector<bool> &inputFlags,
    8706             :                                                                     const Vector<Float> & /* inputWeights */,
    8707             :                                                                     Vector<T> &outputData,
    8708             :                                                                     Vector<bool> &outputFlags,
    8709             :                                                                     uInt startInputPos,
    8710             :                                                                     uInt outputPos,
    8711             :                                                                     uInt width)
    8712             : {
    8713       56928 :         T avg = 0;
    8714       56928 :         uInt inputPos = 0;
    8715       56928 :         bool accumulatorFlag = inputFlags(startInputPos);
    8716             : 
    8717     1719904 :         for (uInt sample_i=0;sample_i<width;sample_i++)
    8718             :         {
    8719             :                 // Get input index
    8720     1662976 :                 inputPos = startInputPos + sample_i;
    8721             : 
    8722             :                 // true/true or false/false
    8723     1662976 :                 if (accumulatorFlag == inputFlags(inputPos))
    8724             :                 {
    8725     1662976 :                         avg += inputData(inputPos);
    8726             :                 }
    8727             :                 // true/false: Reset accumulation when accumulator switches from flagged to unflag
    8728           0 :                 else if ( (accumulatorFlag == true) and (inputFlags(inputPos) == false) )
    8729             :                 {
    8730           0 :                         accumulatorFlag = false;
    8731           0 :                         avg = inputData(inputPos);
    8732             :                 }
    8733             :         }
    8734             : 
    8735       56928 :         outputData(outputPos) = avg;
    8736             : 
    8737             :         // Set output flag (it is initialized to false)
    8738       56928 :         if (accumulatorFlag)
    8739             :         {
    8740         245 :                 outputFlags(outputPos) = true;
    8741             :         }
    8742             : 
    8743       56928 :         return;
    8744             : }
    8745             : 
    8746             : 
    8747             : // -----------------------------------------------------------------------
    8748             : //
    8749             : // -----------------------------------------------------------------------
    8750           0 : template <class T> void MSTransformManager::smooth(Int ,
    8751             :                                                    const Vector<T> &inputDataStripe,
    8752             :                                                    const Vector<bool> &inputFlagsStripe,
    8753             :                                                    const Vector<Float> &inputWeightsStripe,
    8754             :                                                    Vector<T> &outputDataStripe,
    8755             :                                                    Vector<bool> &outputFlagsStripe)
    8756             : {
    8757             :         // Calculate limits
    8758           0 :         uInt width = smoothBin_p;
    8759           0 :         uInt halfWidth = width / 2;
    8760           0 :         uInt outChanStart = halfWidth;
    8761           0 :         uInt outChanStop = inputDataStripe.size() - outChanStart;
    8762             : 
    8763             :         // Main loop
    8764           0 :         for (uInt outChan = outChanStart; outChan<outChanStop; outChan++)
    8765             :         {
    8766           0 :                 smoothKernel(   inputDataStripe,inputFlagsStripe,inputWeightsStripe,
    8767             :                                                 outputDataStripe,outputFlagsStripe,outChan);
    8768             :         }
    8769             : 
    8770             :         // Flag lower edge
    8771           0 :         for (uInt outChan = 0; outChan<outChanStart; outChan++)
    8772             :         {
    8773           0 :                 outputFlagsStripe(outChan) = true;
    8774           0 :                 outputDataStripe(outChan) = inputDataStripe(outChan);
    8775             :         }
    8776             : 
    8777             :         // Flag higher edge
    8778           0 :         for (uInt outChan = outChanStop; outChan<inputDataStripe.size(); outChan++)
    8779             :         {
    8780           0 :                 outputFlagsStripe(outChan) = true;
    8781           0 :                 outputDataStripe(outChan) = inputDataStripe(outChan);
    8782             :         }
    8783             : 
    8784           0 :         return;
    8785             : }
    8786             : 
    8787             : // -----------------------------------------------------------------------
    8788             : //
    8789             : // -----------------------------------------------------------------------
    8790           0 : void MSTransformManager::smoothKernel(const Vector<Complex> &inputData,
    8791             :                                       const Vector<bool> &inputFlags,
    8792             :                                       const Vector<Float> &inputWeights,
    8793             :                                       Vector<Complex> &outputData,
    8794             :                                       Vector<bool> &outputFlags,
    8795             :                                       uInt outputPos)
    8796             : {
    8797           0 :         (*this.*smoothKernelComplex_p)( inputData,inputFlags,inputWeights,
    8798             :                                                                                 outputData,outputFlags,outputPos);
    8799           0 :         return;
    8800             : }
    8801             : 
    8802             : // -----------------------------------------------------------------------
    8803             : //
    8804             : // -----------------------------------------------------------------------
    8805           0 : void MSTransformManager::smoothKernel(const Vector<Float> &inputData,
    8806             :                                       const Vector<bool> &inputFlags,
    8807             :                                       const Vector<Float> &inputWeights,
    8808             :                                       Vector<Float> &outputData,
    8809             :                                       Vector<bool> &outputFlags,
    8810             :                                       uInt outputPos)
    8811             : {
    8812           0 :         (*this.*smoothKernelFloat_p)(   inputData,inputFlags,inputWeights,
    8813             :                                                                         outputData,outputFlags,outputPos);
    8814           0 :         return;
    8815             : }
    8816             : 
    8817             : // -----------------------------------------------------------------------
    8818             : //
    8819             : // -----------------------------------------------------------------------
    8820           0 : template <class T> void  MSTransformManager::plainSmooth(const Vector<T> &inputData,
    8821             :                                                          const Vector<bool> &inputFlags,
    8822             :                                                          const Vector<Float> &,
    8823             :                                                          Vector<T> &outputData,
    8824             :                                                          Vector<bool> &outputFlags,
    8825             :                                                          uInt outputPos)
    8826             : {
    8827           0 :         uInt halfWidth = smoothBin_p / 2;
    8828             : 
    8829             :         // Initialization
    8830           0 :         outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
    8831           0 :         outputData(outputPos) = smoothCoeff_p(0)*inputData(outputPos-halfWidth);
    8832             : 
    8833             :         // Main loop
    8834           0 :         for (uInt i = 1; i<smoothBin_p;i++)
    8835             :         {
    8836           0 :                 outputData(outputPos) += smoothCoeff_p(i)*inputData(outputPos-halfWidth+i);
    8837             : 
    8838             :                 // Output sample is flagged if any of the contributors are flagged
    8839           0 :                 if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
    8840             :         }
    8841             : 
    8842           0 :         return;
    8843             : }
    8844             : 
    8845             : // -----------------------------------------------------------------------
    8846             : //
    8847             : // -----------------------------------------------------------------------
    8848           0 : template <class T> void  MSTransformManager::plainSmoothSpectrum(const Vector<T> &inputData,
    8849             :                                                                  const Vector<bool> &inputFlags,
    8850             :                                                                  const Vector<Float> &,
    8851             :                                                                  Vector<T> &outputData,
    8852             :                                                                  Vector<bool> &outputFlags,
    8853             :                                                                  uInt outputPos)
    8854             : {
    8855           0 :         uInt halfWidth = smoothBin_p / 2;
    8856             : 
    8857             :         // Initialization (mind for zeros as there is a division operation)
    8858           0 :         if (inputData(outputPos-halfWidth) <= FLT_MIN)
    8859             :         {
    8860           0 :                 outputData(outputPos) = 0;
    8861           0 :                 outputFlags(outputPos) = true;
    8862             :         }
    8863             :         else
    8864             :         {
    8865           0 :                 outputFlags(outputPos) = inputFlags(outputPos-halfWidth);
    8866           0 :                 outputData(outputPos) = smoothCoeff_p(0)*smoothCoeff_p(0)/inputData(outputPos-halfWidth);
    8867             :         }
    8868             : 
    8869             :         // Main accumulation loop
    8870           0 :         for (uInt i = 1; i<smoothBin_p;i++)
    8871             :         {
    8872             :                 // Mind for zeros as there is a division operation
    8873           0 :                 if (inputData(outputPos-halfWidth+i) <= FLT_MIN)
    8874             :                 {
    8875           0 :                         outputFlags(outputPos) = true;
    8876             :                 }
    8877             :                 else
    8878             :                 {
    8879           0 :                         outputData(outputPos) += smoothCoeff_p(i)*smoothCoeff_p(i)/inputData(outputPos-halfWidth+i);
    8880             : 
    8881             :                         // Output sample is flagged if any of the contributors are flagged
    8882           0 :                         if (inputFlags(outputPos-halfWidth+i)) outputFlags(outputPos)=true;
    8883             :                 }
    8884             :         }
    8885             : 
    8886             :         // Final propaged weight si the inverse of the accumulation
    8887           0 :         if (outputData(outputPos) > FLT_MIN)
    8888             :         {
    8889           0 :                 outputData(outputPos) = 1/outputData(outputPos);
    8890             :         }
    8891             : 
    8892           0 :         return;
    8893             : }
    8894             : 
    8895             : // -----------------------------------------------------------------------
    8896             : //
    8897             : // -----------------------------------------------------------------------
    8898           0 : template <class T> void MSTransformManager::regrid(Int inputSpw,
    8899             :                                                    const Vector<T> &inputDataStripe,
    8900             :                                                    const Vector<bool> &inputFlagsStripe,
    8901             :                                                    const Vector<Float> &inputWeightsStripe,
    8902             :                                                    Vector<T> &outputDataStripe,
    8903             :                                                    Vector<bool> &outputFlagsStripe)
    8904             : {
    8905             : 
    8906           0 :         regridCore(     inputSpw,
    8907             :                                 inputDataStripe,
    8908             :                                 inputFlagsStripe,
    8909             :                                 inputWeightsStripe,
    8910             :                                 outputDataStripe,
    8911             :                                 outputFlagsStripe);
    8912             : 
    8913           0 : }
    8914             : 
    8915             : // -----------------------------------------------------------------------
    8916             : //
    8917             : // -----------------------------------------------------------------------
    8918           0 : void MSTransformManager::regridCore(Int inputSpw,
    8919             :                                     const Vector<Complex> &inputDataStripe,
    8920             :                                     const Vector<bool> &inputFlagsStripe,
    8921             :                                     const Vector<Float> &inputWeightsStripe,
    8922             :                                     Vector<Complex> &outputDataStripe,
    8923             :                                     Vector<bool> &outputFlagsStripe)
    8924             : {
    8925             : 
    8926           0 :         (*this.*regridCoreComplex_p)(   inputSpw,
    8927             :                                                                         inputDataStripe,
    8928             :                                                                         inputFlagsStripe,
    8929             :                                                                         inputWeightsStripe,
    8930             :                                                                         outputDataStripe,
    8931             :                                                                         outputFlagsStripe);
    8932           0 : }
    8933             : 
    8934             : // -----------------------------------------------------------------------
    8935             : //
    8936             : // -----------------------------------------------------------------------
    8937           0 :   void MSTransformManager::regridCore(Int inputSpw,
    8938             :                                       const Vector<Float> &inputDataStripe,
    8939             :                                       const Vector<bool> &inputFlagsStripe,
    8940             :                                       const Vector<Float> &inputWeightsStripe,
    8941             :                                       Vector<Float> &outputDataStripe,
    8942             :                                       Vector<bool> &outputFlagsStripe)
    8943             : {
    8944           0 :         (*this.*regridCoreFloat_p)(     inputSpw,
    8945             :                                                                 inputDataStripe,
    8946             :                                                                 inputFlagsStripe,
    8947             :                                                                 inputWeightsStripe,
    8948             :                                                                 outputDataStripe,
    8949             :                                                                 outputFlagsStripe);
    8950           0 : }
    8951             : 
    8952             : // -----------------------------------------------------------------------
    8953             : //
    8954             : // -----------------------------------------------------------------------
    8955           0 : void MSTransformManager::fftshift(Int ,
    8956             :                                   const Vector<Complex> &inputDataStripe,
    8957             :                                   const Vector<bool> &inputFlagsStripe,
    8958             :                                   const Vector<Float> &,
    8959             :                                   Vector<Complex> &outputDataStripe,
    8960             :                                   Vector<bool> &outputFlagsStripe)
    8961             : {
    8962           0 :         fFFTServer_p.fftshift(outputDataStripe,
    8963             :                                         outputFlagsStripe,
    8964           0 :                                         (const Vector<Complex>)inputDataStripe,
    8965           0 :                                         (const Vector<bool>)inputFlagsStripe,
    8966           0 :                                         (const uInt)0, // In vectors axis 0 is the only dimension
    8967           0 :                                         (const Double)fftShift_p,
    8968             :                                         false, // A good data point has its flag set to false
    8969             :                                         false);
    8970           0 : }
    8971             : 
    8972             : // -----------------------------------------------------------------------
    8973             : //
    8974             : // -----------------------------------------------------------------------
    8975           0 : void MSTransformManager::fftshift(Int ,
    8976             :                                   const Vector<Float> &inputDataStripe,
    8977             :                                   const Vector<bool> &inputFlagsStripe,
    8978             :                                   const Vector<Float> &,
    8979             :                                   Vector<Float> &outputDataStripe,
    8980             :                                   Vector<bool> &outputFlagsStripe)
    8981             : {
    8982           0 :     fFFTServer_p.fftshift(outputDataStripe,
    8983             :                                         outputFlagsStripe,
    8984           0 :                                         (const Vector<Float>)inputDataStripe,
    8985           0 :                                         (const Vector<bool>)inputFlagsStripe,
    8986           0 :                                         (const uInt)0, // In vectors axis 0 is the only dimension
    8987           0 :                                         (const Double)fftShift_p,
    8988             :                                         false); // A good data point has its flag set to false
    8989           0 : }
    8990             : 
    8991             : // -----------------------------------------------------------------------
    8992             : //
    8993             : // -----------------------------------------------------------------------
    8994           0 : template <class T> void MSTransformManager::interpol1D(Int inputSpw,
    8995             :                                                        const Vector<T> &inputDataStripe,
    8996             :                                                        const Vector<bool> &inputFlagsStripe,
    8997             :                                                        const Vector<Float> &,
    8998             :                                                        Vector<T> &outputDataStripe,
    8999             :                                                        Vector<bool> &outputFlagsStripe)
    9000             : {
    9001           0 :   if (inputDataStripe.size() < 2) {
    9002           0 :     outputDataStripe = inputDataStripe(0);
    9003           0 :     outputFlagsStripe = true;
    9004           0 :     return;
    9005             :   }
    9006             : 
    9007           0 :   if (!regridTClean_p) {
    9008           0 :     InterpolateArray1D<Double,T>::interpolate(outputDataStripe, // Output data
    9009             :                                               outputFlagsStripe, // Output flags
    9010           0 :                                               inputOutputSpwMap_p[inputSpw].second.CHAN_FREQ, // Out chan freq
    9011           0 :                                               inputOutputSpwMap_p[inputSpw].first.CHAN_FREQ_aux, // In chan freq
    9012             :                                               inputDataStripe, // Input data
    9013             :                                               inputFlagsStripe, // Input Flags
    9014           0 :                                               interpolationMethod_p, // Interpolation method
    9015             :                                               false, // A good data point has its flag set to false
    9016             :                                               false // If false extrapolated data points are set flagged
    9017             :                                               );
    9018             :   } else {
    9019           0 :     interpolateByChannelMap(inputSpw,
    9020             :                             inputDataStripe, inputFlagsStripe,
    9021             :                             outputDataStripe, outputFlagsStripe);
    9022             :   }
    9023             : }
    9024             : 
    9025             : /**
    9026             :  * Introduced to mimic the way tclean regrids when the factor between
    9027             :  * the output channel width and the input channel width is > 2.
    9028             :  * Ref. TransformMachines2/FTMachine.cc
    9029             :  *
    9030             :  * Uses a map from original input channels => fake output channels,
    9031             :  * where the fake output channels have the (lower) width of the
    9032             :  * input channels but are projected/aligned with the output channel
    9033             :  * grid.
    9034             :  *
    9035             :  * @param spw spw index of the input channels, to fetch original
    9036             :  *        input channel freqs
    9037             :  * @param inputDataStripe input data coming from regridCubeOfData,
    9038             :  *        transformAndWriteCubeOfData, etc. and passed to the
    9039             :  *        regrid/interpolation kernels.
    9040             :  * @param inputFlagsStripe flags for the inputDataStripe
    9041             :  * @param outputDataStripe will be interpolated by aggregating
    9042             :  *        input visibilities into wider channels
    9043             :  * @param outputFlagsStripe flags for outputDataStripe
    9044             :  */
    9045           0 : template <class T> void MSTransformManager::interpolateByChannelMap(Int spw,
    9046             :                                                                     const Vector<T> &inputDataStripe,
    9047             :                                                                     const Vector<bool> &inputFlagsStripe,
    9048             :                                                                     Vector<T> &outputDataStripe,
    9049             :                                                                     Vector<bool> &outputFlagsStripe)
    9050             : {
    9051           0 :   Vector<T> intermDataStripe;
    9052           0 :   Vector<bool> intermFlagsStripe;
    9053             :   // Bring frequencies from input grid to fake output grid ( the
    9054             :   // one with same widths as the original input channels).
    9055           0 :   InterpolateArray1D<Double,T>::interpolate(intermDataStripe,
    9056             :                                             intermFlagsStripe,
    9057           0 :                                             regridTCleanCHAN_FREQ_p, // Out channel freqs
    9058           0 :                                             inputOutputSpwMap_p[spw].first.CHAN_FREQ_aux, // Input chan freqs
    9059             :                                             inputDataStripe,
    9060             :                                             inputFlagsStripe,
    9061           0 :                                             interpolationMethod_p,
    9062             :                                             false, // flags
    9063             :                                             false // extrapolated data points are set flagged
    9064             :                                             );
    9065             : 
    9066             :   // Aggregate fine grain fake output channels into the final
    9067             :   // output channels
    9068           0 :   outputDataStripe = 0;
    9069           0 :   Vector<Double> outWeights;
    9070           0 :   outWeights.resize(outputDataStripe.size());
    9071           0 :   outWeights = 0.;
    9072           0 :   for (uInt mapIdx = 0; mapIdx < regridTCleanChanMap_p.size(); ++mapIdx) {
    9073           0 :     Int outIdx = regridTCleanChanMap_p[mapIdx];
    9074           0 :     if (outIdx < 0)
    9075           0 :       continue;
    9076             : 
    9077           0 :     outputDataStripe[outIdx] = (outputDataStripe[outIdx] * outWeights[outIdx] +
    9078           0 :                                 intermDataStripe[mapIdx]) /
    9079           0 :       (1. + outWeights[outIdx]);
    9080           0 :     outWeights[outIdx] += 1;
    9081           0 :     outputFlagsStripe[outIdx] |= intermFlagsStripe[mapIdx];
    9082             :   }
    9083           0 : }
    9084             : 
    9085             : // ------------------------------------------------------------------------
    9086             : // casacore::fftshift does not interpolate, it needs interpolation+fftshift
    9087             : // ------------------------------------------------------------------------
    9088           0 : template <class T> void MSTransformManager::interpol1Dfftshift(Int inputSpw,
    9089             :                                                                const Vector<T> &inputDataStripe,
    9090             :                                                                const Vector<bool> &inputFlagsStripe,
    9091             :                                                                const Vector<Float> &inputWeightsStripe,
    9092             :                                                                Vector<T> &outputDataStripe,
    9093             :                                                                Vector<bool> &outputFlagsStripe)
    9094             : {
    9095           0 :     Vector<T> regriddedDataStripe(outputDataStripe.shape(),T());
    9096           0 :     Vector<bool> regriddedFlagsStripe(outputFlagsStripe.shape(),false);
    9097             : 
    9098             :     // This linear interpolation provides a uniform grid (pre-condition to apply fftshift)
    9099           0 :     interpol1D(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,regriddedDataStripe,regriddedFlagsStripe);
    9100             : 
    9101             :     // fftshift takes care of time
    9102           0 :     fftshift(inputSpw,regriddedDataStripe,regriddedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9103           0 : }
    9104             : 
    9105             : // -----------------------------------------------------------------------
    9106             : //
    9107             : // -----------------------------------------------------------------------
    9108           0 : template <class T> void MSTransformManager::averageRegrid(Int inputSpw,
    9109             :                                                           const Vector<T> &inputDataStripe,
    9110             :                                                           const Vector<bool> &inputFlagsStripe,
    9111             :                                                           const Vector<Float> &inputWeightsStripe,
    9112             :                                                           Vector<T> &outputDataStripe,
    9113             :                                                           Vector<bool> &outputFlagsStripe)
    9114             : {
    9115           0 :         Vector<T> averagedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
    9116           0 :         Vector<bool> averagedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
    9117             : 
    9118           0 :         average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
    9119             : 
    9120           0 :         regrid(inputSpw,averagedDataStripe,averagedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9121             : 
    9122           0 :         return;
    9123           0 : }
    9124             : 
    9125             : // -----------------------------------------------------------------------
    9126             : //
    9127             : // -----------------------------------------------------------------------
    9128           0 : template <class T> void MSTransformManager::smoothRegrid(Int inputSpw,
    9129             :                                                          const Vector<T> &inputDataStripe,
    9130             :                                                          const Vector<bool> &inputFlagsStripe,
    9131             :                                                          const Vector<Float> &inputWeightsStripe,
    9132             :                                                          Vector<T> &outputDataStripe,
    9133             :                                                          Vector<bool> &outputFlagsStripe)
    9134             : {
    9135           0 :         Vector<T> smoothedDataStripe(inputDataStripe.shape(),T());
    9136           0 :         Vector<bool> smoothedFlagsStripe(inputFlagsStripe.shape(),false);
    9137             : 
    9138           0 :         smooth(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe,smoothedDataStripe,smoothedFlagsStripe);
    9139             : 
    9140           0 :         regrid(inputSpw,smoothedDataStripe,smoothedFlagsStripe,inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9141             : 
    9142           0 :         return;
    9143           0 : }
    9144             : 
    9145             : // -----------------------------------------------------------------------
    9146             : //
    9147             : // -----------------------------------------------------------------------
    9148           0 : template <class T> void MSTransformManager::averageSmooth(Int inputSpw,
    9149             :                                                           const Vector<T> &inputDataStripe,
    9150             :                                                           const Vector<bool> &inputFlagsStripe,
    9151             :                                                           const Vector<Float> &inputWeightsStripe,
    9152             :                                                           Vector<T> &outputDataStripe,
    9153             :                                                           Vector<bool> &outputFlagsStripe)
    9154             : {
    9155           0 :         Vector<T> averagedDataStripe(outputDataStripe.shape(),T());
    9156           0 :         Vector<bool> averagedFlagsStripe(outputFlagsStripe.shape(),false);
    9157             : 
    9158           0 :         average(inputSpw,inputDataStripe,inputFlagsStripe,inputWeightsStripe, averagedDataStripe,averagedFlagsStripe);
    9159             : 
    9160           0 :         smooth(inputSpw,averagedDataStripe,averagedFlagsStripe, inputWeightsStripe, outputDataStripe,outputFlagsStripe);
    9161             : 
    9162           0 :         return;
    9163           0 : }
    9164             : 
    9165             : // -----------------------------------------------------------------------
    9166             : //
    9167             : // -----------------------------------------------------------------------
    9168           0 :   template <class T> void MSTransformManager::averageSmoothRegrid(Int inputSpw,
    9169             :                                                                   const Vector<T> &inputDataStripe,
    9170             :                                                                   const Vector<bool> &inputFlagsStripe,
    9171             :                                                                   const Vector<Float> &inputWeightsStripe,
    9172             :                                                                   Vector<T> &outputDataStripe,
    9173             :                                                                   Vector<bool> &outputFlagsStripe)
    9174             : {
    9175           0 :         Vector<T> averageSmoothedDataStripe(numOfCombInterChanMap_p[inputSpw],T());
    9176           0 :         Vector<bool> averageSmoothedFlagsStripe(numOfCombInterChanMap_p[inputSpw],false);
    9177             : 
    9178           0 :         averageSmooth(  inputSpw,inputDataStripe,inputFlagsStripe,
    9179             :                                         inputWeightsStripe,averageSmoothedDataStripe,averageSmoothedFlagsStripe);
    9180             : 
    9181           0 :         regrid( inputSpw,averageSmoothedDataStripe,averageSmoothedFlagsStripe,
    9182             :                         inputWeightsStripe,outputDataStripe,outputFlagsStripe);
    9183             : 
    9184           0 :         return;
    9185           0 : }
    9186             : 
    9187             : // -----------------------------------------------------------------------
    9188             : //
    9189             : // -----------------------------------------------------------------------
    9190           0 : void MSTransformManager::smoothFourierFloat(Int,
    9191             :                                             const Vector<Float> &inputDataStripe,
    9192             :                                             const Vector<bool> &inputFlagStripe,
    9193             :                                             const Vector<Float> &,
    9194             :                                             Vector<Float> &outputDataStripe,
    9195             :                                             Vector<bool> &outputFlagStripe)
    9196             : {
    9197             :     // replace flagged channel data with zero
    9198           0 :     auto mutableInputDataStripe = inputDataStripe;
    9199           0 :     Int const numChan = mutableInputDataStripe.nelements();
    9200           0 :     for (Int ichan = 0; ichan < numChan; ++ichan) {
    9201           0 :         if (inputFlagStripe[ichan]) {
    9202           0 :             mutableInputDataStripe[ichan] = 0.0f;
    9203             :         }
    9204             :     }
    9205             : 
    9206             :     // execute convolution
    9207           0 :     Convolver<Float> *convolver = getConvolver(numChan);
    9208           0 :     convolver->linearConv(outputDataStripe, mutableInputDataStripe);
    9209             : 
    9210             :     // copy input flags
    9211           0 :     outputFlagStripe = inputFlagStripe;
    9212           0 : }
    9213             : 
    9214             : // -----------------------------------------------------------------------
    9215             : //
    9216             : // -----------------------------------------------------------------------
    9217           0 : void MSTransformManager::smoothFourierComplex(Int n,
    9218             :                                               const Vector<Complex> &inputDataStripe,
    9219             :                                               const Vector<bool> &inputFlagStripe,
    9220             :                                               const Vector<Float> &inputWeightStripe,
    9221             :                                               Vector<Complex> &outputDataStripe, Vector<bool> &outputFlagStripe)
    9222             : {
    9223           0 :     Vector<Float> inputDataStripeFloat = real(inputDataStripe);
    9224           0 :     Vector<Float> outputDataStripeFloat(inputDataStripeFloat.nelements());
    9225           0 :     smoothFourierFloat(n, inputDataStripeFloat, inputFlagStripe,
    9226             :             inputWeightStripe, outputDataStripeFloat, outputFlagStripe);
    9227           0 :     convertArray(outputDataStripe, outputDataStripeFloat);
    9228           0 : }
    9229             : 
    9230             : // -----------------------------------------------------------------------
    9231             : //
    9232             : // -----------------------------------------------------------------------
    9233           0 : Convolver<Float> *MSTransformManager::getConvolver(Int const numChan) {
    9234           0 :     if (convolverPool_.find(numChan) == convolverPool_.end()) {
    9235           0 :         throw AipsError("Failed to get convolver. Smoothing is not properly configured.");
    9236             :     }
    9237           0 :     return &convolverPool_[numChan];
    9238             : }
    9239             : 
    9240             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16