LCOV - code coverage report
Current view: top level - mstransform/MSTransform - MSTransformManager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 4162 0.0 %
Date: 2024-10-10 15:00:01 Functions: 0 206 0.0 %

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

Generated by: LCOV version 1.16