LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - Calibrater.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 685 2950 23.2 %
Date: 2025-08-21 08:01:32 Functions: 39 100 39.0 %

          Line data    Source code
       1             : //# Calibrater.cc: Implementation of Calibrater.h
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This program is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU General Public License as published by the Free
       7             : //# Software Foundation; either version 2 of the License, or (at your option)
       8             : //# any later version.
       9             : //#
      10             : //# This program is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             : //# more details.
      14             : //#
      15             : //# You should have received a copy of the GNU General Public License along
      16             : //# with this program; if not, write to the Free Software Foundation, Inc.,
      17             : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id: Calibrater.cc,v 19.37 2006/03/16 01:28:09 gmoellen Exp $
      27             : 
      28             : #include <casacore/tables/Tables/Table.h>
      29             : #include <casacore/tables/Tables/TableRecord.h>
      30             : #include <casacore/tables/Tables/TableDesc.h>
      31             : #include <casacore/tables/Tables/TableLock.h>
      32             : #include <casacore/tables/Tables/TableUtil.h>
      33             : #include <casacore/tables/TaQL/TableParse.h>
      34             : #include <casacore/tables/Tables/ArrColDesc.h>
      35             : #include <casacore/tables/DataMan/TiledShapeStMan.h>
      36             : 
      37             : #include <casacore/casa/System/AipsrcValue.h>
      38             : #include <casacore/casa/Arrays/ArrayUtil.h>
      39             : #include <casacore/casa/Arrays/ArrayLogical.h>
      40             : #include <casacore/casa/Arrays/ArrayPartMath.h>
      41             : //#include <casa/Arrays/ArrayMath.h>
      42             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      43             : #include <casacore/ms/MSSel/MSFieldIndex.h>
      44             : #include <casacore/ms/MSSel/MSSelection.h>
      45             : #include <casacore/ms/MSSel/MSSelectionTools.h>
      46             : #include <casacore/ms/MSOper/MSMetaData.h>
      47             : #include <casacore/casa/BasicSL/Constants.h>
      48             : #include <casacore/casa/Exceptions/Error.h>
      49             : #include <iostream>
      50             : #include <sstream>
      51             : #include <casacore/casa/OS/File.h>
      52             : #include <synthesis/MeasurementComponents/Calibrater.h>
      53             : #include <synthesis/CalTables/CLPatchPanel.h>
      54             : #include <synthesis/MeasurementComponents/CalSolVi2Organizer.h>
      55             : #include <synthesis/MeasurementComponents/MSMetaInfoForCal.h>
      56             : #include <synthesis/MeasurementComponents/VisCalSolver.h>
      57             : #include <synthesis/MeasurementComponents/VisCalSolver2.h>
      58             : #include <synthesis/MeasurementComponents/UVMod.h>
      59             : #include <synthesis/MeasurementComponents/TsysGainCal.h>
      60             : #include <msvis/MSVis/VisSetUtil.h>
      61             : #include <msvis/MSVis/VisBuffAccumulator.h>
      62             : #include <msvis/MSVis/VisibilityIterator2.h>
      63             : #include <msvis/MSVis/VisBuffer2.h>
      64             : #include <msvis/MSVis/ViFrequencySelection.h>
      65             : #include <casacore/casa/Quanta/MVTime.h>
      66             : #include <casacore/casa/Logging/LogMessage.h>
      67             : #include <casacore/casa/Logging/LogIO.h>
      68             : #include <casacore/casa/Utilities/Assert.h>
      69             : 
      70             : #include <casacore/tables/Tables/SetupNewTab.h>
      71             : #include <vector>
      72             : using std::vector;
      73             : #include <stdcasa/UtilJ.h>
      74             : 
      75             : #ifdef _OPENMP
      76             :  #include <omp.h>
      77             : #endif
      78             : 
      79             : //#define REPORT_CAL_TIMING
      80             : 
      81             : using namespace casacore;
      82             : using namespace casa::utilj;
      83             : 
      84             : using namespace casacore;
      85             : using namespace casa::vpf;
      86             : 
      87             : using namespace casacore;
      88             : namespace casa { //# NAMESPACE CASA - BEGIN
      89             : 
      90          31 : CalCounts::CalCounts():
      91          31 :   antennaMap_(),
      92          31 :   spwMap_(),
      93          62 :   totalMap_()
      94          31 : {}
      95             : 
      96          31 : void CalCounts::initCounts(Int NSpw, Int NAnt, Int NPol) {
      97          31 :     Vector<Int> polShape(NPol, 0);
      98          31 :     Vector<Int> singleVector(1, 0);
      99             :     
     100          31 :     totalMap_["expected"] = polShape;
     101          31 :     totalMap_["data_unflagged"] = polShape;
     102          31 :     totalMap_["above_minblperant"] = polShape;
     103          31 :     totalMap_["above_minsnr"] = polShape;
     104             :     
     105         155 :     for (Int spw=0; spw<NSpw; spw++) {
     106             :       // Init spw map keys
     107         124 :       spwMap_[spw]["expected"] = polShape;
     108         124 :       spwMap_[spw]["data_unflagged"] = polShape;
     109         124 :       spwMap_[spw]["above_minblperant"] = polShape;
     110         124 :       spwMap_[spw]["above_minsnr"] = polShape;
     111        1388 :       for (Int ant=0; ant<NAnt; ant++) {
     112             :           // Init antenna map keys
     113        1264 :           antennaMap_[spw][ant]["expected"] = polShape;
     114        1264 :           antennaMap_[spw][ant]["data_unflagged"] = polShape;
     115        1264 :           antennaMap_[spw][ant]["above_minblperant"] = polShape;
     116        1264 :           antennaMap_[spw][ant]["above_minsnr"] = polShape;
     117        1264 :           antennaMap_[spw][ant]["used_as_refant"] = singleVector;
     118             :       }
     119             :     }
     120          31 : }
     121             : 
     122         225 : void CalCounts::addAntennaCounts(Int spw, Int NAnt, Int NPol, std::map<Int, std::map<String, Vector<Int>>> resultMap) {
     123             :     // Add the results to the antenna Map
     124         225 :     Vector<Int> spwExp(NPol, 0), spwUnflag(NPol, 0), spwMinsnr(NPol, 0);
     125             :     
     126        2457 :     for (Int ant=0; ant<NAnt; ant++) {
     127        2232 :         if (resultMap.find(ant) == resultMap.end()) {continue;};
     128             :         // add if used as refant
     129        2232 :         antennaMap_[spw][ant]["used_as_refant"][0] += resultMap[ant]["used_as_refant"][0];
     130       20088 :         for (Int pol=0; pol<NPol; pol++) {
     131       17856 :             antennaMap_[spw][ant]["expected"][pol] += resultMap[ant]["expected"][pol];
     132       17856 :             antennaMap_[spw][ant]["data_unflagged"][pol] += resultMap[ant]["data_unflagged"][pol];
     133       17856 :             antennaMap_[spw][ant]["above_minblperant"][pol] += resultMap[ant]["above_minblperant"][pol];
     134       17856 :             antennaMap_[spw][ant]["above_minsnr"][pol] += resultMap[ant]["above_minsnr"][pol];
     135             :             // if any antenna value is good add to spw total
     136       17856 :             if (resultMap[ant]["expected"][pol] == 1) {spwExp[pol] = 1;};
     137       17856 :             if (resultMap[ant]["data_unflagged"][pol] == 1) {spwUnflag[pol] = 1;};
     138       17856 :             if (resultMap[ant]["above_minblperant"][pol] == 1) {spwMinsnr[pol] = 1;};
     139       17856 :             if (resultMap[ant]["above_minsnr"][pol] == 1) {spwMinsnr[pol] = 1;};
     140             :         }
     141             :     }
     142             :     // Add the totals to the spw Map
     143        2025 :     for (Int pol=0; pol<NPol; pol++) {
     144        1800 :         spwMap_[spw]["expected"][pol] += spwExp[pol];
     145        1800 :         spwMap_[spw]["data_unflagged"][pol] += spwUnflag[pol];
     146        1800 :         spwMap_[spw]["above_minblperant"][pol] += spwMinsnr[pol];
     147        1800 :         spwMap_[spw]["above_minsnr"][pol] += spwMinsnr[pol];
     148             :         // Acumulate total overall values
     149        1800 :         totalMap_["expected"][pol] += spwExp[pol];
     150        1800 :         totalMap_["data_unflagged"][pol] += spwUnflag[pol];
     151        1800 :         totalMap_["above_minblperant"][pol] += spwMinsnr[pol];
     152        1800 :         totalMap_["above_minsnr"][pol] += spwMinsnr[pol];
     153             :     }
     154             :     
     155         225 : }
     156             : 
     157          31 : void CalCounts::updateRefants(Int NSpw, Int NAnt, std::map<Int, std::map<Int, Int>> refantMap) {
     158         155 :     for (Int spw=0; spw<NSpw; spw++) {
     159        1388 :         for (Int ant=0; ant<NAnt; ant++) {
     160        1264 :             antennaMap_[spw][ant]["used_as_refant"][0] += refantMap[spw][ant];
     161             :         }
     162             :     }
     163          31 : }
     164             : 
     165        1264 : Vector<Int> CalCounts::antMapVal(Int spw, Int ant, String gate) {
     166        1264 :     return antennaMap_[spw][ant][gate];
     167             : }
     168             : 
     169         496 : Vector<Int> CalCounts::spwMapVal(Int spw, String gate) {
     170         496 :     return spwMap_[spw][gate];
     171             : }
     172             : 
     173         124 : Vector<Int> CalCounts::totalMapVal(String gate) {
     174         124 :     return totalMap_[gate];
     175             : }
     176             : 
     177          31 : Record CalCounts::makeRecord(Int NAnt, Int NPol) {
     178             :     
     179          31 :     Vector<Int> totExp(NPol, 0), totUnflag(NPol, 0), totMinsnr(NPol, 0);
     180             :     
     181          31 :     nSpw = spwMap_.size();
     182          31 :     Record containerRec = Record();
     183          31 :     Record resultRec = Record();
     184             :     
     185          31 :     resultRec.define("expected", totalMap_["expected"]);
     186          31 :     resultRec.define("data_unflagged", totalMap_["data_unflagged"]);
     187          31 :     resultRec.define("above_minblperant", totalMap_["above_minblperant"]);
     188          31 :     resultRec.define("above_minsnr", totalMap_["above_minsnr"]);
     189             :     
     190         155 :     for (Int spw=0; spw<nSpw; spw++) {
     191         124 :         Record spwRec = Record();
     192         124 :         spwRec.define("expected", spwMap_[spw]["expected"]);
     193         124 :         spwRec.define("data_unflagged", spwMap_[spw]["data_unflagged"]);
     194         124 :         spwRec.define("above_minblperant", spwMap_[spw]["above_minblperant"]);
     195         124 :         spwRec.define("above_minsnr", spwMap_[spw]["above_minsnr"]);
     196        1388 :         for (Int ant=0; ant<NAnt; ant++) {
     197        1264 :             Record subRec = Record();
     198        1264 :             subRec.define("expected", antennaMap_[spw][ant]["expected"]);
     199        1264 :             subRec.define("data_unflagged", antennaMap_[spw][ant]["data_unflagged"]);
     200        1264 :             subRec.define("above_minblperant", antennaMap_[spw][ant]["above_minblperant"]);
     201        1264 :             subRec.define("above_minsnr", antennaMap_[spw][ant]["above_minsnr"]);
     202        1264 :             subRec.define("used_as_refant", antennaMap_[spw][ant]["used_as_refant"]);
     203        1264 :             spwRec.defineRecord(RecordFieldId("ant"+to_string(ant)), subRec);
     204        1264 :         }
     205         124 :         resultRec.defineRecord(RecordFieldId("spw"+to_string(spw)), spwRec);
     206         124 :     }
     207          31 :     containerRec.defineRecord(RecordFieldId("solvestats"), resultRec);
     208             :     
     209          62 :     return containerRec;
     210          31 : }
     211             : 
     212           0 : CalCounts::~CalCounts() {}
     213             : 
     214         242 : Calibrater::Calibrater(): 
     215         242 :   ms_p(0), 
     216         242 :   mssel_p(0), 
     217         242 :   mss_p(0),
     218         242 :   frequencySelections_p(nullptr),
     219         242 :   msmc_p(0),
     220         242 :   ve_p(0),
     221         242 :   vc_p(),
     222         242 :   svc_p(0),
     223         242 :   histLockCounter_p(), 
     224         242 :   hist_p(0),
     225         242 :   usingCalLibrary_(false),
     226         242 :   corrDepFlags_(false), // default (==traditional behavior)
     227         242 :   actRec_(),
     228         242 :   resRec_(),
     229         242 :   simdata_p(false),
     230         726 :   ssvp_p()
     231             : {
     232             :   //  cout << "This is the NEW VI2-aware Calibrater" << endl;
     233         242 : }
     234             : 
     235           0 : Calibrater::Calibrater(String msname): 
     236           0 :   msname_p(msname),
     237           0 :   ms_p(0), 
     238           0 :   mssel_p(0), 
     239           0 :   mss_p(0),
     240           0 :   frequencySelections_p(nullptr),
     241           0 :   msmc_p(0),
     242           0 :   ve_p(0),
     243           0 :   vc_p(),
     244           0 :   svc_p(0),
     245           0 :   histLockCounter_p(), 
     246           0 :   hist_p(0),
     247           0 :   usingCalLibrary_(false),
     248           0 :   corrDepFlags_(false), // default (==traditional behavior)
     249           0 :   actRec_(),
     250           0 :   resRec_(),
     251           0 :   simdata_p(false),
     252           0 :   ssvp_p()
     253             : {
     254             : 
     255             : 
     256           0 :   if (!Table::isReadable(msname))
     257           0 :     throw(AipsError("MS "+msname+" does not exist."));
     258             : 
     259             : 
     260           0 :   logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL
     261           0 :             << "Arranging to calibrate MS: "+msname
     262           0 :             << LogIO::POST;
     263             :   
     264             :   // This is a bare Calibrater, intended to serve a VisEquation 
     265             : 
     266             :   // We need very little of the usual stuff
     267             : 
     268             :   // A VisEquation
     269           0 :   ve_p = new VisEquation();
     270             : 
     271             :   // Reset the apply/solve VisCals
     272           0 :   reset();
     273             : 
     274           0 : }
     275             : 
     276           0 : Calibrater::Calibrater(const vi::SimpleSimVi2Parameters& ssvp): 
     277           0 :   msname_p("<noms>"),
     278           0 :   ms_p(0), 
     279           0 :   mssel_p(0), 
     280           0 :   mss_p(0),
     281           0 :   frequencySelections_p(nullptr),
     282           0 :   msmc_p(0),
     283           0 :   ve_p(0),
     284           0 :   vc_p(),
     285           0 :   svc_p(0),
     286           0 :   histLockCounter_p(), 
     287           0 :   hist_p(0),
     288           0 :   usingCalLibrary_(false),
     289           0 :   corrDepFlags_(false), // default (==traditional behavior)
     290           0 :   actRec_(),
     291           0 :   resRec_(),
     292           0 :   simdata_p(true),
     293           0 :   ssvp_p(ssvp)
     294             : {
     295             : 
     296           0 :   logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL
     297             :             << "Arranging SIMULATED MS data for testing!!!!"
     298           0 :             << LogIO::POST;
     299             :   
     300             :   // A VisEquation
     301           0 :   ve_p = new VisEquation();
     302             : 
     303             :   // Initialize the meta-info server that will be shared with VisCals
     304           0 :   if (msmc_p) delete msmc_p;
     305           0 :   msmc_p = new MSMetaInfoForCal(ssvp_p);
     306             : 
     307             :   // Reset the apply/solve VisCals
     308           0 :   reset();
     309             : 
     310           0 : }
     311             : 
     312             : /*
     313             : Calibrater::Calibrater(const Calibrater & other)
     314             : {
     315             :   operator=(other);
     316             : }
     317             : 
     318             : Calibrater& Calibrater::operator=(const Calibrater & other)
     319             : {
     320             :   ms_p=other.ms_p;
     321             :   mssel_p=other.mssel_p;
     322             :   ve_p=other.ve_p;
     323             :   histLockCounter_p=other.histLockCounter_p;
     324             :   hist_p=other.hist_p;
     325             :   historytab_p=other.historytab_p;
     326             :   
     327             :   return *this;
     328             : }
     329             : */
     330             : 
     331         726 : Calibrater::~Calibrater()
     332             : {
     333         242 :   cleanup();
     334         242 :   if (msmc_p) delete msmc_p; msmc_p=0;
     335         242 :   if (ms_p)   delete ms_p;   ms_p=0;
     336         242 :   if (hist_p) delete hist_p; hist_p=0;
     337             : 
     338         484 : }
     339             : 
     340         242 : Calibrater* Calibrater::factory(Bool old) {
     341             :   
     342         242 :   Calibrater* cal(NULL);
     343             : 
     344         242 :   if (old)
     345           0 :     cal = new OldCalibrater();
     346             :   else 
     347             :     //throw(AipsError("VI2-aware Calibrater not yet available..."));
     348         242 :     cal = new Calibrater();
     349             : 
     350         242 :   return cal;
     351             : 
     352             : }
     353             : 
     354           0 : Calibrater* Calibrater::factory(String msname, Bool old) {
     355             :   
     356           0 :   Calibrater* cal(NULL);
     357             : 
     358           0 :   if (old)
     359           0 :     cal = new OldCalibrater(msname);
     360             :   else
     361           0 :     throw(AipsError("VI2-aware Calibrater not yet available..."));
     362             :   //cal = new Calibrater(msname);
     363             : 
     364           0 :   return cal;
     365             : 
     366             : }
     367             : 
     368             : 
     369        3919 : LogIO& Calibrater::logSink() {return sink_p;};
     370             : 
     371           0 : String Calibrater::timerString() {
     372           0 :   ostringstream o;
     373           0 :   o <<" [user:   " << timer_p.user () << 
     374           0 :     "  system: " << timer_p.system () <<
     375           0 :     "  real:   " << timer_p.real () << "]"; 
     376           0 :   timer_p.mark();
     377           0 :   return o;
     378           0 : };
     379             : 
     380          64 : Bool Calibrater::initialize(MeasurementSet& inputMS, 
     381             :                             Bool compress,
     382             :                             Bool addScratch, Bool addModel)  {
     383             :   
     384          64 :   logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL3;
     385             :   
     386             :   try {
     387          64 :     timer_p.mark();
     388             : 
     389             :     // Set pointer ms_p from input MeasurementSet
     390          64 :     if (ms_p) {
     391           0 :       *ms_p=inputMS;
     392             :     } else {
     393          64 :       ms_p = new MeasurementSet(inputMS);
     394          64 :       AlwaysAssert(ms_p,AipsError);
     395             :     };
     396             : 
     397             :     // Remember the ms's name
     398          64 :     msname_p=ms_p->tableName();
     399             : 
     400             :     // Initialize the meta-info server that will be shared with VisCals
     401          64 :     if (msmc_p) delete msmc_p;
     402          64 :     msmc_p = new MSMetaInfoForCal(*ms_p);
     403             : 
     404             :     // Add/init scr cols, if requested (init is hard-wired)
     405          64 :     if (addScratch || addModel) {
     406           0 :       Bool alsoinit=true;
     407           0 :       VisSetUtil::addScrCols(*ms_p,addModel,addScratch,alsoinit,compress);
     408             :     }
     409             : 
     410             :     // Set the selected MeasurementSet to be the same initially
     411             :     // as the input MeasurementSet
     412             :     logSink() << LogIO::NORMAL
     413             :               << "Initializing nominal selection to the whole MS."
     414          64 :               << LogIO::POST;
     415             : 
     416          64 :     if (mssel_p) delete mssel_p;
     417          64 :     mssel_p=new MeasurementSet(*ms_p);
     418             :     
     419             :     // Create the associated VisEquation
     420             :     //  TBD: move to ctor and make it non-pointer
     421          64 :     if (ve_p) {
     422           0 :       delete ve_p;
     423           0 :       ve_p=0;
     424             :     };
     425          64 :     ve_p=new VisEquation();
     426             : 
     427             :     // Reset the apply/solve VisCals
     428          64 :     reset(true,true);
     429             : 
     430          64 :     return true;
     431             : 
     432           0 :   } catch (AipsError x) {
     433           0 :     logSink() << LogOrigin("Calibrater","initialize",WHERE) 
     434             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
     435           0 :               << LogIO::POST;
     436           0 :     cleanup();
     437           0 :     if (msmc_p) delete msmc_p; msmc_p=NULL;
     438           0 :     if (ms_p)   delete ms_p;   ms_p=NULL;
     439           0 :     if (hist_p) delete hist_p; hist_p=NULL;
     440             : 
     441           0 :     throw(AipsError("Error in Calibrater::initialize()"));
     442             :     return false;
     443           0 :   } 
     444             :   return false;
     445             : }
     446             : 
     447             : 
     448             : // Select data (using MSSelection syntax)
     449          32 : void Calibrater::selectvis(const String& time,
     450             :                            const String& spw,
     451             :                            const String& scan,
     452             :                            const String& field,
     453             :                            const String& intent,
     454             :                            const String& obsIDs,
     455             :                            const String& baseline,
     456             :                            const String& uvrange,
     457             :                            const String& chanmode,
     458             :                            const Int&,
     459             :                            const Int&,
     460             :                            const Int&,
     461             :                            const MRadialVelocity&,
     462             :                            const MRadialVelocity&,
     463             :                            const String& msSelect)
     464             : {
     465             : // Define primary measurement set selection criteria
     466             : // Inputs:
     467             : //    time
     468             : //    spw
     469             : //    scan
     470             : //    field
     471             : //    intent
     472             : //    obsIDs
     473             : //    baseline
     474             : //    uvrange
     475             : //    chanmode     const String&            Frequency/velocity selection mode
     476             : //                                          ("channel", "velocity" or 
     477             : //                                           "opticalvelocity")
     478             : //    nchan        const Int&               No of channels to select
     479             : //    start        const Int&               Start channel to select
     480             : //    step         const Int&               Channel increment
     481             : //    mStart       const MRadialVelocity&   Start radial vel. to select
     482             : //    mStep        const MRadialVelocity&   Radial velocity increment
     483             : //    msSelect     const String&            MS selection string (TAQL)
     484             : // Output to private data:
     485             : //
     486          32 :   logSink() << LogOrigin("Calibrater","selectvis") << LogIO::NORMAL3;
     487             :   
     488             :   try {
     489             : 
     490             :  /*   
     491             :     cout << "time     = " << time << " " << time.length() <<endl;
     492             :     cout << "spw      = " << spw << " " << spw.length() <<endl;
     493             :     cout << "scan     = " << scan << " " << scan.length() <<endl;
     494             :     cout << "field    = " << field << " " << field.length() <<endl;
     495             :     cout << "baseline = " << baseline << " " << baseline.length() << endl;
     496             :     cout << "uvrange  = " << uvrange << " " << uvrange.length() << endl;
     497             :  */
     498             : 
     499          32 :     logSink() << "Selecting data" << LogIO::POST;
     500             :     
     501             :     // Apply selection to the original MeasurementSet
     502          32 :     logSink() << "Performing selection on MeasurementSet" << endl;
     503             :     
     504          32 :     if (mssel_p) {
     505          32 :       delete mssel_p;
     506          32 :       mssel_p=0;
     507             :     };
     508             : 
     509             :     // Report non-trivial user selections
     510          32 :     if (time!="")
     511           2 :       logSink() << " Selecting on time: '" << time << "'" << endl;
     512          32 :     if (spw!="")
     513          13 :       logSink() << " Selecting on spw: '" << spw << "'" << endl;
     514          32 :     if (scan!="")
     515           2 :       logSink() << " Selecting on scan: '" << scan << "'" << endl;
     516          32 :     if (field!="")
     517           5 :       logSink() << " Selecting on field: '" << field << "'" << endl;
     518          32 :     if (intent!="")
     519           0 :       logSink() << " Selecting on intent: '" << intent << "'" << endl;
     520          32 :     if(obsIDs != "")
     521           0 :       logSink() << " Selecting by observation IDs: '" << obsIDs << "'" << endl;
     522          32 :     if (baseline!="")
     523           0 :       logSink() << " Selecting on antenna/baseline: '" << baseline << "'" << endl;
     524          32 :     if (uvrange!="")
     525           1 :       logSink() << " Selecting on uvrange: '" << uvrange << "'" << endl;
     526          32 :     if (msSelect!="")
     527           0 :       logSink() << " Selecting with TaQL: '" << msSelect << "'" << endl;
     528          32 :     logSink() << LogIO::POST;
     529             : 
     530             : 
     531             :     // Assume no selection, for starters
     532          32 :     mssel_p = new MeasurementSet(*ms_p);
     533             : 
     534             :     // Apply user-supplied selection
     535          32 :     Bool nontrivsel=false;
     536             : 
     537             :     // Ensure use of a fresh MSSelection object
     538          32 :     if (mss_p) { delete mss_p; mss_p=NULL; }
     539          32 :     mss_p=new MSSelection();
     540          64 :     nontrivsel= mssSetData(*ms_p,
     541          32 :                            *mssel_p,"",
     542             :                            time,baseline,
     543             :                            field,spw,
     544             :                            uvrange,msSelect,
     545             :                            "",scan,"",intent, obsIDs,mss_p);
     546             : 
     547             :     // Keep any MR status for the MS
     548          32 :     mssel_p->setMemoryResidentSubtables(ms_p->getMrsEligibility());
     549             : 
     550             :     // If non-trivial MSSelection invoked and nrow reduced:
     551          32 :     if(nontrivsel && mssel_p->nrow()<ms_p->nrow()) {
     552             : 
     553             :       // Escape if no rows selected
     554          14 :       if (mssel_p->nrow()==0) 
     555           0 :         throw(AipsError("Specified selection selects zero rows!"));
     556             : 
     557             :       // ...otherwise report how many rows are selected
     558          14 :       logSink() << "By selection " << ms_p->nrow() 
     559          14 :                 << " rows are reduced to " << mssel_p->nrow() 
     560          14 :                 << LogIO::POST;
     561             : 
     562             :       // Revise the msmc_p so it contains only the _selected_ MS
     563          14 :       if (msmc_p) delete msmc_p;
     564          14 :       msmc_p = new MSMetaInfoForCal(*mssel_p, ms_p->tableName());
     565             : 
     566             :     }
     567             :     else {
     568             :       // Selection did nothing:
     569          18 :       logSink() << "Selection did not drop any rows" << LogIO::POST;
     570             :     }
     571             : 
     572             :     // Attempt to use MSSelection for channel selection
     573             :     //  if user not using the old way
     574          32 :     if (chanmode=="none") {
     575          32 :       selectChannel(spw);
     576             :     }
     577             :     else {
     578             :       // Old-fashioned way now deprecated
     579             :       logSink() << LogIO::WARN 
     580             :                 << "You have used the old-fashioned mode parameter" << endl
     581             :                 << "for channel selection." << endl
     582             :                 << "Please begin using the new channel selection" << endl
     583           0 :                 << "syntax in the spw parameter." << LogIO::POST;
     584           0 :       throw(AipsError("Old-fashioned chanmode selection is no longer supported!"));
     585             :     }
     586             : 
     587             :   }
     588           0 :   catch (MSSelectionError& x) {
     589             :     // Re-initialize with the existing MS
     590           0 :     logSink() << LogOrigin("Calibrater","selectvis",WHERE) 
     591             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     592           0 :               << LogIO::POST;
     593             :     // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty
     594           0 :     initialize(*ms_p,false,false,false);
     595           0 :     throw(AipsError("Error in data selection specification: " + x.getMesg()));
     596           0 :   } 
     597           0 :   catch (AipsError x) {
     598             :     // Re-initialize with the existing MS
     599           0 :     logSink() << LogOrigin("Calibrater","selectvis",WHERE) 
     600             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     601           0 :               << LogIO::POST;
     602             :     // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty.
     603           0 :     initialize(*ms_p,false,false,false);
     604           0 :     throw(AipsError("Error in Calibrater::selectvis(): " + x.getMesg()));
     605           0 :   } 
     606          32 : };
     607             : 
     608             : 
     609           7 : Bool Calibrater::setapply(const String& type, 
     610             :                           const Double& t,
     611             :                           const String& table,
     612             :                           const String& spw,
     613             :                           const String& field,
     614             :                           const String& interp,
     615             :                           const Bool& calwt,
     616             :                           const Vector<Int>& spwmap,
     617             :                           const Vector<Double>& opacity) 
     618             : {
     619             : 
     620          14 :   logSink() << LogOrigin("Calibrater",
     621             :                          "setapply(type, t, table, spw, field, interp, calwt, spwmap, opacity)")
     622          14 :             << LogIO::NORMAL;
     623             : 
     624             : 
     625             :   //  cout << "Calibrater::setapply: field="<< field << endl;
     626             :    
     627             :   // Set record format for calibration table application information
     628           7 :   RecordDesc applyparDesc;
     629           7 :   applyparDesc.addField ("t", TpDouble);
     630           7 :   applyparDesc.addField ("table", TpString);
     631           7 :   applyparDesc.addField ("interp", TpString);
     632           7 :   applyparDesc.addField ("spw", TpArrayInt);
     633             :   //  applyparDesc.addField ("field", TpArrayInt);
     634           7 :   applyparDesc.addField ("fieldstr", TpString);
     635           7 :   applyparDesc.addField ("calwt",TpBool);
     636           7 :   applyparDesc.addField ("spwmap",TpArrayInt);
     637           7 :   applyparDesc.addField ("opacity",TpArrayDouble);
     638             :   
     639             :   // Create record with the requisite field values
     640           7 :   Record applypar(applyparDesc);
     641           7 :   applypar.define ("t", t);
     642           7 :   applypar.define ("table", table);
     643             : 
     644             :   /*
     645             :   String cinterp=interp;
     646             :   //  cinterp.erase(remove_if(cinterp.begin(), cinterp.end(), isspace), cinterp.end());
     647             :   cinterp.erase( remove( cinterp.begin(), cinterp.end(), ' ' ), cinterp.end() );
     648             :   */
     649             :  
     650           7 :   applypar.define ("interp", interp);
     651           7 :   applypar.define ("spw",getSpwIdx(spw));
     652             :   //  applypar.define ("field",getFieldIdx(field));
     653           7 :   applypar.define ("fieldstr",field);
     654           7 :   applypar.define ("calwt",calwt);
     655           7 :   applypar.define ("spwmap",spwmap);
     656           7 :   applypar.define ("opacity", opacity);
     657             :   
     658           7 :   String upType=type;
     659           7 :   upType.upcase();
     660           7 :   if (upType=="")
     661             :     // Get type from table
     662           5 :     upType = calTableType(table);
     663             : 
     664          14 :   return setapply(upType,applypar);
     665             : 
     666           7 : }
     667             : 
     668           7 : Bool Calibrater::setapply (const String& type, 
     669             :                            const Record& applypar)
     670             : {
     671           7 :   logSink() << LogOrigin("Calibrater", "setapply(type, applypar)");
     672             : 
     673             :   // First try to create the requested VisCal object
     674           7 :   VisCal *vc(NULL);
     675             : 
     676             :   try {
     677             : 
     678           7 :     if(!ok()) 
     679           0 :       throw(AipsError("Calibrater not prepared for setapply."));
     680             : 
     681           7 :     String upType=type;
     682           7 :     upType.upcase();
     683             : 
     684             :     logSink() << LogIO::NORMAL 
     685             :               << "Arranging to APPLY:"
     686           7 :               << LogIO::POST;
     687             : 
     688             :     // Add a new VisCal to the apply list
     689           7 :     vc = createVisCal(upType,*msmc_p);  
     690             : 
     691           7 :     vc->setApply(applypar);       
     692             : 
     693             :     logSink() << LogIO::NORMAL << ".   "
     694           7 :               << vc->applyinfo()
     695           7 :               << LogIO::POST;
     696             : 
     697           7 :   } catch (AipsError x) {
     698             :     logSink() << LogIO::SEVERE << x.getMesg() 
     699             :               << " Check inputs and try again."
     700           0 :               << LogIO::POST;
     701           0 :     if (vc) delete vc;
     702           0 :     throw(AipsError("Error in Calibrater::setapply."));
     703             :     return false;
     704           0 :   }
     705             : 
     706             :   // Creation apparently successful, so add to the apply list
     707             :   // TBD: consolidate with above?
     708             :   try {
     709             : 
     710           7 :     uInt napp=vc_p.nelements();
     711           7 :     vc_p.resize(napp+1,false,true);      
     712           7 :     vc_p[napp] = vc;
     713           7 :     vc=NULL;
     714             :    
     715             :     // Maintain sort of apply list
     716           7 :     ve_p->setapply(vc_p);
     717             :     
     718           7 :     return true;
     719             : 
     720           0 :   } catch (AipsError x) {
     721             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
     722           0 :               << LogIO::POST;
     723           0 :     if (vc) delete vc;
     724           0 :     throw(AipsError("Error in Calibrater::setapply."));
     725             :     return false;
     726           0 :   } 
     727             :   return false;
     728             : }
     729             : 
     730             : 
     731             : // Validate a Cal Library record
     732           0 : Bool Calibrater::validatecallib(Record callib) {
     733             : 
     734           0 :   uInt ntab=callib.nfields();
     735           0 :   for (uInt itab=0;itab<ntab;++itab) {
     736             : 
     737           0 :     String tabname=callib.name(itab);
     738           0 :     Record thistabrec=callib.asRecord(itab);
     739           0 :     uInt ncl=thistabrec.nfields();
     740             : 
     741           0 :     for (uInt icl=0;icl<ncl;++icl) {
     742             : 
     743           0 :       if (thistabrec.dataType(icl)!=TpRecord)
     744           0 :         continue;
     745             : 
     746           0 :       Record thisicl=thistabrec.asRecord(icl);
     747             :       try {
     748           0 :         CalLibSlice::validateCLS(thisicl);
     749             :       }
     750           0 :       catch ( AipsError x) {
     751             :         logSink() << LogIO::SEVERE
     752             :                   << "Caltable " << tabname 
     753             :                   << " is missing the following fields: " 
     754             :                   << x.getMesg() 
     755           0 :                   << LogIO::POST;
     756           0 :       }
     757             : 
     758           0 :     }
     759           0 :   }
     760           0 :   return true;
     761             : }
     762             : 
     763             : 
     764             : // Set up apply-able calibration via a Cal Library
     765           2 : Bool Calibrater::setcallib2(Record callib, const MeasurementSet* ms) {
     766             : 
     767           2 :   logSink() << LogOrigin("Calibrater", "setcallib2(callib)");
     768             : 
     769             :   //  cout << "Calibrater::setcallib2(callib) : " << boolalpha << callib << endl;
     770             : 
     771           2 :   uInt ntab=callib.nfields();
     772             : 
     773             :   //  cout << "callib.nfields() = " << ntab << endl;
     774             : 
     775             :   // Do some preliminary per-table verification
     776           4 :   for (uInt itab=0;itab<ntab;++itab) {
     777             : 
     778           2 :     String tabname=callib.name(itab);
     779             : 
     780             :     // Trap parang
     781             :     // TBD...
     782             :     //    if (tabname=="<parang>")
     783             :     //      continue;
     784             : 
     785             :     // Insist that the table exists on disk
     786           2 :     if (!Table::isReadable(tabname))
     787           0 :       throw(AipsError("Caltable "+tabname+" does not exist."));
     788             : 
     789           2 :   }
     790             : 
     791             :   // Tables exist, so deploy them...
     792             : 
     793             :   // Local MS object for callib parsing (only)
     794             :   //  MeasurementSet lms(msname_p,Table::Update);
     795             :   // TBD: Use selected MS instead (not yet available in OTF plotms context!)
     796             :   //const MeasurementSet lms(*mssel_p);
     797             :   //MeasurementSet lms(msname_p);
     798             : 
     799             :   // Local const MS object for callib parsing (only)
     800           2 :   const MeasurementSet *lmsp(0);
     801           2 :   if (ms) {
     802             :     // Use supplied MS (from outside), if specified...
     803             :     // TBD: should we verify same base MS as ms_p/mssel_p?
     804             :     //cout << "Using externally-specified MS!!" << endl;
     805           0 :     lmsp=ms;
     806             :   }
     807             :   else {
     808             :     // ...use internal one instead
     809             :     //cout << "Using internal MS (mssel_p)!!" << endl;
     810           2 :     lmsp=mssel_p;
     811             :   }
     812             :   // Reference for use below
     813           2 :   const MeasurementSet &lms(*lmsp);
     814             : 
     815             : 
     816           4 :   for (uInt itab=0;itab<ntab;++itab) {
     817             : 
     818           2 :     String tabname=callib.name(itab);
     819             : 
     820             :     // Get the type from the table
     821           2 :     String upType=calTableType(tabname);
     822           2 :     upType.upcase();
     823             : 
     824             :     // Add table name to the record
     825           2 :     Record thistabrec=callib.asrwRecord(itab);
     826           2 :     thistabrec.define("tablename",tabname);
     827             : 
     828             :     // First try to create the requested VisCal object
     829           2 :     VisCal *vc(NULL);
     830             : 
     831             :     try {
     832             : 
     833             :       //      if(!ok()) 
     834             :       //        throw(AipsError("Calibrater not prepared for setapply."));
     835             :       
     836             :       logSink() << LogIO::NORMAL 
     837             :                 << "Arranging to APPLY:"
     838           2 :                 << LogIO::POST;
     839             :       
     840             :       // Add a new VisCal to the apply list
     841           2 :       vc = createVisCal(upType,*msmc_p);
     842             : 
     843             :       // ingest this table according to its callib
     844           2 :       vc->setCallib(thistabrec,lms);
     845             :       
     846           0 :     } catch (AipsError x) {
     847             :       logSink() << LogIO::SEVERE << x.getMesg() 
     848             :                 << " Check inputs and try again."
     849           0 :                 << LogIO::POST;
     850           0 :       if (vc) delete vc;
     851           0 :       throw(AipsError("Error in Calibrater::callib2."));
     852             :       return false;
     853           0 :     }
     854             : 
     855             :     // Creation apparently successful, so add to the apply list
     856             :     // TBD: consolidate with above?
     857             :     try {
     858             :       
     859           2 :       uInt napp=vc_p.nelements();
     860           2 :       vc_p.resize(napp+1,false,true);      
     861           2 :       vc_p[napp] = vc;
     862           2 :       vc=NULL;
     863             :    
     864             :       // Maintain sort of apply list
     865           2 :       ve_p->setapply(vc_p);
     866             :       
     867           0 :     } catch (AipsError x) {
     868             :       logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
     869           0 :                 << LogIO::POST;
     870           0 :       if (vc) delete vc;
     871           0 :       throw(AipsError("Error in Calibrater::setapply."));
     872             :       return false;
     873           0 :     } 
     874           2 :   }
     875             : 
     876             :   // Signal use of CalLibrary
     877           2 :   usingCalLibrary_=true;
     878             : 
     879             :   // All ok, if we get this far!
     880           2 :   return true;
     881             : 
     882             : }
     883             : 
     884           0 : Bool Calibrater::setmodel(const String& modelImage)
     885             : {
     886           0 :   if (!svc_p)
     887           0 :     throw(AipsError("Calibrater::setmodel() called before Calibrater::setsolve()"));
     888           0 :   svc_p->setModel(modelImage);
     889           0 :   return true;
     890             : }
     891             : 
     892           0 : Bool Calibrater::setModel(const Vector<Double>& stokes) {
     893             : 
     894           0 :   if (ve_p) {
     895           0 :     Vector<Float> fstokes(stokes.shape());
     896           0 :     convertArray(fstokes,stokes);
     897           0 :     ve_p->setModel(fstokes);
     898           0 :   }
     899             :   else
     900           0 :     throw(AipsError("Error in Calibrater::setModel: no VisEquation."));
     901             : 
     902           0 :   return true;
     903             : 
     904             : }
     905             : 
     906          32 : Bool Calibrater::setsolve (const String& type, 
     907             :                            const String& solint,
     908             :                            const String& table,
     909             :                            const Bool append,
     910             :                            const Double preavg, 
     911             :                            const String& apmode,
     912             :                            const Int minblperant,
     913             :                            const String& refant,
     914             :                            const String& refantmode,
     915             :                            const Bool solnorm,
     916             :                            const String& normtype,
     917             :                            const Float minsnr,
     918             :                            const String& combine,
     919             :                            const Int fillgaps,
     920             :                            const String& cfcache,
     921             :                            const Double painc,
     922             :                            const Int fitorder,
     923             :                            const Float fraction,
     924             :                            const Int numedge,
     925             :                            const String& radius,
     926             :                            const Bool smooth,
     927             :                            const Bool zerorates,
     928             :                            const Bool globalsolve,
     929             :                            const Int niter,
     930             :                            const String& corrcomb,
     931             :                            const Vector<Double>& delaywindow, 
     932             :                            const Vector<Double>& ratewindow,
     933             :                            const Vector<Bool>& paramactive,
     934             :                            const Bool concatspws,
     935             :                            const String& solmode,
     936             :                            const Vector<Double>& rmsthresh
     937             :     )
     938             : {
     939             :   
     940          32 :   logSink() << LogOrigin("Calibrater","setsolve") << LogIO::NORMAL3;
     941             :   
     942             :   // Create a record description containing the solver parameters
     943          32 :   RecordDesc solveparDesc;
     944          32 :   solveparDesc.addField ("solint", TpString);
     945          32 :   solveparDesc.addField ("preavg", TpDouble);
     946          32 :   solveparDesc.addField ("apmode", TpString);
     947          32 :   solveparDesc.addField ("refant", TpArrayInt);
     948          32 :   solveparDesc.addField ("refantmode", TpString);
     949          32 :   solveparDesc.addField ("minblperant", TpInt);
     950          32 :   solveparDesc.addField ("table", TpString);
     951          32 :   solveparDesc.addField ("append", TpBool);
     952          32 :   solveparDesc.addField ("solnorm", TpBool);
     953          32 :   solveparDesc.addField ("normtype", TpString);
     954          32 :   solveparDesc.addField ("type", TpString);
     955          32 :   solveparDesc.addField ("combine", TpString);
     956          32 :   solveparDesc.addField ("maxgap", TpInt);
     957          32 :   solveparDesc.addField ("cfcache", TpString);
     958          32 :   solveparDesc.addField ("painc", TpDouble);
     959          32 :   solveparDesc.addField ("fitorder", TpInt);
     960          32 :   solveparDesc.addField ("solmode", TpString);
     961          32 :   solveparDesc.addField ("rmsthresh", TpArrayDouble);
     962             : 
     963             :   // fringe-fit specific fields
     964          32 :   solveparDesc.addField ("zerorates", TpBool);
     965          32 :   solveparDesc.addField ("minsnr", TpFloat);
     966          32 :   solveparDesc.addField ("globalsolve", TpBool);
     967          32 :   solveparDesc.addField ("delaywindow", TpArrayDouble);
     968          32 :   solveparDesc.addField ("ratewindow", TpArrayDouble);
     969          32 :   solveparDesc.addField ("niter", TpInt);
     970          32 :   solveparDesc.addField ("corrcomb", TpString);
     971          32 :   solveparDesc.addField ("paramactive", TpArrayBool);
     972          32 :   solveparDesc.addField ("concatspws", TpBool);
     973             : 
     974             :   // single dish specific fields
     975          32 :   solveparDesc.addField ("fraction", TpFloat);
     976          32 :   solveparDesc.addField ("numedge", TpInt);
     977          32 :   solveparDesc.addField ("radius", TpString);
     978          32 :   solveparDesc.addField ("smooth", TpBool);
     979             : 
     980             : 
     981             :   // Create a solver record with the requisite field values
     982          32 :   Record solvepar(solveparDesc);
     983          32 :   solvepar.define ("solint", solint);
     984          32 :   solvepar.define ("preavg", preavg);
     985          32 :   String upmode=apmode;
     986          32 :   upmode.upcase();
     987          32 :   solvepar.define ("apmode", upmode);
     988          32 :   solvepar.define ("refant", getRefantIdxList(refant));
     989          32 :   solvepar.define ("refantmode", refantmode);
     990          32 :   solvepar.define ("minblperant", minblperant);
     991          32 :   solvepar.define ("table", table);
     992          32 :   solvepar.define ("append", append);
     993          32 :   solvepar.define ("solnorm", solnorm);
     994          32 :   solvepar.define ("normtype", normtype);
     995             :   // Fringe-fit specific
     996          32 :   solvepar.define ("minsnr", minsnr);
     997          32 :   solvepar.define ("zerorates", zerorates);
     998          32 :   solvepar.define ("globalsolve", globalsolve);
     999          32 :   solvepar.define ("niter", niter);
    1000          32 :   solvepar.define ("corrcomb", corrcomb);
    1001          32 :   solvepar.define ("delaywindow", delaywindow);
    1002          32 :   solvepar.define ("ratewindow", ratewindow);
    1003          32 :   solvepar.define ("solmode", solmode);
    1004          32 :   solvepar.define ("rmsthresh", rmsthresh);
    1005          32 :   solvepar.define ("paramactive", paramactive);
    1006          32 :   solvepar.define ("concatspws", concatspws);
    1007             :   
    1008          32 :   String uptype=type;
    1009          32 :   uptype.upcase();
    1010          32 :   solvepar.define ("type", uptype);
    1011             :   
    1012          32 :   String upcomb=combine;
    1013          32 :   upcomb.upcase();
    1014          32 :   solvepar.define("combine",upcomb);
    1015          32 :   solvepar.define("maxgap",fillgaps);
    1016          32 :   solvepar.define ("cfcache", cfcache);
    1017          32 :   solvepar.define ("painc", painc);
    1018          32 :   solvepar.define("fitorder", fitorder);
    1019             : 
    1020             :   // single dish specific
    1021          32 :   solvepar.define("fraction", fraction);
    1022          32 :   solvepar.define("numedge", numedge);
    1023          32 :   solvepar.define("radius", radius);
    1024          32 :   solvepar.define("smooth", smooth);
    1025             : 
    1026          64 :   return setsolve(type,solvepar);
    1027          32 : }
    1028             : 
    1029           0 : Bool Calibrater::setsolvebandpoly(const String& table,
    1030             :                                   const Bool& append,
    1031             :                                   const String& solint,
    1032             :                                   const String& combine,
    1033             :                                   const Vector<Int>& degree,
    1034             :                                   const Bool& visnorm,
    1035             :                                   const Bool& solnorm,
    1036             :                                   const Int& maskcenter,
    1037             :                                   const Float& maskedge,
    1038             :                                   const String& refant) {
    1039             : 
    1040           0 :   logSink() << LogOrigin("Calibrater","setsolvebandpoly") << LogIO::NORMAL3;
    1041             : 
    1042             :   // TBD: support solution interval!
    1043             : 
    1044             :     // Create a record description containing the solver parameters
    1045           0 :     RecordDesc solveparDesc;
    1046           0 :     solveparDesc.addField ("table", TpString);
    1047           0 :     solveparDesc.addField ("append", TpBool);
    1048           0 :     solveparDesc.addField ("solint", TpString);
    1049           0 :     solveparDesc.addField ("combine", TpString);
    1050           0 :     solveparDesc.addField ("degree", TpArrayInt);
    1051           0 :     solveparDesc.addField ("visnorm", TpBool);
    1052           0 :     solveparDesc.addField ("solnorm", TpBool);
    1053           0 :     solveparDesc.addField ("maskcenter", TpInt);
    1054           0 :     solveparDesc.addField ("maskedge", TpFloat);
    1055           0 :     solveparDesc.addField ("refant", TpArrayInt);
    1056             : 
    1057             :     //    solveparDesc.addField ("preavg", TpDouble);
    1058             :     //    solveparDesc.addField ("phaseonly", TpBool);
    1059             :     
    1060             :     // Create a solver record with the requisite field values
    1061           0 :     Record solvepar(solveparDesc);
    1062           0 :     solvepar.define ("table", table);
    1063           0 :     solvepar.define ("append", append);
    1064           0 :     solvepar.define ("solint",solint);
    1065           0 :     String upcomb=combine;
    1066           0 :     upcomb.upcase();
    1067           0 :     solvepar.define ("combine",combine);
    1068           0 :     solvepar.define ("degree", degree);
    1069           0 :     solvepar.define ("visnorm", visnorm);
    1070           0 :     solvepar.define ("solnorm", solnorm);
    1071           0 :     solvepar.define ("maskcenter", maskcenter);
    1072           0 :     solvepar.define ("maskedge", maskedge);
    1073           0 :     solvepar.define ("refant", getRefantIdxList(refant));
    1074             : 
    1075             : 
    1076             :     //    solvepar.define ("t", t);
    1077             :     //    solvepar.define ("preavg", preavg);
    1078             :     //    solvepar.define ("phaseonly", phaseonly);
    1079             : 
    1080             : 
    1081           0 :     return setsolve("BPOLY",solvepar);
    1082             : 
    1083           0 : }
    1084             : 
    1085           0 : Bool Calibrater::setsolvegainspline(const String& table,
    1086             :                                     const Bool&   append,
    1087             :                                     const String& apmode,
    1088             :                                     const Double& splinetime,
    1089             :                                     const Double& preavg,
    1090             :                                     const Int&    numpoint,
    1091             :                                     const Double& phasewrap,
    1092             :                                     const String& refant) {
    1093             :   
    1094           0 :   logSink() << LogOrigin("Calibrater","setsolvegainspline") << LogIO::NORMAL3;
    1095             : 
    1096             :   // Create a record description containing the solver parameters
    1097           0 :   RecordDesc solveparDesc;
    1098           0 :   solveparDesc.addField ("table", TpString);
    1099           0 :   solveparDesc.addField ("append", TpBool);
    1100           0 :   solveparDesc.addField ("apmode", TpString);
    1101           0 :   solveparDesc.addField ("splinetime", TpDouble);
    1102           0 :   solveparDesc.addField ("preavg", TpDouble);
    1103           0 :   solveparDesc.addField ("refant", TpArrayInt);
    1104           0 :   solveparDesc.addField ("numpoint", TpInt);
    1105           0 :   solveparDesc.addField ("phasewrap", TpDouble);
    1106             :   
    1107             :   // Create a solver record with the requisite field values
    1108           0 :   Record solvepar(solveparDesc);
    1109           0 :   solvepar.define ("table", table);
    1110           0 :   solvepar.define ("append", append);
    1111           0 :   String upMode=apmode;
    1112           0 :   upMode.upcase();
    1113           0 :   solvepar.define ("apmode", upMode);
    1114           0 :   solvepar.define ("splinetime",splinetime);
    1115           0 :   solvepar.define ("preavg", preavg);
    1116           0 :   solvepar.define ("refant", getRefantIdxList(refant));
    1117           0 :   solvepar.define ("numpoint",numpoint);
    1118           0 :   solvepar.define ("phasewrap",phasewrap);
    1119             :   
    1120           0 :   return setsolve("GSPLINE",solvepar);
    1121             :   
    1122           0 : }
    1123             : 
    1124          32 : Bool Calibrater::setsolve (const String& type, 
    1125             :                            const Record& solvepar) {
    1126             : 
    1127             :   // Attempt to create the solvable object
    1128          32 :   SolvableVisCal *svc(NULL);
    1129             :   try {
    1130             : 
    1131          32 :     if(!ok()) 
    1132           0 :       throw(AipsError("Calibrater not prepared for setsolve."));
    1133             : 
    1134          32 :     String upType = type;
    1135          32 :     upType.upcase();
    1136             : 
    1137             :     // Clean out any old solve that was lying around
    1138          32 :     unsetsolve();
    1139             : 
    1140             :     logSink() << LogIO::NORMAL 
    1141             :               << "Arranging to SOLVE:"
    1142          32 :               << LogIO::POST;
    1143             : 
    1144             :     // Create the new SolvableVisCal
    1145          32 :     svc = createSolvableVisCal(upType,*msmc_p);
    1146          32 :     svc->setSolve(solvepar);
    1147             :     
    1148             :     logSink() << LogIO::NORMAL << ".   "
    1149          32 :               << svc->solveinfo()
    1150          32 :               << LogIO::POST;
    1151             : 
    1152             :     // Creation apparently successful, keep it
    1153          32 :     svc_p=svc;
    1154          32 :     svc=NULL;
    1155             : 
    1156             :     // if calibration specific data filter is necessary
    1157             :     // keep configuration parameter as a record
    1158          32 :     setCalFilterConfiguration(upType, solvepar);
    1159             : 
    1160          32 :     return true;
    1161             : 
    1162          32 :   } catch (AipsError x) {
    1163             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    1164           0 :               << LogIO::POST;
    1165           0 :     unsetsolve();
    1166           0 :     if (svc) delete svc;
    1167           0 :     throw(AipsError("Error in Calibrater::setsolve."));
    1168             :     return false;
    1169           0 :   } 
    1170             :   return false;
    1171             : }
    1172             : 
    1173           0 : Vector<Int> Calibrater::convertSetToVector(set<Int> selset){
    1174           0 :   Vector<Int> vtmpint(selset.begin(), selset.size(),0);
    1175           0 :   return vtmpint;
    1176             : }
    1177             : 
    1178           0 : Vector<Int> Calibrater::getSelectedSpws() {
    1179           0 :   MSMetaData msmdtmp(mssel_p, 50.0);
    1180           0 :   set<uInt> selspwset = msmdtmp.getSpwIDs();
    1181           0 :   Vector<Int> res(selspwset.begin(), selspwset.size(),0);
    1182           0 :   return res;
    1183           0 : }
    1184             : 
    1185           0 : Vector<String> Calibrater::getSelectedIntents() {
    1186           0 :   MSMetaData msmdtmp(mssel_p, 50.0);
    1187           0 :   set<String> selintentset = msmdtmp.getIntents();
    1188           0 :   Vector<String> res(selintentset.begin(), selintentset.size(),0);
    1189           0 :   return res;
    1190           0 : }
    1191             : 
    1192           0 : Vector<String> Calibrater::getApplyTables() {
    1193           0 :   set<String> applytableset;
    1194           0 :   Int numtables = vc_p.nelements();
    1195           0 :   string space_delimiter = " ";
    1196           0 :   vector<string> words{};
    1197           0 :   size_t pos = 0;
    1198           0 :   string applyinf;
    1199             :   
    1200             :   // parse through the apply info
    1201             :   // Grab all the tables and put them in a vector
    1202           0 :   if (numtables > 0){
    1203           0 :     for (Int i=0;i<numtables;i++){
    1204           0 :       applyinf = vc_p[i]->applyinfo();
    1205           0 :       while ((pos=applyinf.find(space_delimiter))!=string::npos) {
    1206           0 :         words.push_back(applyinf.substr(0, pos));
    1207           0 :         applyinf.erase(0, pos+space_delimiter.length());
    1208             :       }
    1209           0 :       for (const auto &str : words){
    1210           0 :         if (str.rfind("table=",0) == 0){
    1211           0 :           applytableset.insert(str.substr(6));
    1212             :         }
    1213             :       }
    1214             :     }
    1215             :   }
    1216           0 :   Vector<String> res(applytableset.begin(),applytableset.size(),0);
    1217           0 :   return res;
    1218           0 : }
    1219             : 
    1220           0 : Vector<String> Calibrater::getSolveTable() {
    1221           0 :   string solveinf;
    1222           0 :   set<String> solvetableset;
    1223           0 :   string space_delimiter = " ";
    1224           0 :   vector<string> words{};
    1225           0 :   size_t pos = 0;
    1226             :   
    1227             :   // Parse through the solve info
    1228             :   // and extract the applied solve table into a vector
    1229           0 :   if (svc_p){
    1230           0 :     solveinf = svc_p->solveinfo();
    1231           0 :     while ((pos=solveinf.find(space_delimiter)) !=string::npos) {
    1232           0 :       words.push_back(solveinf.substr(0, pos));
    1233           0 :       solveinf.erase(0, pos+space_delimiter.length());
    1234             :     }
    1235           0 :     for (const auto &str : words) {
    1236           0 :       if (str.rfind("table=",0) == 0){
    1237           0 :         solvetableset.insert(str.substr(6));
    1238             :       }
    1239             :     }
    1240             :   }
    1241           0 :   Vector<String> res(solvetableset.begin(), solvetableset.size(),0);
    1242           0 :   return res;
    1243           0 : }
    1244             : 
    1245           0 : Bool Calibrater::getIteratorSelection(Vector<Int>* observationlist, Vector<Int>* scanlist, Vector<Int>* fieldlist, Vector<Int>* antennalist) {
    1246             :   // get the observation, scan, field, and antenna from the iterator
    1247           0 :   set<Int> selobsset;
    1248           0 :   set<Int> selscanset;
    1249           0 :   set<Int> selfieldset;
    1250           0 :   set<Int> selantset;
    1251             : 
    1252           0 :   vi::VisibilityIterator2 vi(*mssel_p);
    1253           0 :   vi.originChunks();
    1254           0 :   vi.origin();
    1255           0 :   vi::VisBuffer2 *vb = vi.getVisBuffer();
    1256             :   
    1257           0 :   for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()){
    1258           0 :     for (vi.origin (); vi.more(); vi.next()){
    1259             :         // get obs ids
    1260           0 :         selobsset.insert(vb->observationId()(0));
    1261             :         // get scan ids
    1262           0 :         selscanset.insert(vb->scan()(0));
    1263             :         // get field ids
    1264           0 :         selfieldset.insert(vb->fieldId()(0));
    1265             :       }
    1266             :   }
    1267           0 :   for (auto & ant : vb->antenna1()){
    1268           0 :     selantset.insert(ant);
    1269           0 :   }
    1270           0 :   for (auto & ant : vb->antenna2()){
    1271           0 :     selantset.insert(ant);
    1272           0 :   }
    1273             :   
    1274           0 :   *observationlist = convertSetToVector(selobsset);
    1275           0 :   *scanlist = convertSetToVector(selscanset);
    1276           0 :   *fieldlist = convertSetToVector(selfieldset);
    1277           0 :   *antennalist = convertSetToVector(selantset);
    1278             :   
    1279           0 :   return true;
    1280           0 : }
    1281             : 
    1282           0 :  Record Calibrater::returndict()
    1283             : {
    1284             :   // Create record and subrecrds for selection data
    1285           0 :   Record rec;
    1286           0 :   Record selectVisRec;
    1287             : 
    1288           0 :   Vector<Int> selscanlist;
    1289           0 :   Vector<Int> selfieldlist;
    1290           0 :   Vector<Int> selantlist;
    1291           0 :   Vector<Int> selobslist;
    1292             : 
    1293           0 :   getIteratorSelection(&selobslist, &selscanlist, &selfieldlist, &selantlist);
    1294             :      
    1295             :   // Define sub-record for selection parameters
    1296           0 :   selectVisRec.define("antennas", selantlist);
    1297           0 :   selectVisRec.define("field", selfieldlist);
    1298           0 :   selectVisRec.define("spw", getSelectedSpws());
    1299           0 :   selectVisRec.define("scan", selscanlist);
    1300           0 :   selectVisRec.define("observation", selobslist);
    1301           0 :   selectVisRec.define("intents", getSelectedIntents());
    1302             :   
    1303             :   // Create a record with current calibrater state information
    1304             :   //rec.define("antennas", selantlist);
    1305             :   //rec.define("field", selfieldlist);
    1306             :   //rec.define("spw", getSelectedSpws());
    1307             :   //rec.define("scan", selscanlist);
    1308             :   //rec.define("observation", selobslist);
    1309             :   //rec.define("intents", getSelectedIntents());
    1310           0 :   rec.defineRecord("selectvis", selectVisRec);
    1311           0 :   rec.define("apply_tables", getApplyTables());
    1312           0 :   rec.define("solve_tables", getSolveTable());
    1313             :     
    1314           0 :   rec.merge(resRec_);
    1315             :   
    1316           0 :   return rec;
    1317           0 : }
    1318             : 
    1319           0 : Bool Calibrater::state() {
    1320             : 
    1321           0 :   logSink() << LogOrigin("Calibrater","state") << LogIO::NORMAL3;
    1322             : 
    1323           0 :   applystate();
    1324           0 :   solvestate();
    1325             : 
    1326           0 :   return true;
    1327             : 
    1328             : }
    1329             : 
    1330          32 : Bool Calibrater::applystate() {
    1331             : 
    1332             : 
    1333             :   //  logSink() << LogOrigin("Calibrater","applystate") << LogIO::NORMAL;
    1334             : 
    1335             :   logSink() << LogIO::NORMAL 
    1336             :             << "The following calibration terms are arranged for apply:"
    1337          32 :             << LogIO::POST;
    1338             : 
    1339          32 :   Int napp(vc_p.nelements());
    1340          32 :   if (napp>0)
    1341          17 :     for (Int iapp=0;iapp<napp;++iapp)
    1342             :       logSink() << LogIO::NORMAL << ".   "
    1343          18 :                 << vc_p[iapp]->applyinfo()
    1344          18 :                 << LogIO::POST;
    1345             :   else
    1346             :     logSink() << LogIO::NORMAL << ".   "
    1347             :               << "(None)"
    1348          24 :               << LogIO::POST;
    1349             : 
    1350          32 :   return true;
    1351             : 
    1352             : }
    1353             : 
    1354             : 
    1355          32 : Bool Calibrater::solvestate() {
    1356             : 
    1357             :   //  logSink() << LogOrigin("Calibrater","solvestate") << LogIO::NORMAL;
    1358             : 
    1359             :   logSink() << LogIO::NORMAL 
    1360             :             << "The following calibration term is arranged for solve:"
    1361          32 :             << LogIO::POST;
    1362             : 
    1363          32 :   if (svc_p)
    1364             :     logSink() << LogIO::NORMAL << ".   "
    1365          32 :               << svc_p->solveinfo()
    1366          32 :               << LogIO::POST;
    1367             :   else
    1368             :     logSink()  << LogIO::NORMAL << ".   "
    1369             :               << "(None)"
    1370           0 :               << LogIO::POST;
    1371             : 
    1372          32 :   return true;
    1373             : }
    1374             : 
    1375         339 : Bool Calibrater::reset(const Bool& apply, const Bool& solve) {
    1376             : 
    1377             :   //  logSink() << LogOrigin("Calibrater","reset") << LogIO::NORMAL;
    1378             : 
    1379             :   // Delete the VisCal apply list
    1380         339 :   if (apply)   
    1381         339 :     unsetapply();
    1382             : 
    1383             :   // Delete the VisCal solve object
    1384         339 :   if (solve)
    1385         339 :     unsetsolve();
    1386             :         
    1387         339 :   return true;
    1388             : }
    1389             : 
    1390             : // Delete all (default) or one VisCal in apply list
    1391         339 : Bool Calibrater::unsetapply(const Int& which) {
    1392             : 
    1393             :   //  logSink() << LogOrigin("Calibrater","unsetapply") << LogIO::NORMAL;
    1394             :   
    1395             :   try {
    1396         339 :     if (which<0) {
    1397         348 :       for (uInt i=0;i<vc_p.nelements();i++)
    1398           9 :         if (vc_p[i]) delete vc_p[i];
    1399         339 :       vc_p.resize(0,true);
    1400             :     } else {
    1401           0 :       if (vc_p[which]) delete vc_p[which];
    1402           0 :       vc_p.remove(which);
    1403             :     }
    1404             :     
    1405             :     // Maintain size/sort of apply list
    1406         339 :     if(ve_p) ve_p->setapply(vc_p);
    1407             : 
    1408         339 :     return true;
    1409           0 :   } catch (AipsError x) {
    1410             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    1411           0 :               << LogIO::POST;
    1412           0 :     throw(AipsError("Error in Calibrater::unsetapply."));
    1413             : 
    1414             :     return false;
    1415           0 :   }
    1416             :   return false;
    1417             : }
    1418             : 
    1419             :   // Delete solve VisCal
    1420         371 : Bool Calibrater::unsetsolve() {
    1421             : 
    1422             :   //  logSink() << LogOrigin("Calibrater","unsetsolve") << LogIO::NORMAL;
    1423             : 
    1424             :   try {
    1425         371 :     if (svc_p) delete svc_p;
    1426         371 :     svc_p=NULL;
    1427             :     
    1428         371 :     if(ve_p) ve_p->setsolve(*svc_p);
    1429             : 
    1430         371 :     return true;
    1431             : 
    1432           0 :   } catch (AipsError x) {
    1433             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    1434           0 :               << LogIO::POST;
    1435           0 :     throw(AipsError("Error in Calibrater::unsetsolve."));
    1436             :     return false;
    1437           0 :   }
    1438             :   return false;
    1439             : }
    1440             : 
    1441             : Bool
    1442           5 : Calibrater::setCorrDepFlags(const Bool& corrDepFlags) 
    1443             : {
    1444             : 
    1445           5 :   logSink() << LogOrigin("Calibrater","setCorrDepFlags") << LogIO::NORMAL;
    1446             : 
    1447             :   // Set it
    1448           5 :   corrDepFlags_=corrDepFlags;
    1449             : 
    1450           5 :   logSink() << "Setting correlation dependent flags = " << (corrDepFlags_ ? "True" : "False") << LogIO::POST;
    1451             : 
    1452           5 :   return true;
    1453             : 
    1454             : }
    1455             : 
    1456             : Bool
    1457           0 : Calibrater::setCorrcomb(const String& corrcomb) 
    1458             : {
    1459             : 
    1460           0 :   logSink() << LogOrigin("Calibrater", "setCorrcomb") << LogIO::NORMAL;
    1461             : 
    1462           0 :   corrcomb_= corrcomb;
    1463             : 
    1464           0 :   logSink() << "Setting correlation combination = " << corrcomb << LogIO::POST;
    1465             : 
    1466           0 :   return true;
    1467             : 
    1468             : }
    1469             : 
    1470             : 
    1471             : Bool
    1472           0 : Calibrater::correct2(String mode)
    1473             : {
    1474           0 :     logSink() << LogOrigin("Calibrater","correct2 (VI2/VB2)") << LogIO::NORMAL;
    1475             : 
    1476             :     //cout << "Artificial STOP!" << endl;
    1477             :     //return false;
    1478             : 
    1479             : 
    1480           0 :     Bool retval = true;
    1481             : 
    1482             :     try {
    1483             : 
    1484             :       // Ensure apply list non-zero and properly sorted
    1485           0 :       ve_p->setapply(vc_p);
    1486             : 
    1487           0 :       bool forceOldVIByEnv(false);
    1488           0 :       forceOldVIByEnv = (getenv("VI1CAL")!=NULL);
    1489           0 :       if (forceOldVIByEnv && anyEQ(ve_p->listTypes(),VisCal::A)) {
    1490           0 :         logSink() << LogIO::WARN << "Using VI2 calibration apply.  AMueller (uvcontsub) no longer requires VI1 for apply." << LogIO::POST;
    1491             :       }
    1492             : 
    1493             :       /*   CAS-12434 (2019Jun07, gmoellen): AMueller works with VB2 in _apply_ (only) context now
    1494             :       // Trap uvcontsub case, since it does not yet handlg VB2
    1495             :       if (anyEQ(ve_p->listTypes(),VisCal::A)) {
    1496             : 
    1497             :         // Only uvcontsub, nothing else
    1498             :         if (ve_p->nTerms()==1) {
    1499             :           // Use old method (which doesn't need WEIGHT_SPECTRUM support in this context)
    1500             :           return this->correct(mode);
    1501             :         }
    1502             :         else
    1503             :           throw(AipsError("Cannot handle AMueller (uvcontsub) and other types simultaneously."));
    1504             :       }
    1505             :       */
    1506             :       
    1507             :       // Report the types that will be applied
    1508           0 :       applystate();
    1509             : 
    1510             :       // make mode all-caps
    1511           0 :       String upmode=mode;
    1512           0 :       upmode.upcase();
    1513             : 
    1514             :       // If trialmode=T, only the flags will be set
    1515             :       //   (and only written if not TRIAL)
    1516           0 :       Bool trialmode=(upmode.contains("TRIAL") || 
    1517           0 :                       upmode.contains("FLAGONLY"));
    1518             : 
    1519             : 
    1520             :       // Arrange for iteration over data
    1521           0 :       Block<Int> columns;
    1522             :       // include scan iteration
    1523           0 :       columns.resize(5);
    1524           0 :       columns[0]=MS::ARRAY_ID;
    1525           0 :       columns[1]=MS::SCAN_NUMBER;
    1526           0 :       columns[2]=MS::FIELD_ID;
    1527           0 :       columns[3]=MS::DATA_DESC_ID;
    1528           0 :       columns[4]=MS::TIME;
    1529             : 
    1530           0 :       vi::SortColumns sc(columns);
    1531           0 :       vi::VisibilityIterator2 vi(*mssel_p,sc,true);
    1532             : 
    1533             :       // Apply channel selection (see selectChannel(spw))
    1534           0 :       if (frequencySelections_p)
    1535           0 :         vi.setFrequencySelection(*frequencySelections_p);
    1536             : 
    1537           0 :       vi::VisBuffer2 *vb = vi.getVisBuffer();
    1538             : 
    1539             :       // Detect if we will be setting WEIGHT_SPECTRUM, and arrange for this
    1540           0 :       vi.originChunks();    // required for wSExists() in next line to work
    1541           0 :       vi.origin();
    1542           0 :       Bool doWtSp=vi.weightSpectrumExists();  // Exists non-trivially
    1543             : 
    1544           0 :       if (doWtSp && calWt()) 
    1545           0 :         logSink() << "Found valid WEIGHT_SPECTRUM, correcting it." << LogIO::POST;
    1546             : 
    1547             :       // Pass each timestamp (VisBuffer) to VisEquation for correction
    1548             :       
    1549           0 :       Vector<Bool> uncalspw(vi.nSpectralWindows());  // Used to accumulate error messages
    1550           0 :       uncalspw.set(false);                           // instead of bombing the user
    1551             : 
    1552           0 :       uInt nvb(0);
    1553             : 
    1554           0 :         for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    1555             : 
    1556           0 :           for (vi.origin(); vi.more(); vi.next()) {
    1557             : 
    1558           0 :             uInt spw = vb->spectralWindows()(0);
    1559             :             //if (ve_p->spwOK(spw)){
    1560             :             //if (    (usingCalLibrary_ && ve_p->VBOKforCalApply(*vb))  // CalLibrary case
    1561             :             //     || (!usingCalLibrary_ && ve_p->spwOK(spw))          // old-fashioned case
    1562             :             //   ) {
    1563           0 :             if ( ve_p->VBOKforCalApply(*vb) ) {  // Handles old and new (CL) contexts
    1564             : 
    1565             :               // Re-initialize weight info from sigma info
    1566             :               //   This is smart wrt spectral weights, etc.
    1567             :               //   (this makes W and WS, if present, "dirty" in the vb)
    1568             :               // TBD: only do this if !trial (else: avoid the I/O)
    1569           0 :               vb->resetWeightsUsingSigma();
    1570             : 
    1571             :               // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
    1572             :               //   (this makes CD "dirty" in the vb)
    1573             :               // TBD: only do this if !trial (else: avoid the I/O)
    1574           0 :               vb->setVisCubeCorrected(vb->visCube());
    1575             : 
    1576             :               // Make flagcube dirty in the vb
    1577             :               //  NB: we must _always_ do this I/O  (even trial mode)
    1578           0 :               vb->setFlagCube(vb->flagCube());
    1579             : 
    1580             :               // Make all vb "not dirty"; we'll carefully arrange the writeback below
    1581           0 :               vb->dirtyComponentsClear();
    1582             : 
    1583             :               // throws exception if nothing to apply
    1584           0 :               ve_p->correct2(*vb,trialmode,doWtSp);
    1585             :                     
    1586             :               // Only if not a trial run, manage writes to disk
    1587           0 :               if (upmode!="TRIAL") {
    1588             :                 
    1589           0 :                 if (upmode.contains("CAL")) {
    1590           0 :                   vb->setVisCubeCorrected(vb->visCubeCorrected());
    1591             : 
    1592           0 :                   if (calWt()) {
    1593             :                     // Set weights dirty only if calwt=T
    1594           0 :                     if (doWtSp) {
    1595           0 :                       vb->setWeightSpectrum(vb->weightSpectrum());
    1596             :                       // If WS was calibrated, set W to its channel-axis median
    1597           0 :                       vb->setWeight(partialMedians(vb->weightSpectrum(),IPosition(1,1)));
    1598             :                     }
    1599             :                     else
    1600           0 :                       vb->setWeight(vb->weight()); 
    1601             :                   }
    1602             :                 }
    1603             : 
    1604           0 :                 if (upmode.contains("FLAG"))
    1605           0 :                   vb->setFlagCube(vb->flagCube());
    1606             :                 
    1607             :                 // Push the calibrated data etc. back to the MS
    1608           0 :                 vb->writeChangesBack();
    1609           0 :                 nvb+=1;  // increment vb counter
    1610             :               }
    1611             : 
    1612             :             }
    1613             :             else{
    1614           0 :               uncalspw[spw] = true;
    1615             : 
    1616             :               // set the flags, if we are being strict
    1617             :               // (don't touch the data/weights, which are initialized)
    1618           0 :               if (upmode.contains("STRICT")) {
    1619             : 
    1620             :                 // reference (to avoid copy) and set the flags
    1621           0 :                 Cube<Bool> fC(vb->flagCube());   // reference
    1622           0 :                 fC.set(true);  
    1623             : 
    1624             :                 // make dirty for writeChangesBack  (does this do an actual copy?)
    1625           0 :                 vb->setFlagCube(vb->flagCube());
    1626             : 
    1627             :                 // write back to 
    1628           0 :                 vb->writeChangesBack();
    1629             : 
    1630           0 :               }
    1631             :               else {
    1632             : 
    1633             :                 // Break out of inner VI2 loop, if possible
    1634           0 :                 if (! vi.isAsynchronous()){
    1635             :                   
    1636             :                   // Asynchronous I/O doesn't have a way to skip
    1637             :                   // VisBuffers, so only break out when not using
    1638             :                   // async i/o.
    1639           0 :                   break; 
    1640             : 
    1641             :                 }
    1642             : 
    1643             :               }
    1644             :             }
    1645             :           }
    1646             :         }
    1647             : 
    1648             :         // Now that we're out of the loop, summarize any errors.
    1649             : 
    1650           0 :         retval = summarize_uncalspws(uncalspw, "correct",
    1651           0 :                                      upmode.contains("STRICT"));
    1652             :         
    1653           0 :         actRec_=Record();
    1654           0 :         actRec_.define("origin","Calibrater::correct");
    1655           0 :         actRec_.defineRecord("VisEquation",ve_p->actionRec());
    1656             :         
    1657             : 
    1658             :         //cout << "Number of VisBuffers corrected: " << nvb << endl;
    1659             : 
    1660           0 :     }
    1661           0 :     catch (AipsError x) {
    1662             :         logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1663           0 :                       << LogIO::POST;
    1664             : 
    1665           0 :         logSink() << "Resetting all calibration application settings." << LogIO::POST;
    1666           0 :         unsetapply();
    1667             : 
    1668           0 :         throw(AipsError("Error in Calibrater::correct."));
    1669             :         retval = false;         // Not that it ever gets here...
    1670           0 :     }
    1671           0 :     return retval;
    1672             : }
    1673             : 
    1674           0 : Bool Calibrater::corrupt2()
    1675             : {
    1676           0 :     logSink() << LogOrigin("Calibrater","corrupt2 (VI2/VB2)") << LogIO::NORMAL;
    1677           0 :     Bool retval = true;
    1678             : 
    1679             :     try {
    1680             : 
    1681           0 :       if (!ok())
    1682           0 :         throw(AipsError("Calibrater not prepared for corrupt2!"));
    1683             :       
    1684             :       // MODEL_DATA column must be physically present!
    1685           0 :       if (!ms_p->tableDesc().isColumn("MODEL_DATA"))
    1686           0 :         throw(AipsError("MODEL_DATA column unexpectedly absent. Cannot corrupt."));
    1687             : 
    1688             :       // Ensure apply list non-zero and properly sorted
    1689           0 :       ve_p->setapply(vc_p);
    1690             : 
    1691             :       /*
    1692             :       // Trap uvcontsub case, since it does not yet handlg VB2
    1693             :       if (anyEQ(ve_p->listTypes(),VisCal::A)) {
    1694             : 
    1695             :         // Only uvcontsub, nothing else
    1696             :         if (ve_p->nTerms()==1) {
    1697             :           // Use old method (which doesn't need WEIGHT_SPECTRUM support in this context)
    1698             :           return this->correct(mode);
    1699             :         }
    1700             :         else
    1701             :           throw(AipsError("Cannot handle AMueller (uvcontsub) and other types simultaneously."));
    1702             :       }
    1703             :       */
    1704             :       
    1705             :       // Report the types that will be applied
    1706           0 :       applystate();
    1707             : 
    1708             :       // Arrange for iteration over data
    1709           0 :       Block<Int> columns;
    1710             :       // include scan iteration
    1711           0 :       columns.resize(5);
    1712           0 :       columns[0]=MS::ARRAY_ID;
    1713           0 :       columns[1]=MS::SCAN_NUMBER;
    1714           0 :       columns[2]=MS::FIELD_ID;
    1715           0 :       columns[3]=MS::DATA_DESC_ID;
    1716           0 :       columns[4]=MS::TIME;
    1717             : 
    1718           0 :       vi::SortColumns sc(columns);
    1719           0 :       vi::VisibilityIterator2 vi(*mssel_p,sc,true);
    1720             : 
    1721             :       // Apply channel selection (see selectChannel(spw))
    1722           0 :       if (frequencySelections_p)
    1723           0 :         vi.setFrequencySelection(*frequencySelections_p);
    1724             : 
    1725           0 :       vi::VisBuffer2 *vb = vi.getVisBuffer();
    1726             : 
    1727             :       // Detect if we will be setting WEIGHT_SPECTRUM, and arrange for this
    1728           0 :       vi.originChunks();    // required for wSExists() in next line to work
    1729           0 :       vi.origin();
    1730             :       
    1731           0 :       Vector<Bool> uncalspw(vi.nSpectralWindows());  // Used to accumulate error messages
    1732           0 :       uncalspw.set(false);                           // instead of bombing the user
    1733             : 
    1734             :       // Pass each timestamp (VisBuffer) to VisEquation for correction
    1735           0 :       uInt nvb(0);
    1736           0 :       for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    1737           0 :         for (vi.origin(); vi.more(); vi.next()) {
    1738           0 :           uInt spw = vb->spectralWindows()(0);
    1739             :           //if (ve_p->spwOK(spw)){
    1740           0 :           if (usingCalLibrary_ || ve_p->spwOK(spw)){
    1741             : 
    1742             :             // Make all vb "not dirty", for safety
    1743           0 :             vb->dirtyComponentsClear();
    1744             : 
    1745             :             // throws exception if nothing to apply
    1746           0 :             ve_p->corrupt2(*vb);
    1747             : 
    1748             :             // make visCubeModel _ONLY_ dirty for writeChangesBack
    1749           0 :             vb->setVisCubeModel(vb->visCubeModel());
    1750             :             
    1751             :             // Push the corrupted model back to the MS
    1752           0 :             vb->writeChangesBack();
    1753           0 :             nvb+=1;  // increment vb counter
    1754             :           }
    1755             :           else{
    1756           0 :             uncalspw[spw] = true;
    1757             :           }
    1758             :         }
    1759             :       }
    1760             : 
    1761             :       // Now that we're out of the loop, summarize any errors.
    1762           0 :       retval = summarize_uncalspws(uncalspw, "corrupt2",false);   // (didn't flag them)
    1763             :       
    1764           0 :       actRec_=Record();
    1765           0 :       actRec_.define("origin","Calibrater::corrupt2");
    1766           0 :       actRec_.defineRecord("VisEquation",ve_p->actionRec());
    1767             : 
    1768             :       //cout << "Number of VisBuffers corrupted: " << nvb << endl;
    1769             :       
    1770           0 :     }
    1771           0 :     catch (AipsError x) {
    1772             :         logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1773           0 :                       << LogIO::POST;
    1774             : 
    1775           0 :         logSink() << "Resetting all calibration application settings." << LogIO::POST;
    1776           0 :         unsetapply();
    1777             : 
    1778           0 :         throw(AipsError("Error in Calibrater::corrupt2."));
    1779             :         retval = false;         // Not that it ever gets here...
    1780           0 :     }
    1781           0 :     return retval;
    1782             :  }
    1783             : 
    1784           0 : Bool Calibrater::initWeightsWithTsys(String wtmode, Bool dowtsp,
    1785             :                                      String tsystable, String gainfield, String interp, Vector<Int> spwmap) {
    1786             : 
    1787           0 :         logSink() << LogOrigin("Calibrater", "initWeightsWithTsys")
    1788           0 :                         << LogIO::NORMAL;
    1789           0 :         Bool retval = true;
    1790             : 
    1791             :         try {
    1792             : 
    1793           0 :                 if (!ok())
    1794           0 :                         throw(AipsError("Calibrater not prepared for initWeights!"));
    1795             : 
    1796           0 :                 String uptype = calTableType(tsystable);
    1797           0 :                 if (!uptype.contains("TSYS")) {
    1798           0 :                         throw(AipsError(
    1799           0 :                                         "Invalid calibration table type for Tsys weighting."));
    1800             :                 }
    1801             :                 // Set record format for calibration table application information
    1802           0 :                 RecordDesc applyparDesc;
    1803           0 :                 applyparDesc.addField("t", TpDouble);
    1804           0 :                 applyparDesc.addField("table", TpString);
    1805           0 :                 applyparDesc.addField("interp", TpString);
    1806           0 :                 applyparDesc.addField("spw", TpArrayInt);
    1807           0 :                 applyparDesc.addField("fieldstr", TpString);
    1808           0 :                 applyparDesc.addField("calwt", TpBool);
    1809           0 :                 applyparDesc.addField("spwmap", TpArrayInt);
    1810           0 :                 applyparDesc.addField("opacity", TpArrayDouble);
    1811             : 
    1812             :                 // Create record with the requisite field values
    1813           0 :                 Record applypar(applyparDesc);
    1814           0 :                 applypar.define("t", 0.0);
    1815           0 :                 applypar.define("table", tsystable);
    1816           0 :                 applypar.define("interp", interp);
    1817           0 :                 applypar.define("spw", getSpwIdx(""));
    1818           0 :                 applypar.define("fieldstr", gainfield);
    1819           0 :                 applypar.define("calwt", true);
    1820           0 :                 applypar.define("spwmap", spwmap);
    1821           0 :                 applypar.define("opacity", Vector<Double>(1, 0.0));
    1822             : 
    1823           0 :                 if (vc_p.nelements() > 0) {
    1824           0 :                         logSink() << LogIO::WARN << "Resetting all calibration application settings." << LogIO::POST;
    1825           0 :                         unsetapply();
    1826             :                 }
    1827           0 :                 logSink() << LogIO::NORMAL << "Weight initialization does not support selection. Resetting MS selection." << LogIO::POST;
    1828           0 :                 selectvis();
    1829           0 :                 StandardTsys vc = StandardTsys(*msmc_p);
    1830           0 :                 vc.setApply(applypar);
    1831             : 
    1832           0 :                 logSink() << LogIO::NORMAL << ".   " << vc.applyinfo() << LogIO::POST;
    1833           0 :                 PtrBlock<VisCal*> vcb(1, &vc);
    1834             :                 // Maintain sort of apply list
    1835           0 :                 ve_p->setapply(vcb);
    1836             : 
    1837             :                 // Detect WEIGHT_SPECTRUM and SIGMA_SPECTRUM
    1838           0 :                 TableDesc mstd = ms_p->actualTableDesc();
    1839           0 :                 String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
    1840           0 :                 Bool wtspexists = mstd.isColumn(colWtSp);
    1841           0 :                 String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    1842           0 :                 Bool sigspexists = mstd.isColumn(colSigSp);
    1843           0 :                 Bool addsigsp = (dowtsp && !sigspexists);
    1844             : 
    1845             :                 // Some log info
    1846           0 :                 bool use_exposure = false;
    1847           0 :                 if (wtmode == "tsys") {
    1848             :                         logSink()
    1849             :                                         << "Initializing SIGMA and WEIGHT according to channel bandwidth and Tsys. NOTE this is an expert mode."
    1850           0 :                                         << LogIO::WARN << LogIO::POST;
    1851           0 :                 } else if (wtmode == "tinttsys") {
    1852             :                         logSink()
    1853             :                                         << "Initializing SIGMA and WEIGHT according to channel bandwidth, integration time, and Tsys. NOTE this is an expert mode."
    1854           0 :                                         << LogIO::WARN << LogIO::POST;
    1855           0 :                         use_exposure = true;
    1856             :                 } else {
    1857           0 :                         throw(AipsError("Unrecognized wtmode specified: " + wtmode));
    1858             :                 }
    1859             : 
    1860             :                 // Force dowtsp if the column already exists
    1861           0 :                 if (wtspexists && !dowtsp) {
    1862             :                         logSink() << "Found WEIGHT_SPECTRUM; will force its initialization."
    1863           0 :                                         << LogIO::POST;
    1864           0 :                         dowtsp = true;
    1865             :                 }
    1866             : 
    1867             :                 // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
    1868           0 :                 if (dowtsp) {
    1869             : 
    1870             :                         // Ensure WEIGHT_SPECTRUM really exists at all
    1871             :                         //   (often it exists but is empty)
    1872           0 :                         if (!wtspexists) {
    1873           0 :                                 logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
    1874             : 
    1875             :                                 // Nominal defaulttileshape
    1876           0 :                                 IPosition dts(3, 4, 32, 1024);
    1877             : 
    1878             :                                 // Discern DATA's default tile shape and use it
    1879           0 :                                 const Record dminfo = ms_p->dataManagerInfo();
    1880           0 :                                 for (uInt i = 0; i < dminfo.nfields(); ++i) {
    1881           0 :                                         Record col = dminfo.asRecord(i);
    1882             :                                         //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    1883           0 :                                         if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
    1884           0 :                                                 dts = IPosition(
    1885           0 :                                                                 col.asRecord("SPEC").asArrayInt(
    1886           0 :                                                                                 "DEFAULTTILESHAPE"));
    1887             :                                                 //cout << "Found DATA's default tile: " << dts << endl;
    1888           0 :                                                 break;
    1889             :                                         }
    1890           0 :                                 }
    1891             : 
    1892             :                                 // Add the column
    1893           0 :                                 String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
    1894           0 :                                 TableDesc tdWtSp;
    1895           0 :                                 tdWtSp.addColumn(
    1896           0 :                                                 ArrayColumnDesc<Float>(colWtSp, "weight spectrum", 2));
    1897           0 :                                 TiledShapeStMan wtSpStMan("TiledWgtSpectrum", dts);
    1898           0 :                                 ms_p->addColumn(tdWtSp, wtSpStMan);
    1899           0 :                         } else
    1900           0 :                                 logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
    1901             :                         // Ensure WEIGHT_SPECTRUM really exists at all
    1902             :                         //   (often it exists but is empty)
    1903           0 :                 if (!sigspexists) {
    1904           0 :                                 logSink() << "Creating SIGMA_SPECTRUM." << LogIO::POST;
    1905             : 
    1906             :                                 // Nominal defaulttileshape
    1907           0 :                                 IPosition dts(3, 4, 32, 1024);
    1908             : 
    1909             :                                 // Discern DATA's default tile shape and use it
    1910           0 :                                 const Record dminfo = ms_p->dataManagerInfo();
    1911           0 :                                 for (uInt i = 0; i < dminfo.nfields(); ++i) {
    1912           0 :                                         Record col = dminfo.asRecord(i);
    1913             :                                         //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    1914           0 :                                         if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
    1915           0 :                                                 dts = IPosition(
    1916           0 :                                                                 col.asRecord("SPEC").asArrayInt(
    1917           0 :                                                                                 "DEFAULTTILESHAPE"));
    1918             :                                                 //cout << "Found DATA's default tile: " << dts << endl;
    1919           0 :                                                 break;
    1920             :                                         }
    1921           0 :                                 }
    1922             : 
    1923             :                                 // Add the column
    1924           0 :                                 String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    1925           0 :                                 TableDesc tdSigSp;
    1926           0 :                                 tdSigSp.addColumn(
    1927           0 :                                                 ArrayColumnDesc<Float>(colSigSp, "sigma spectrum", 2));
    1928           0 :                                 TiledShapeStMan sigSpStMan("TiledSigtSpectrum", dts);
    1929           0 :                                 ms_p->addColumn(tdSigSp, sigSpStMan);
    1930             :                                 {
    1931           0 :                                   TableDesc loctd = ms_p->actualTableDesc();
    1932           0 :                                   String loccolSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    1933           0 :                                   AlwaysAssert(loctd.isColumn(loccolSigSp),AipsError);
    1934           0 :                                 }
    1935           0 :                 }
    1936             :                 }
    1937             :                 else {
    1938           0 :     if (sigspexists) {
    1939           0 :       logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
    1940             :       if (true || ms_p->canRemoveColumn(colSigSp)) {
    1941           0 :         ms_p->removeColumn(colSigSp);
    1942             :       }
    1943             :       else
    1944             :         logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
    1945             :     }
    1946             :                 }
    1947             : 
    1948             :                 // Arrange for iteration over data
    1949             :                 //  TBD: Be sure this sort is optimal for creating WS?
    1950           0 :                 Block<Int> columns;
    1951             :                 // include scan iteration
    1952           0 :                 columns.resize(5);
    1953           0 :                 columns[0] = MS::ARRAY_ID;
    1954           0 :                 columns[1] = MS::SCAN_NUMBER;
    1955           0 :                 columns[2] = MS::FIELD_ID;
    1956           0 :                 columns[3] = MS::DATA_DESC_ID;
    1957           0 :                 columns[4] = MS::TIME;
    1958             : 
    1959           0 :                 vi::SortColumns sc(columns);
    1960           0 :                 vi::VisibilityIterator2 vi2(*ms_p, sc, true);
    1961           0 :                 vi::VisBuffer2 *vb = vi2.getVisBuffer();
    1962             : 
    1963           0 :                 MSColumns mscol(*ms_p);
    1964           0 :                 const MSSpWindowColumns& msspw(mscol.spectralWindow());
    1965           0 :                 uInt nSpw = msspw.nrow();
    1966           0 :                 Vector<Double> effChBw(nSpw, 0.0);
    1967           0 :                 for (uInt ispw = 0; ispw < nSpw; ++ispw) {
    1968           0 :                         effChBw[ispw] = mean(msspw.effectiveBW()(ispw));
    1969             :                 }
    1970             : 
    1971           0 :                 Int ivb(0);
    1972           0 :                 for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
    1973             : 
    1974           0 :                         for (vi2.origin(); vi2.more(); vi2.next(), ++ivb) {
    1975             : 
    1976           0 :                                 Int spw = vb->spectralWindows()(0);
    1977             : 
    1978           0 :                                 auto nrow = vb->nRows();
    1979           0 :                                 Int nchan = vb->nChannels();
    1980           0 :                                 Int ncor = vb->nCorrelations();
    1981             : 
    1982             :                                 // Prepare for WEIGHT_SPECTRUM and SIGMA_SPECTRUM, if nec.
    1983           0 :                                 Cube<Float> newwtsp(0, 0, 0), newsigsp(0, 0, 0);
    1984           0 :                                 if (dowtsp) {
    1985           0 :                                   newwtsp.resize(ncor, nchan, nrow);
    1986           0 :                                   newwtsp.set(1.0);
    1987           0 :                                   newsigsp.resize(ncor, nchan, nrow);
    1988           0 :                                   newsigsp.set(1.0);
    1989             :                                 }
    1990             : 
    1991           0 :                                 if (ve_p->spwOK(spw)) {
    1992             : 
    1993             :                                         // Re-initialize weight info from sigma info
    1994             :                                         //   This is smart wrt spectral weights, etc.
    1995             :                                         //   (this makes W and WS, if present, "dirty" in the vb)
    1996             :                                         // TBD: only do this if !trial (else: avoid the I/O)
    1997             :                                         // vb->resetWeightsUsingSigma();
    1998             :                                         // Handle non-trivial modes
    1999             :                                         // Init WEIGHT, SIGMA  from bandwidth & time
    2000           0 :                                         Matrix<Float> newwt(ncor, nrow), newsig(ncor, nrow);
    2001           0 :                                         newwt.set(1.0);
    2002           0 :                                         newsig.set(1.0);
    2003             : 
    2004             :                                         // Detect ACs
    2005           0 :                                         const Vector<Int> a1(vb->antenna1());
    2006           0 :                                         const Vector<Int> a2(vb->antenna2());
    2007           0 :                                         Vector<Bool> ac(a1 == a2);
    2008             : 
    2009             :                                         // XCs need an extra factor of 2
    2010           0 :                                         Vector<Float> xcfactor(nrow, 2.0);
    2011           0 :                                         xcfactor(ac) = 1.0;                             // (but not ACs)
    2012             : 
    2013             :                                         // The row-wise integration time
    2014           0 :                                         Vector<Float> expo(nrow);
    2015           0 :                                         convertArray(expo, vb->exposure());
    2016             : 
    2017             :                                         // Set weights to channel bandwidth first.
    2018           0 :                                         newwt.set(Float(effChBw(spw)));
    2019             : 
    2020             :                                         // For each correlation, apply exposure and xcfactor
    2021           0 :                                         for (Int icor = 0; icor < ncor; ++icor) {
    2022             : 
    2023           0 :                                                 Vector<Float> wt(newwt.row(icor));
    2024           0 :                                                 if (use_exposure) {
    2025           0 :                                                         wt *= expo;
    2026             :                                                 }
    2027           0 :                                                 wt *= xcfactor;
    2028           0 :                                                 if (dowtsp) {
    2029           0 :                                                         for (Int ich = 0; ich < nchan; ++ich) {
    2030             :                                                                 Vector<Float> wtspi(
    2031           0 :                                                                                 newwtsp(Slice(icor, 1, 1),
    2032           0 :                                                                                                 Slice(ich, 1, 1), Slice()).nonDegenerate(
    2033           0 :                                                                                                 IPosition(1, 2)));
    2034           0 :                                                                 wtspi = wt;
    2035           0 :                                                         }
    2036             :                                                 }
    2037           0 :                                         }
    2038             :                                         // Handle SIGMA_SPECTRUM
    2039           0 :                                         if (dowtsp) {
    2040           0 :                                           newsigsp = 1.0f / sqrt(newwtsp);
    2041             :                                         }
    2042             :                                         // sig from wt is inverse sqrt
    2043           0 :                                         newsig = 1.0f / sqrt(newwt);
    2044             : 
    2045             :                                         // Arrange write-back of both SIGMA and WEIGHT
    2046           0 :                                         vb->setSigma(newsig);
    2047           0 :                                         vb->setWeight(newwt);
    2048           0 :                                         if (dowtsp) {
    2049           0 :                                           vb->initWeightSpectrum(newwtsp);
    2050           0 :                                           vb->initSigmaSpectrum(newsigsp);
    2051             :                                         }
    2052             :                                         // Force writeback to disk (need to initialize weight/sigma before applying cal table)
    2053           0 :                                         vb->writeChangesBack();
    2054             : 
    2055             :                                         // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
    2056             :                                         //   (this makes CD "dirty" in the vb)
    2057             :                                         // TBD: only do this if !trial (else: avoid the I/O)
    2058           0 :                                         vb->setVisCubeCorrected(vb->visCube());
    2059             : 
    2060             :                                         // Make flagcube dirty in the vb
    2061             :                                         //  NB: we must _always_ do this I/O  (even trial mode)
    2062           0 :                                         vb->setFlagCube(vb->flagCube());
    2063             : 
    2064             :                                         // Make all vb "not dirty"; we'll carefully arrange the writeback below
    2065           0 :                                         vb->dirtyComponentsClear();
    2066             : 
    2067             :                                         // throws exception if nothing to apply
    2068           0 :                                         ve_p->correct2(*vb, false, dowtsp);
    2069             : 
    2070           0 :                                         if (dowtsp) {
    2071           0 :                                                 vb->setWeightSpectrum(vb->weightSpectrum());
    2072             :                                                 // If WS was calibrated, set W to its channel-axis median
    2073           0 :                                                 vb->setWeight( partialMedians(vb->weightSpectrum(), IPosition(1, 1)) );
    2074           0 :                                                 newsigsp = 1.0f / sqrt(vb->weightSpectrum());
    2075           0 :                                                 vb->initSigmaSpectrum(newsigsp);
    2076           0 :                                                 vb->setSigma( partialMedians(newsigsp, IPosition(1, 1)) );
    2077             :                                         } else {
    2078           0 :                                                 vb->setWeight(vb->weight());
    2079           0 :                                                 newsig = 1.0f / sqrt(vb->weight());
    2080           0 :                                                 vb->setSigma(newsig);
    2081             :                                         }
    2082             :                                         // Force writeback to disk
    2083           0 :                                         vb->writeChangesBack();
    2084             : 
    2085           0 :                                 } else {//Not calibrating the spw
    2086           0 :                                   if (dowtsp && !wtspexists) {
    2087             :                                     // newly created WS Need to initialize
    2088           0 :                                     vb->initWeightSpectrum(newwtsp);
    2089             :                                   }
    2090           0 :                                   if (addsigsp) {
    2091             :                                     // newly created SS Need to initialize
    2092           0 :                                     vb->initSigmaSpectrum(newsigsp);
    2093           0 :                                     vb->writeChangesBack();
    2094             :                                   }
    2095             :                                 }
    2096           0 :                         }
    2097             :                 }
    2098             :                 // clear-up Tsys caltable from list of apply
    2099           0 :                 unsetapply();
    2100             : 
    2101           0 :         } catch (AipsError x) {
    2102             :                 logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2103           0 :                                 << LogIO::POST;
    2104             : 
    2105             :                 logSink() << "Resetting all calibration application settings."
    2106           0 :                                 << LogIO::POST;
    2107           0 :                 unsetapply();
    2108             : 
    2109           0 :                 throw(AipsError("Error in Calibrater::initWeights."));
    2110             :                 retval = false;  // Not that it ever gets here...
    2111           0 :         }
    2112           0 :         return retval;
    2113             : }
    2114             : 
    2115             : 
    2116           0 : Bool Calibrater::initWeights(String wtmode, Bool dowtsp) {
    2117             : 
    2118           0 :   logSink() << LogOrigin("Calibrater","initWeights") << LogIO::NORMAL;
    2119           0 :   Bool retval = true;
    2120             : 
    2121             :   try {
    2122             : 
    2123           0 :     if (!ok())
    2124           0 :       throw(AipsError("Calibrater not prepared for initWeights!"));
    2125             : 
    2126             :     // An enum for the requested wtmode
    2127             :     enum wtInitModeEnum {
    2128             :       NONE,    // ambiguous, will complain
    2129             :       ONES,    // SIGMA=1.0, propagate to WEIGHT, WEIGHT_SEPCTRUM
    2130             :       NYQ,      // SIGMA=f(df,dt), propagate to WEIGHT, WEIGHT_SEPCTRUM
    2131             :       SIGMA,   // SIGMA as is, propagate to WEIGHT, WEIGHT_SEPCTRUM
    2132             :       WEIGHT,  // SIGMA, WEIGHT as are, propagate to WEIGHT_SEPCTRUM (if requested)
    2133             :       DELWTSP,  // just delete WEIGHT_SPECTRUM if it exists
    2134             :       DELSIGSP,  // just delete SIGMA_SPECTRUM if it exists
    2135             :     };
    2136             :     
    2137             :     // Translate mode String to enum value
    2138           0 :     wtInitModeEnum initmode(NONE);
    2139           0 :     if (wtmode=="ones") initmode=ONES;
    2140           0 :     else if (wtmode=="nyq") initmode=NYQ;
    2141           0 :     else if (wtmode=="sigma") initmode=SIGMA;
    2142           0 :     else if (wtmode=="weight") initmode=WEIGHT;
    2143           0 :     else if (wtmode=="delwtsp") initmode=DELWTSP;
    2144           0 :     else if (wtmode=="delsigsp") initmode=DELSIGSP;
    2145             : 
    2146             :     // Detect WEIGHT_SPECTRUM
    2147           0 :     TableDesc mstd = ms_p->actualTableDesc();
    2148           0 :     String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
    2149           0 :     Bool wtspexists=mstd.isColumn(colWtSp);
    2150           0 :     String colSigSp=MS::columnName(MS::SIGMA_SPECTRUM);
    2151           0 :     Bool sigspexists=mstd.isColumn(colSigSp);
    2152             : 
    2153             :     // Some log info
    2154           0 :     switch (initmode) {
    2155           0 :     case DELWTSP: {
    2156           0 :       if (wtspexists) {
    2157             :         if (true || ms_p->canRemoveColumn(colWtSp)) {
    2158           0 :           logSink() << "Removing WEIGHT_SPECTRUM." << LogIO::POST;
    2159           0 :           ms_p->removeColumn(colWtSp);
    2160             :         }
    2161             :         else
    2162             :           logSink() << "Sorry, WEIGHT_SPECTRUM is not removable." << LogIO::POST;
    2163             :       }
    2164             :       else
    2165           0 :         logSink() << "WEIGHT_SPECTRUM already absent." << LogIO::POST;
    2166             : 
    2167             :       // Nothing more to do here
    2168           0 :       return true;
    2169             :       break;
    2170             :     }
    2171           0 :     case DELSIGSP: {
    2172           0 :       if (sigspexists) {
    2173             :         if (true || ms_p->canRemoveColumn(colSigSp)) {
    2174           0 :           logSink() << "Removing SIGMA_SPECTRUM." << LogIO::POST;
    2175           0 :           ms_p->removeColumn(colSigSp);
    2176             :         }
    2177             :         else
    2178             :           logSink() << "Sorry, SIGMA_SPECTRUM is not removable." << LogIO::POST;
    2179             :       }
    2180             :       else
    2181           0 :         logSink() << "SIGMA_SPECTRUM already absent." << LogIO::POST;
    2182             : 
    2183             :       // Nothing more to do here
    2184           0 :       return true;
    2185             :       break;
    2186             :     }
    2187           0 :     case NONE: {
    2188           0 :       throw(AipsError("Unrecognized wtmode specified: "+wtmode));
    2189             :       break;
    2190             :     }
    2191           0 :     case ONES: {
    2192           0 :       logSink() << "Initializing SIGMA and WEIGHT with 1.0" << LogIO::POST;
    2193           0 :       break;
    2194             :     }
    2195           0 :     case NYQ: {
    2196             :       logSink() << "Initializing SIGMA and WEIGHT according to channel bandwidth and integration time." 
    2197           0 :                 << LogIO::POST;
    2198           0 :       break;
    2199             :     }
    2200           0 :     case SIGMA: {
    2201           0 :       logSink() << "Initializing WEIGHT according to existing SIGMA." << LogIO::POST;
    2202           0 :       break;
    2203             :     }
    2204           0 :     case WEIGHT: {
    2205             :       // Complain if dowtsp==F, because otherwise we have nothing to do
    2206           0 :       if (!dowtsp)
    2207           0 :         throw(AipsError("Specified wtmode requires dowtsp=T"));
    2208           0 :       break;
    2209             :     }
    2210             :     }
    2211             : 
    2212             :     // Force dowtsp if the column already exists
    2213           0 :     if (wtspexists && !dowtsp) {
    2214           0 :       logSink() << "Found WEIGHT_SPECTRUM; will force its initialization." << LogIO::POST;
    2215           0 :       dowtsp=true;
    2216             :     }
    2217             :     // remove SIGMA_SPECTRUM column for non-channelized weight
    2218           0 :     if (sigspexists) {
    2219           0 :       logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
    2220             :       if (true || ms_p->canRemoveColumn(colSigSp)) {
    2221           0 :         ms_p->removeColumn(colSigSp);
    2222             :       }
    2223             :       else
    2224             :         logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
    2225             :     }
    2226             : 
    2227             :     // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
    2228           0 :     if (dowtsp) {
    2229             : 
    2230             :       // Ensure WEIGHT_SPECTRUM really exists at all 
    2231             :       //   (often it exists but is empty)
    2232           0 :       if (!wtspexists) {
    2233           0 :         logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
    2234             : 
    2235             :         // Nominal defaulttileshape
    2236           0 :         IPosition dts(3,4,32,1024); 
    2237             : 
    2238             :         // Discern DATA's default tile shape and use it
    2239           0 :         const Record dminfo=ms_p->dataManagerInfo();
    2240           0 :         for (uInt i=0;i<dminfo.nfields();++i) {
    2241           0 :           Record col=dminfo.asRecord(i);
    2242             :           //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    2243           0 :           if (anyEQ(col.asArrayString("COLUMNS"),String("DATA"))) {
    2244           0 :             dts=IPosition(col.asRecord("SPEC").asArrayInt("DEFAULTTILESHAPE"));
    2245             :             //cout << "Found DATA's default tile: " << dts << endl;
    2246           0 :             break;
    2247             :           }
    2248           0 :         }
    2249             : 
    2250             :         // Add the column
    2251           0 :         String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
    2252           0 :         TableDesc tdWtSp;
    2253           0 :         tdWtSp.addColumn(ArrayColumnDesc<Float>(colWtSp,"weight spectrum", 2));
    2254           0 :         TiledShapeStMan wtSpStMan("TiledWgtSpectrum",dts);
    2255           0 :         ms_p->addColumn(tdWtSp,wtSpStMan);
    2256           0 :       }
    2257             :       else
    2258           0 :         logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
    2259             : 
    2260             : 
    2261           0 :       logSink() << "Initializing WEIGHT_SPECTRUM uniformly in channel (==WEIGHT)." << LogIO::POST;
    2262             : 
    2263             :     }
    2264             : 
    2265             :     // Arrange for iteration over data
    2266             :     //  TBD: Be sure this sort is optimal for creating WS?
    2267           0 :     Block<Int> columns;
    2268             :     // include scan iteration
    2269           0 :     columns.resize(5);
    2270           0 :     columns[0]=MS::ARRAY_ID;
    2271           0 :     columns[1]=MS::SCAN_NUMBER;
    2272           0 :     columns[2]=MS::FIELD_ID;
    2273           0 :     columns[3]=MS::DATA_DESC_ID;
    2274           0 :     columns[4]=MS::TIME;
    2275             : 
    2276           0 :     vi::SortColumns sc(columns);
    2277           0 :     vi::VisibilityIterator2 vi2(*ms_p,sc,true);
    2278           0 :     vi::VisBuffer2 *vb = vi2.getVisBuffer();
    2279             : 
    2280           0 :     MSColumns mscol(*ms_p);
    2281           0 :     const MSSpWindowColumns& msspw(mscol.spectralWindow());
    2282           0 :     uInt nSpw=msspw.nrow();
    2283           0 :     Vector<Double> effChBw(nSpw,0.0);
    2284           0 :     for (uInt ispw=0;ispw<nSpw;++ispw) {
    2285           0 :       effChBw[ispw]=mean(msspw.effectiveBW()(ispw));
    2286             :     }
    2287             : 
    2288           0 :     Int ivb(0);
    2289           0 :     for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
    2290             : 
    2291           0 :       for (vi2.origin(); vi2.more(); vi2.next(),++ivb) {
    2292             : 
    2293           0 :         Int spw = vb->spectralWindows()(0);
    2294             : 
    2295           0 :         auto nrow=vb->nRows();
    2296           0 :         Int nchan=vb->nChannels();
    2297           0 :         Int ncor=vb->nCorrelations();
    2298             : 
    2299             :         // Vars for new sigma/weight info
    2300             : 
    2301             :         // Prepare for WEIGHT_SPECTRUM, if nec.
    2302           0 :         Cube<Float> newwtsp(0,0,0);
    2303           0 :         if (dowtsp) {
    2304           0 :           newwtsp.resize(ncor,nchan,nrow);
    2305           0 :           newwtsp.set(1.0);
    2306             :         }
    2307             : 
    2308             :         // Handle non-trivial modes
    2309           0 :         switch (initmode) {
    2310             :         // Init WEIGHT, SIGMA  with ones
    2311           0 :         case ONES: {
    2312             : 
    2313           0 :           Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
    2314           0 :           newwt.set(1.0);
    2315           0 :           newsig.set(1.0);
    2316             : 
    2317             :           // Arrange write-back of both SIGMA and WEIGHT
    2318           0 :           vb->setSigma(newsig);
    2319           0 :           vb->setWeight(newwt);
    2320             : 
    2321             :           // NB: newwtsp already ready
    2322             : 
    2323           0 :           break;
    2324           0 :         }         
    2325             : 
    2326             :         // Init WEIGHT, SIGMA  from bandwidth & time
    2327           0 :         case NYQ: {
    2328             : 
    2329           0 :           Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
    2330           0 :           newwt.set(1.0);
    2331           0 :           newsig.set(1.0);
    2332             : 
    2333             :           // Detect ACs
    2334           0 :           const Vector<Int> a1(vb->antenna1());
    2335           0 :           const Vector<Int> a2(vb->antenna2());
    2336           0 :           Vector<Bool> ac(a1==a2);
    2337             :           
    2338             :           // XCs need an extra factor of 2
    2339           0 :           Vector<Float> xcfactor(nrow,2.0);
    2340           0 :           xcfactor(ac)=1.0;   // (but not ACs)
    2341             :           
    2342             :           // The row-wise integration time
    2343           0 :           Vector<Float> expo(nrow);
    2344           0 :           convertArray(expo,vb->exposure());
    2345             : 
    2346             :           // Set weights to channel bandwidth first.
    2347           0 :           newwt.set(Float(effChBw(spw)));
    2348             :           
    2349             :           // For each correlation, apply exposure and xcfactor
    2350           0 :           for (Int icor=0;icor<ncor;++icor) {
    2351             : 
    2352           0 :             Vector<Float> wt(newwt.row(icor));
    2353           0 :             wt*=expo;
    2354           0 :             wt*=xcfactor;
    2355           0 :             if (dowtsp) {
    2356           0 :               for (Int ich=0;ich<nchan;++ich) {
    2357           0 :                 Vector<Float> wtspi(newwtsp(Slice(icor,1,1),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(1,2)));
    2358           0 :                 wtspi=wt;
    2359           0 :               }
    2360             :             }
    2361           0 :           }
    2362             : 
    2363             :           // sig from wt is inverse sqrt
    2364           0 :           newsig=1.0f/sqrt(newwt);
    2365             : 
    2366             :           // Arrange write-back of both SIGMA and WEIGHT
    2367           0 :           vb->setSigma(newsig);
    2368           0 :           vb->setWeight(newwt);
    2369             : 
    2370           0 :           break;
    2371           0 :         }
    2372             :         // Init WEIGHT from SIGMA 
    2373           0 :         case SIGMA: {
    2374             : 
    2375           0 :           Matrix<Float> newwt(ncor,nrow);
    2376           0 :           newwt.set(FLT_EPSILON);        // effectively zero, but strictly not zero
    2377             : 
    2378           0 :           Matrix<Float> sig;
    2379           0 :           sig.assign(vb->sigma());       // access existing SIGMA
    2380             : 
    2381           0 :           LogicalArray mask(sig==0.0f);  // mask out unphysical SIGMA
    2382           0 :           sig(mask)=1.0f;
    2383             : 
    2384           0 :           newwt=1.0f/square(sig);
    2385           0 :           newwt(mask)=FLT_EPSILON;       // effectively zero
    2386             : 
    2387             :           // Writeback WEIGHT
    2388           0 :           vb->setWeight(newwt);
    2389             :           
    2390           0 :           if (dowtsp) {
    2391           0 :             for (Int ich=0;ich<nchan;++ich) {
    2392           0 :               Matrix<Float> wtspi(newwtsp(Slice(),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(2,0,2)));
    2393           0 :               wtspi=newwt;
    2394           0 :             }
    2395             :           }
    2396             : 
    2397           0 :           break;
    2398           0 :         }
    2399             :         // Init WEIGHT_SPECTRUM from WEIGHT
    2400           0 :         case WEIGHT: {
    2401           0 :           const Matrix<Float> wt(vb->weight()); // access existing WEIGHT
    2402           0 :           for (Int ich=0;ich<nchan;++ich) {
    2403           0 :             Matrix<Float> wtspi(newwtsp(Slice(),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(2,0,2)));
    2404           0 :             wtspi=wt;
    2405           0 :           }
    2406           0 :           break;
    2407           0 :         } 
    2408           0 :         default: {
    2409           0 :           throw(AipsError("Problem in weight initialization loop."));
    2410             :         }
    2411             :         }
    2412             : 
    2413             :         // Force writeback to disk
    2414           0 :         vb->writeChangesBack();
    2415             :         
    2416             :         // Handle WEIGHT_SPECTRUM
    2417           0 :         if (dowtsp)
    2418           0 :           vb->initWeightSpectrum(newwtsp);
    2419             : 
    2420           0 :       }
    2421             :     }
    2422             : 
    2423           0 :   }
    2424           0 :   catch (AipsError x) {
    2425             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2426           0 :              << LogIO::POST;
    2427             : 
    2428           0 :     logSink() << "Resetting all calibration application settings." << LogIO::POST;
    2429           0 :     unsetapply();
    2430             : 
    2431           0 :     throw(AipsError("Error in Calibrater::initWeights."));
    2432             :     retval = false;  // Not that it ever gets here...
    2433           0 :   }
    2434           0 :   return retval;
    2435             : }
    2436             : 
    2437             : 
    2438           0 : Bool Calibrater::initWeights(Bool doBT, Bool dowtsp) {
    2439             : 
    2440           0 :   logSink() << LogOrigin("Calibrater","initWeights") << LogIO::NORMAL;
    2441           0 :   Bool retval = true;
    2442             : 
    2443             :   try {
    2444             : 
    2445           0 :     if (!ok())
    2446           0 :       throw(AipsError("Calibrater not prepared for initWeights!"));
    2447             : 
    2448             :     // Log that we are beginning...
    2449           0 :     if (doBT)
    2450           0 :       logSink() << "Initializing SIGMA and WEIGHT according to channel bandwidth and integration time." << LogIO::POST;
    2451             :     else
    2452           0 :       logSink() << "Initializing SIGMA and WEIGHT to unity." << LogIO::POST;
    2453             : 
    2454           0 :     if (dowtsp) {
    2455           0 :       logSink() << "Also initializing WEIGHT_SPECTRUM uniformly in channel (==WEIGHT)." << LogIO::POST;
    2456             : 
    2457             :       // Ensure WEIGHT_SPECTRUM really exists at all 
    2458             :       //   (often it exists but is empty)
    2459           0 :       TableDesc mstd = ms_p->actualTableDesc();
    2460           0 :       if (!mstd.isColumn("WEIGHT_SPECTRUM")) {
    2461           0 :         cout << "Creating WEIGHT_SPECTRUM!" << endl;
    2462             : 
    2463             :         // Nominal defaulttileshape
    2464           0 :         IPosition dts(3,4,32,1024); 
    2465             : 
    2466             :         // Discern DATA's default tile shape and use it
    2467           0 :         const Record dminfo=ms_p->dataManagerInfo();
    2468           0 :         for (uInt i=0;i<dminfo.nfields();++i) {
    2469           0 :           Record col=dminfo.asRecord(i);
    2470             :           //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    2471           0 :           if (anyEQ(col.asArrayString("COLUMNS"),String("DATA"))) {
    2472           0 :             dts=IPosition(col.asRecord("SPEC").asArrayInt("DEFAULTTILESHAPE"));
    2473           0 :             cout << "Found DATA's default tile: " << dts << endl;
    2474           0 :             break;
    2475             :           }
    2476           0 :         }
    2477             : 
    2478             :         // Add the column
    2479           0 :         String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
    2480           0 :         TableDesc tdWtSp;
    2481           0 :         tdWtSp.addColumn(ArrayColumnDesc<Float>(colWtSp,"weight spectrum", 2));
    2482           0 :         TiledShapeStMan wtSpStMan("TiledWgtSpectrum",dts);
    2483           0 :         ms_p->addColumn(tdWtSp,wtSpStMan);
    2484           0 :       }
    2485           0 :     }
    2486             : 
    2487             :     // Arrange for iteration over data
    2488           0 :     Block<Int> columns;
    2489             :     // include scan iteration
    2490           0 :     columns.resize(5);
    2491           0 :     columns[0]=MS::ARRAY_ID;
    2492           0 :     columns[1]=MS::SCAN_NUMBER;
    2493           0 :     columns[2]=MS::FIELD_ID;
    2494           0 :     columns[3]=MS::DATA_DESC_ID;
    2495           0 :     columns[4]=MS::TIME;
    2496             : 
    2497           0 :     vi::SortColumns sc(columns);
    2498           0 :     vi::VisibilityIterator2 vi2(*ms_p,sc,true);
    2499           0 :     vi::VisBuffer2 *vb = vi2.getVisBuffer();
    2500             : 
    2501           0 :     MSColumns mscol(*ms_p);
    2502           0 :     const MSSpWindowColumns& msspw(mscol.spectralWindow());
    2503           0 :     uInt nSpw=msspw.nrow();
    2504           0 :     Vector<Double> effChBw(nSpw,0.0);
    2505           0 :     for (uInt ispw=0;ispw<nSpw;++ispw) {
    2506           0 :       effChBw[ispw]=mean(msspw.effectiveBW()(ispw));
    2507             :     }
    2508             : 
    2509           0 :     Int ivb(0);
    2510           0 :     for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
    2511             : 
    2512           0 :       for (vi2.origin(); vi2.more(); vi2.next()) {
    2513             : 
    2514           0 :         Int spw = vb->spectralWindows()(0);
    2515             : 
    2516           0 :         auto nrow=vb->nRows();
    2517           0 :         Int nchan=vb->nChannels();
    2518           0 :         Int ncor=vb->nCorrelations();
    2519             : 
    2520           0 :         Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
    2521           0 :         newwt.set(1.0);
    2522           0 :         newsig.set(1.0);
    2523             : 
    2524           0 :         Cube<Float> newwtsp(0,0,0);
    2525           0 :         if (dowtsp) {
    2526           0 :           newwtsp.resize(ncor,nchan,nrow);
    2527           0 :           newwtsp.set(1.0);
    2528             :         }
    2529             : 
    2530             :         // If requested, set weights according to bandwidth and integration time
    2531           0 :         if (doBT) {
    2532             :           
    2533             :           // Detect ACs
    2534           0 :           const Vector<Int> a1(vb->antenna1());
    2535           0 :           const Vector<Int> a2(vb->antenna2());
    2536           0 :           Vector<Bool> ac(a1==a2);
    2537             :           
    2538             :           // XCs need an extra factor of 2
    2539           0 :           Vector<Float> xcfactor(nrow,2.0);
    2540           0 :           xcfactor(ac)=1.0;   // (but not ACs)
    2541             :           
    2542             :           // The row-wise integration time
    2543           0 :           Vector<Float> expo(nrow);
    2544           0 :           convertArray(expo,vb->exposure());
    2545             : 
    2546             :           // Set weights to channel bandwidth first.
    2547           0 :           newwt.set(Float(effChBw(spw)));
    2548             :           
    2549             :           // For each correlation, apply exposure and xcfactor
    2550           0 :           for (Int icor=0;icor<ncor;++icor) {
    2551             : 
    2552           0 :             Vector<Float> wt(newwt.row(icor));
    2553           0 :             wt*=expo;
    2554           0 :             wt*=xcfactor;
    2555           0 :             if (dowtsp) {
    2556           0 :               for (Int ich=0;ich<nchan;++ich) {
    2557           0 :                 Vector<Float> wtsp(newwtsp(Slice(icor,1,1),Slice(ich,1,1),Slice()));
    2558           0 :                 wtsp=wt;
    2559           0 :               }
    2560             :             }
    2561             :             
    2562           0 :           }
    2563             : 
    2564             :           // sig from wt is inverse sqrt
    2565           0 :           newsig=newsig/sqrt(newwt);
    2566             : 
    2567           0 :         }
    2568             : 
    2569             :         /*
    2570             :           cout << ivb << " "
    2571             :           << ncor << " " << nchan << " " << nrow << " "
    2572             :           << expo(0) << " "
    2573             :           << newwt(0,0) << " "
    2574             :           << newsig(0,0) << " "
    2575             :           << endl;
    2576             :         */
    2577           0 :         ++ivb;
    2578             : 
    2579             :         // Set in vb, and writeback
    2580           0 :         vb->setWeight(newwt);
    2581           0 :         vb->setSigma(newsig);
    2582           0 :         vb->writeChangesBack();
    2583             :         
    2584           0 :         if (dowtsp)
    2585           0 :           vb->initWeightSpectrum(newwtsp);
    2586             : 
    2587           0 :       }
    2588             :     }
    2589             : 
    2590           0 :   }
    2591           0 :   catch (AipsError x) {
    2592             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2593           0 :              << LogIO::POST;
    2594             : 
    2595           0 :     logSink() << "Resetting all calibration application settings." << LogIO::POST;
    2596           0 :     unsetapply();
    2597             : 
    2598           0 :     throw(AipsError("Error in Calibrater::initWeightsOLD."));
    2599             :     retval = false;  // Not that it ever gets here...
    2600           0 :   }
    2601           0 :   return retval;
    2602             : }
    2603             : 
    2604             : 
    2605          32 : Bool Calibrater::solve() {
    2606             : 
    2607          32 :   logSink() << LogOrigin("Calibrater","solve") << LogIO::NORMAL3;
    2608             : 
    2609             :   try {
    2610             : 
    2611          32 :     if (!ok()) 
    2612           0 :       throw(AipsError("Calibrater not prepared for solve."));
    2613             : 
    2614             :     // Handle nothing-to-solve-for case
    2615          32 :     if (!svc_p)
    2616           0 :       throw(AipsError("Please run setsolve before attempting to solve."));
    2617             : 
    2618             :     // Handle specified caltable
    2619          32 :     if (svc_p) {
    2620             : 
    2621             :       // If table exists (readable) and not deletable
    2622             :       //   we have to abort (append=T requires deletable)
    2623          46 :       if ( Table::isReadable(svc_p->calTableName()) &&
    2624          14 :            !TableUtil::canDeleteTable(svc_p->calTableName()) ) {
    2625           0 :         throw(AipsError("Specified caltable ("+svc_p->calTableName()+") exists and\n cannot be replaced (or appended to) because it appears to be open somewhere (Quit plotcal?)."));
    2626             :       }
    2627             :     }
    2628             : 
    2629             :     // Arrange VisEquation for solve
    2630          32 :     ve_p->setsolve(*svc_p);
    2631             : 
    2632             :     // Ensure apply list properly sorted w.r.t. solvable term
    2633          32 :     ve_p->setapply(vc_p);
    2634             : 
    2635             :     // Report what is being applied and solved-for
    2636          32 :     applystate();
    2637          32 :     solvestate();
    2638             : 
    2639             :     // Report correct/corrupt apply order
    2640             :     //    ve_p->state();
    2641             : 
    2642             :     // Generally use standard solver
    2643          32 :     if (svc_p->useGenericGatherForSolve())
    2644          32 :       genericGatherAndSolve();  // VI2-driven, SDBs
    2645             :     else {
    2646             :       //cout << "Fully self-directed data gather and solve" << endl;
    2647             :       // Fully self-directed data gather and solve
    2648           0 :       throw(AipsError("Can't do selfGatherAndSolve for "+svc_p->typeName()));
    2649             :       //svc_p->selfGatherAndSolve(*vs_p,*ve_p);
    2650             :     }
    2651             : 
    2652           1 :   } catch (AipsError x) {
    2653           1 :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
    2654             : 
    2655           1 :     logSink() << "Reseting entire solve/apply state." << LogIO::POST;
    2656           1 :     reset();
    2657             : 
    2658           1 :     throw(AipsError("Error in Calibrater::solve."));
    2659             :     return false;
    2660           2 :   } 
    2661             : 
    2662          31 :   return true;
    2663             : 
    2664             : }
    2665             : 
    2666             : 
    2667          31 : Bool Calibrater::summarize_uncalspws(const Vector<Bool>& uncalspw,
    2668             :                                      const String& origin,
    2669             :                                      Bool strictflag)
    2670             : {
    2671          31 :   Bool hadprob = false;
    2672          31 :   uInt totNspw = uncalspw.nelements();
    2673             : 
    2674         155 :   for(uInt i = 0; i < totNspw; ++i){
    2675         124 :     if(uncalspw[i]){
    2676           0 :       hadprob = true;
    2677           0 :       break;
    2678             :     }
    2679             :   }
    2680          31 :   if(hadprob){
    2681             :     logSink() << LogIO::WARN
    2682           0 :               << "Spectral window(s) ";
    2683           0 :     for(uInt i = 0; i < totNspw; ++i){
    2684           0 :       if(uncalspw[i]){
    2685           0 :         logSink() << i << ", ";
    2686             :       }
    2687             :     }
    2688             :     logSink() << "\n  could not be " << origin << "ed due to missing (pre-)calibration\n"
    2689           0 :               << "    in one or more of the specified tables.\n";
    2690           0 :     if (strictflag)
    2691           0 :       logSink() << "    These spws have been flagged!";
    2692             :     else
    2693           0 :       logSink() << "    Please check your results carefully!";
    2694             : 
    2695           0 :     logSink() << LogIO::POST;
    2696             :   }
    2697          31 :   return !hadprob;
    2698             : }
    2699             : 
    2700          29 : void Calibrater::fluxscale(const String& infile, 
    2701             :                            const String& outfile,
    2702             :                            const String& refFields, 
    2703             :                            const Vector<Int>& refSpwMap, 
    2704             :                            const String& tranFields,
    2705             :                            const Bool& append,
    2706             :                            const Float& inGainThres,
    2707             :                            const String& antSel,
    2708             :                            const String& timerangeSel,
    2709             :                            const String& scanSel,
    2710             :                            SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
    2711             :                            Vector<Int>& tranidx,
    2712             :                            const String& oListFile,
    2713             :                            const Bool& incremental,
    2714             :                            const Int& fitorder,
    2715             :                            const Bool& display) {
    2716             : 
    2717             :   // TBD:  Permit more flexible matching on specified field names
    2718             :   //  (Currently, exact matches are required.)
    2719             : 
    2720          29 :   logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
    2721             : 
    2722             :   //outfile check
    2723          29 :   if (outfile=="") 
    2724           0 :     throw(AipsError("output fluxscaled caltable name must be specified!"));
    2725             :   else {
    2726          29 :     if (File(outfile).exists() && !append) 
    2727           0 :       throw(AipsError("output caltable name, "+outfile+" exists. Please specify a different caltable name"));
    2728             :   }
    2729             : 
    2730             :   // Convert refFields/transFields to index lists
    2731          29 :   Vector<Int> refidx(0);
    2732             : 
    2733          29 :   if (refFields.length()>0)
    2734          29 :     refidx=getFieldIdx(refFields);
    2735             :   else
    2736           0 :     throw(AipsError("A reference field must be specified!"));
    2737             : 
    2738          29 :   if (tranFields.length()>0)
    2739          12 :     tranidx=getFieldIdx(tranFields);
    2740             : 
    2741             :   // Call Vector<Int> version:
    2742          29 :   fluxscale(infile,outfile,refidx,refSpwMap,tranidx,append,inGainThres,antSel,timerangeSel,
    2743             :       scanSel,oFluxScaleFactor,oListFile,incremental,fitorder,display);
    2744             : 
    2745          29 : }
    2746             : 
    2747          29 : void Calibrater::fluxscale(const String& infile, 
    2748             :                            const String& outfile,
    2749             :                            const Vector<Int>& refField, 
    2750             :                            const Vector<Int>& refSpwMap, 
    2751             :                            const Vector<Int>& tranField,
    2752             :                            const Bool& append,
    2753             :                            const Float& inGainThres,
    2754             :                            const String& antSel,
    2755             :                            const String& timerangeSel,
    2756             :                            const String& scanSel,
    2757             :                            SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
    2758             :                            const String& oListFile,
    2759             :                            const Bool& incremental,
    2760             :                            const Int& fitorder,
    2761             :                            const Bool& display) {
    2762             :   
    2763             :   //  throw(AipsError("Method 'fluxscale' is temporarily disabled."));
    2764             : 
    2765             :   // TBD: write inputs to MSHistory
    2766          29 :   logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
    2767             : 
    2768          29 :   SolvableVisCal *fsvj_(NULL);
    2769             :   try {
    2770             :     // If infile is Calibration table
    2771          58 :     if (Table::isReadable(infile) && 
    2772          58 :         TableUtil::tableInfo(infile).type()=="Calibration") {
    2773             : 
    2774             :       // get calibration type
    2775          29 :       String caltype;
    2776          29 :       caltype = TableUtil::tableInfo(infile).subType();
    2777             :       logSink() << "Table " << infile 
    2778             :                 << " is of type: "<< caltype 
    2779          29 :                 << LogIO::POST;
    2780          58 :       String message="Table "+infile+" is of type: "+caltype;
    2781          29 :       MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    2782             :       
    2783             :       // form selection
    2784          29 :       String select="";
    2785             :       // Selection is empty for case of no tran specification
    2786          29 :       if (tranField.nelements()>0) {
    2787             :         
    2788             :         // All selected fields
    2789          12 :         Vector<Int> allflds = concatenateArray(refField,tranField);
    2790             :         
    2791             :         // Assemble TaQL
    2792          12 :         ostringstream selectstr;
    2793          12 :         selectstr << "FIELD_ID IN [";
    2794          42 :         for (Int iFld=0; iFld<allflds.shape(); iFld++) {
    2795          30 :           if (iFld>0) selectstr << ", ";
    2796          30 :           selectstr << allflds(iFld);
    2797             :         }
    2798          12 :         selectstr << "]";
    2799          12 :         select=selectstr.str();
    2800          12 :       }
    2801             : 
    2802             :       // Construct proper SVC object
    2803          29 :       if (caltype == "G Jones") {
    2804          29 :         fsvj_ = createSolvableVisCal("G",*msmc_p);
    2805           0 :       } else if (caltype == "T Jones") {
    2806           0 :         fsvj_ = createSolvableVisCal("T",*msmc_p);
    2807             :       } else {
    2808             :         // Can't process other than G and T (add B?)
    2809           0 :         ostringstream typeErr;
    2810           0 :         typeErr << "Type " << caltype 
    2811           0 :                << " not supported in fluxscale.";
    2812             : 
    2813           0 :         throw(AipsError(typeErr.str()));
    2814           0 :       }
    2815             : 
    2816             :       // fill table with selection
    2817          29 :       RecordDesc applyparDesc;
    2818          29 :       applyparDesc.addField ("table", TpString);
    2819          29 :       applyparDesc.addField ("select", TpString);
    2820          29 :       Record applypar(applyparDesc);
    2821          29 :       applypar.define ("table", infile);
    2822          29 :       applypar.define ("select", select);
    2823          29 :       fsvj_->setApply(applypar);
    2824             : 
    2825             :       //Bool incremental=false;
    2826             :       // Make fluxscale calculation
    2827          29 :       Vector<String> fldnames(MSFieldColumns(ms_p->field()).name().getColumn());
    2828             :       //fsvj_->fluxscale(refField,tranField,refSpwMap,fldnames,oFluxScaleFactor,
    2829          29 :       fsvj_->fluxscale(outfile,refField,tranField,refSpwMap,fldnames,inGainThres,antSel,
    2830             :         timerangeSel,scanSel,oFluxScaleFactor, oListFile,incremental,fitorder,display);
    2831             : //        oListFile);
    2832             :      
    2833             :       // If no outfile specified, use infile (overwrite!)
    2834          29 :       String out(outfile);
    2835          29 :       if (out.length()==0)
    2836           0 :         out = infile;
    2837             : 
    2838             :       // Store result
    2839          29 :       if (append) {
    2840           1 :         logSink() << "Appending result to " << out << LogIO::POST;
    2841           1 :         String message="Appending result to "+out;
    2842           1 :         MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    2843           1 :       } else {
    2844          28 :         logSink() << "Storing result in " << out << LogIO::POST;
    2845          28 :         String message="Storing result in "+out;
    2846          28 :         MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    2847          28 :       }
    2848          29 :       fsvj_->storeNCT(out,append);
    2849             :       
    2850             :       // Clean up
    2851          29 :       delete fsvj_;
    2852             : 
    2853          29 :     } else {
    2854             :       // Table not found/unreadable, or not Calibration
    2855           0 :       ostringstream tabErr;
    2856           0 :       tabErr << "File " << infile
    2857           0 :              << " does not exist or is not a Calibration Table.";
    2858             : 
    2859           0 :       throw(AipsError(tabErr.str()));
    2860             : 
    2861           0 :     }
    2862           0 :   } catch (AipsError x) {
    2863             : 
    2864             :     logSink() << LogIO::SEVERE
    2865             :               << "Caught Exception: "
    2866             :               << x.getMesg()
    2867           0 :               << LogIO::POST;
    2868             :     
    2869             :     // Clean up
    2870           0 :     if (fsvj_) delete fsvj_;
    2871             : 
    2872             :     // Write to MS History table
    2873             :     //    String message="Caught Exception: "+x.getMesg();
    2874             :     //    MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    2875             : 
    2876           0 :     throw(AipsError("Error in Calibrater::fluxscale."));
    2877             : 
    2878             :     return;
    2879             : 
    2880           0 :   }
    2881          29 :   return;
    2882             : 
    2883             : 
    2884             : }
    2885             : 
    2886           0 : void Calibrater::specifycal(const String& type,
    2887             :                             const String& caltable,
    2888             :                             const String& time,
    2889             :                             const String& spw,
    2890             :                             const String& antenna,
    2891             :                             const String& pol,
    2892             :                             const Vector<Double>& parameter,
    2893             :                             const String& infile,
    2894             :                             const Bool& uniform) {
    2895             : 
    2896           0 :   logSink() << LogOrigin("Calibrater","specifycal") << LogIO::NORMAL;
    2897             : 
    2898             :   // SVJ objects:
    2899           0 :   SolvableVisCal *cal_(NULL);
    2900             : 
    2901             :   try {
    2902             :                             
    2903             :     // Set record format for calibration table application information
    2904           0 :     RecordDesc specifyDesc;
    2905           0 :     specifyDesc.addField ("caltable", TpString);
    2906           0 :     specifyDesc.addField ("time", TpString);
    2907           0 :     specifyDesc.addField ("spw", TpArrayInt);
    2908           0 :     specifyDesc.addField ("antenna", TpArrayInt);
    2909           0 :     specifyDesc.addField ("pol", TpString);
    2910           0 :     specifyDesc.addField ("parameter", TpArrayDouble);
    2911           0 :     specifyDesc.addField ("caltype",TpString);
    2912           0 :     specifyDesc.addField ("infile",TpString);
    2913           0 :     specifyDesc.addField ("uniform",TpBool);
    2914             : 
    2915             :     // Create record with the requisite field values
    2916           0 :     Record specify(specifyDesc);
    2917           0 :     specify.define ("caltable", caltable);
    2918           0 :     specify.define ("time", time);
    2919           0 :     if (spw=="*")
    2920           0 :       specify.define ("spw",Vector<Int>(1,-1));
    2921             :     else
    2922           0 :       specify.define ("spw",getSpwIdx(spw));
    2923           0 :     if (antenna=="*")
    2924           0 :       specify.define ("antenna",Vector<Int>(1,-1) );
    2925             :     else
    2926           0 :       specify.define ("antenna",getAntIdx(antenna));
    2927           0 :     specify.define ("pol",pol);
    2928           0 :     specify.define ("parameter",parameter);
    2929           0 :     specify.define ("caltype",type);
    2930           0 :     specify.define ("infile",infile);
    2931           0 :     specify.define ("uniform",uniform);
    2932             : 
    2933             :     // Now do it
    2934           0 :     String utype=upcase(type);
    2935           0 :     if (utype=="G" || utype.contains("AMP") || utype.contains("PH"))
    2936           0 :       cal_ = createSolvableVisCal("G",*msmc_p);
    2937           0 :     else if (utype=='K' || utype.contains("SBD") || utype.contains("DELAY"))
    2938           0 :       cal_ = createSolvableVisCal("K",*msmc_p);
    2939           0 :     else if (utype.contains("MBD"))
    2940           0 :       cal_ = createSolvableVisCal("K",*msmc_p);  // As of 5.3, MBD is ordinary K
    2941           0 :     else if (utype.contains("ANTPOS"))
    2942           0 :       cal_ = createSolvableVisCal("KANTPOS",*msmc_p);
    2943           0 :     else if (utype.contains("TSYS"))
    2944           0 :       cal_ = createSolvableVisCal("TSYS",*msmc_p);
    2945           0 :     else if (utype.contains("EVLAGAIN") ||
    2946           0 :              utype.contains("SWP") ||
    2947           0 :              utype.contains("RQ") ||
    2948           0 :          utype.contains("WTS"))
    2949           0 :       cal_ = createSolvableVisCal("EVLASWP",*msmc_p);
    2950           0 :     else if (utype.contains("OPAC"))
    2951           0 :       cal_ = createSolvableVisCal("TOPAC",*msmc_p);
    2952           0 :     else if (utype.contains("GC") && ms_p && ms_p->keywordSet().isDefined("GAIN_CURVE"))
    2953           0 :       cal_ = createSolvableVisCal("POWERCURVE",*msmc_p);
    2954           0 :     else if (utype.contains("GC") || utype.contains("EFF"))
    2955           0 :       cal_ = createSolvableVisCal("GAINCURVE",*msmc_p);
    2956           0 :     else if (utype.contains("TEC"))
    2957           0 :       cal_ = createSolvableVisCal("TEC",*msmc_p);
    2958           0 :     else if (utype.contains("SDSKY_PS"))
    2959           0 :       cal_ = createSolvableVisCal("SDSKY_PS",*msmc_p);
    2960           0 :     else if (utype.contains("SDSKY_RASTER"))
    2961           0 :       cal_ = createSolvableVisCal("SDSKY_RASTER",*msmc_p);
    2962           0 :     else if (utype.contains("SDSKY_OTF"))
    2963           0 :       cal_ = createSolvableVisCal("SDSKY_OTF",*msmc_p);
    2964             :     else
    2965           0 :       throw(AipsError("Unrecognized caltype."));
    2966             : 
    2967             :     // set up for specification (set up the CalSet)
    2968           0 :     cal_->setSpecify(specify);
    2969             : 
    2970             :     // fill with specified values
    2971           0 :     cal_->specify(specify);
    2972             : 
    2973             :     // Store result
    2974           0 :     cal_->storeNCT();
    2975             : 
    2976           0 :     delete cal_;
    2977             : 
    2978           0 :   } catch (AipsError x) {
    2979             :     logSink() << LogIO::SEVERE
    2980             :               << "Caught Exception: "
    2981             :               << x.getMesg()
    2982           0 :               << LogIO::POST;
    2983             : 
    2984           0 :     if (cal_) delete cal_;
    2985             :     
    2986           0 :     throw(AipsError("Error in Calibrater::specifycal."));
    2987             :     return;
    2988           0 :   }
    2989           0 :   return;
    2990             : 
    2991             : }
    2992             : 
    2993             : 
    2994           0 : Bool Calibrater::smooth(const String& infile, 
    2995             :                         String& outfile,  // const Bool& append,
    2996             :                         const String& smoothtype,
    2997             :                         const Double& smoothtime,
    2998             :                         const String& fields,
    2999             :       const bool ratesmooth)
    3000             : {
    3001             : 
    3002             :   // TBD: support append?
    3003             :   // TBD: spw selection?
    3004             : 
    3005           0 :   logSink() << LogOrigin("Calibrater","smooth") << LogIO::NORMAL;
    3006             : 
    3007           0 :   logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
    3008             : 
    3009             : 
    3010             :   // A pointer to an SVC
    3011           0 :   SolvableVisCal *svc(NULL);
    3012             : 
    3013             :   try {
    3014             :     
    3015             :     // Handle no in file 
    3016           0 :     if (infile=="")
    3017           0 :       throw(AipsError("Please specify an input calibration table."));
    3018             : 
    3019             :     // Handle bad smoothtype
    3020           0 :     if (smoothtype!="mean" && smoothtype!="median")
    3021           0 :       throw(AipsError("Unrecognized smooth type!"));
    3022             : 
    3023             :     // Handle bad smoothtime
    3024           0 :     if (smoothtime<=0)
    3025           0 :       throw(AipsError("Please specify a strictly positive smoothtime."));
    3026             : 
    3027             :     // Handle no outfile
    3028           0 :     if (outfile=="") {
    3029           0 :       outfile=infile;
    3030             :       logSink() << "Will overwrite input file with smoothing result." 
    3031           0 :                 << LogIO::POST;
    3032             :     }
    3033             : 
    3034             : 
    3035           0 :     svc = createSolvableVisCal(calTableType(infile),*msmc_p);
    3036             :     
    3037           0 :     if (svc->smoothable()) {
    3038             :       
    3039             :       // Fill calibration table using setApply
    3040           0 :       RecordDesc applyparDesc;
    3041           0 :       applyparDesc.addField ("table", TpString);
    3042           0 :       Record applypar(applyparDesc);
    3043           0 :       applypar.define ("table", infile);
    3044           0 :       svc->setApply(applypar);
    3045             : 
    3046             :       // Convert refFields/transFields to index lists
    3047           0 :       Vector<Int> fldidx(0);
    3048           0 :       if (fields.length()>0)
    3049           0 :         fldidx=getFieldIdx(fields);
    3050             : 
    3051             :       // Delegate to SVC
    3052           0 :       svc->smooth(fldidx,smoothtype,smoothtime,ratesmooth);
    3053             :       
    3054             :       // Store the result on disk
    3055             :       //    if (append) logSink() << "Appending result to " << outfile << LogIO::POST;
    3056             :       //else 
    3057           0 :       logSink() << "Storing result in " << outfile << LogIO::POST;
    3058             :       
    3059             :       
    3060           0 :       if (outfile != "") 
    3061           0 :         svc->calTableName()=outfile;
    3062           0 :       svc->storeNCT();
    3063             : 
    3064             :       // Clean up
    3065           0 :       if (svc) delete svc; svc=NULL;
    3066             :       
    3067             :       // Apparently, it worked
    3068           0 :       return true;
    3069             : 
    3070           0 :     }
    3071             :     else
    3072           0 :       throw(AipsError("This type ("+svc->typeName()+") does not support smoothing."));
    3073             : 
    3074           0 :   } catch (AipsError x) {
    3075             :    
    3076             :     logSink() << LogIO::SEVERE
    3077             :               << "Caught Exception: "
    3078             :               << x.getMesg()
    3079           0 :               << LogIO::POST;
    3080             :     // Clean up
    3081           0 :     if (svc) delete svc; svc=NULL;
    3082             : 
    3083           0 :     throw(AipsError("Error in Calibrater::smooth."));
    3084             : 
    3085             :     return false;
    3086           0 :   }
    3087             :   return false;
    3088             : }
    3089             : 
    3090             : // Apply new reference antenna to calibration
    3091           0 : Bool Calibrater::reRefant(const casacore::String& infile,
    3092             :                           casacore::String& outfile, 
    3093             :                           const casacore::String& refantmode, 
    3094             :                           const casacore::String& refant)
    3095             : {
    3096             : 
    3097           0 :   logSink() << LogOrigin("Calibrater","reRefant") << LogIO::NORMAL;
    3098             : 
    3099             :   //  logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
    3100             : 
    3101             : 
    3102             :   // A pointer to an SVC
    3103           0 :   SolvableVisJones *svj(NULL);
    3104             : 
    3105             :   try {
    3106             :     
    3107             :     // Handle no in file 
    3108           0 :     if (infile=="")
    3109           0 :       throw(AipsError("Please specify an input calibration table."));
    3110             : 
    3111             :     // Handle bad refantmode
    3112           0 :     if (refantmode!="strict" && 
    3113           0 :         refantmode!="flex")
    3114           0 :       throw(AipsError("Unrecognized refantmode!"));
    3115             : 
    3116             :     // Handle no outfile
    3117           0 :     if (outfile=="") {
    3118           0 :       outfile=infile;
    3119             :       logSink() << "Will overwrite input file with rerefant result."
    3120           0 :                 << LogIO::POST;
    3121             :     }
    3122             : 
    3123             : 
    3124           0 :     svj = (SolvableVisJones*) createSolvableVisCal(calTableType(infile),*msmc_p);
    3125             :     
    3126             :     // Fill calibration table using setApply
    3127           0 :     RecordDesc applyparDesc;
    3128           0 :     applyparDesc.addField ("table", TpString);
    3129           0 :     Record applypar(applyparDesc);
    3130           0 :     applypar.define ("table", infile);
    3131           0 :     svj->setApply(applypar);
    3132             : 
    3133             :     // Do the work
    3134           0 :     svj->refantmode() = refantmode;
    3135           0 :     svj->refantlist().reference(getRefantIdxList(refant));   // replaces the default list
    3136           0 :     svj->applyRefAnt();
    3137             : 
    3138             :     // Store the result on disk
    3139           0 :     logSink() << "Storing result in " << outfile << LogIO::POST;
    3140             :       
    3141           0 :     if (outfile != "") 
    3142           0 :       svj->calTableName()=outfile;
    3143           0 :     svj->storeNCT();
    3144             : 
    3145             :     // Clean up
    3146           0 :     if (svj) delete svj; svj=NULL;
    3147             :       
    3148             :     // Apparently, it worked
    3149           0 :     return true;
    3150             : 
    3151           0 :   } catch (AipsError x) {
    3152             :    
    3153             :     logSink() << LogIO::SEVERE
    3154             :               << "Caught Exception: "
    3155             :               << x.getMesg()
    3156           0 :               << LogIO::POST;
    3157             :     // Clean up
    3158           0 :     if (svj) delete svj; svj=NULL;
    3159             : 
    3160           0 :     throw(AipsError("Error in Calibrater::reRefant."));
    3161             :     
    3162             :     return false;
    3163           0 :   }
    3164             :   return false;
    3165             : }
    3166             : 
    3167             : 
    3168             : // List a calibration table
    3169           0 : Bool Calibrater::listCal(const String& infile,
    3170             :                          const String& field,
    3171             :                          const String& antenna,
    3172             :                          const String& spw,
    3173             :                          const String& listfile,
    3174             :                          const Int& pagerows) {
    3175             :     
    3176           0 :     SolvableVisCal *svc(NULL);
    3177           0 :     logSink() << LogOrigin("Calibrater","listCal");
    3178             :     
    3179             :     try {
    3180             :         
    3181             :         // Trap (currently) unsupported types
    3182           0 :         if (upcase(calTableType(infile))=="GSPLINE" ||
    3183           0 :             upcase(calTableType(infile))=="BPOLY")
    3184           0 :             throw(AipsError("GSPLINE and BPOLY tables cannot currently be listed."));
    3185             :         
    3186             :         // Get user's selected fields, ants
    3187           0 :         Vector<Int> ufldids=getFieldIdx(field);
    3188           0 :         Vector<Int> uantids=getAntIdx(antenna);
    3189             :         
    3190           0 :         String newSpw = spw;
    3191           0 :         Bool defaultSelect = false;
    3192           0 :         if (spw.empty()) { // list all channels (default)
    3193           0 :             defaultSelect = true;
    3194           0 :             newSpw = "*"; 
    3195             :             logSink() << LogIO::NORMAL1 << "Spws selected: ALL" << endl
    3196           0 :                       << "Channels selected: ALL" << LogIO::POST;
    3197             :         }
    3198             :         // Get user's selected spw and channels
    3199           0 :         Vector<Int> uspwids=getSpwIdx(newSpw);
    3200           0 :         Matrix<Int> uchanids=getChanIdx(newSpw);
    3201           0 :         if (!defaultSelect) {
    3202             :             logSink() << LogIO::NORMAL1 << "Spw and Channel selection matrix: "
    3203             :                       << endl << "Each rows shows: [ Spw , Start Chan , Stop Chan , Chan Step ]"
    3204           0 :                       << endl << uchanids << LogIO::POST;
    3205             :         }
    3206             :         logSink() << LogIO::DEBUG2 
    3207             :                   << "uspwids = "  << uspwids  << endl
    3208           0 :                   << "uchanids = " << uchanids << LogIO::POST;
    3209             :         
    3210             :         // By default, do first spw, first chan
    3211           0 :         if (uspwids.nelements()==0) {
    3212           0 :             uchanids.resize(1,4);
    3213           0 :             uchanids=0;
    3214             :         } 
    3215             :         
    3216             :         // Set record format for calibration table application information
    3217           0 :         RecordDesc applyparDesc;
    3218           0 :         applyparDesc.addField ("table", TpString);
    3219             :         
    3220             :         // Create record with the requisite field values
    3221           0 :         Record applypar(applyparDesc);
    3222           0 :         applypar.define ("table", infile);
    3223             :         
    3224             :         // Generate the VisCal to be listed
    3225           0 :         svc = createSolvableVisCal(calTableType(infile),*msmc_p);  
    3226           0 :         svc->setApply(applypar);       
    3227             :         
    3228             :         // list it
    3229           0 :         svc->listCal(ufldids,uantids,uchanids,  //uchanids(0,0),uchanids(0,1),
    3230             :                      listfile,pagerows);
    3231             :         
    3232           0 :         if (svc) delete svc; svc=NULL;
    3233             :         
    3234           0 :         return true;
    3235             :         
    3236           0 :     } catch (AipsError x) {
    3237             :         
    3238             :         logSink() << LogIO::SEVERE
    3239             :                   << "Caught Exception: "
    3240             :                   << x.getMesg()
    3241           0 :                   << LogIO::POST;
    3242             :         // Clean up
    3243           0 :         if (svc) delete svc; svc=NULL;
    3244             :         
    3245           0 :         throw(AipsError("Error in Calibrater::listCal."));
    3246             :         
    3247             :         return false;
    3248           0 :     }
    3249             :     return false;
    3250             :     
    3251             : }
    3252             : 
    3253             : 
    3254             : 
    3255           0 : Bool Calibrater::updateCalTable(const String& caltable) {
    3256             : 
    3257             :   // Call the SVC method that knows how
    3258           0 :   return NewCalTable::CTBackCompat(caltable);
    3259             : 
    3260             : }
    3261             : 
    3262          32 : void Calibrater::selectChannel(const String& spw) {
    3263             : 
    3264          32 :   if (mss_p && mssel_p) {
    3265             : 
    3266             :     // Refresh the frequencySelections object to feed to VI2, if relevant
    3267          32 :     frequencySelections_p.reset(new vi::FrequencySelections());
    3268             : 
    3269          32 :     vi::FrequencySelectionUsingChannels usingChannels;
    3270          32 :     usingChannels.add(*mss_p,mssel_p);
    3271          32 :     frequencySelections_p->add(usingChannels);
    3272             : 
    3273             :     //    cout << usingChannels.toString() << endl;
    3274             :     //    cout << "FS.size() = " << frequencySelections_p->size() << endl;
    3275             : 
    3276          32 :   }
    3277             : 
    3278             :   // TBD:  Does frequencySelections_p support string info for reporting to logger?
    3279             : 
    3280          32 :   Matrix<Int> chansel = getChanIdx(spw);
    3281          32 :   uInt nselspw=chansel.nrow();
    3282             : 
    3283          32 :   if (nselspw==0)
    3284             :     logSink() << "Frequency selection: Selecting all channels in all spws." 
    3285          19 :               << LogIO::POST;
    3286             :   else {
    3287             : 
    3288          13 :     logSink() << "Frequency selection: " << LogIO::POST;
    3289             : 
    3290             :     // Trap non-unit step (for now)
    3291          13 :     if (ntrue(chansel.column(3)==1)!=nselspw) {
    3292             :       logSink() << LogIO::WARN
    3293             :                 << "Calibration does not support non-unit channel stepping; "
    3294             :                 << "using step=1."
    3295           0 :                 << LogIO::POST;
    3296           0 :       chansel.column(3)=1;
    3297             :     }
    3298             : 
    3299          13 :     Vector<Int> uspw(chansel.column(0));
    3300          13 :     Vector<Int> ustart(chansel.column(1));
    3301          13 :     Vector<Int> uend(chansel.column(2));
    3302          13 :     Vector<Int> ustep(chansel.column(3));
    3303             : 
    3304          13 :     logSink() << LogIO::NORMAL;
    3305          47 :     for (uInt i=0;i<nselspw;++i) {
    3306             : 
    3307          68 :       logSink() << ".  Spw " << uspw(i) << ":"
    3308         136 :                 << ustart(i) << "~" << uend(i) 
    3309          34 :                 << " (" << uend(i)-ustart(i)+1 << " channels,"
    3310          68 :                 << " step by " << ustep(i) << ")"
    3311          68 :                 << endl;
    3312             :         
    3313             :     } // i
    3314          13 :     logSink() << LogIO::POST;
    3315             : 
    3316          13 :   } // non-triv spw selection
    3317             : 
    3318          32 : }
    3319             : 
    3320             : 
    3321         242 : Bool Calibrater::cleanup() {
    3322             : 
    3323             :   //  logSink() << LogOrigin("Calibrater","cleanup") << LogIO::NORMAL;
    3324             : 
    3325             :   // Delete the VisCals
    3326         242 :   reset();
    3327             : 
    3328             :   // Delete derived dataset stuff
    3329         242 :   if(mssel_p) delete mssel_p; mssel_p=0;
    3330         242 :   if(mss_p) delete mss_p; mss_p=0;
    3331         242 :   frequencySelections_p.reset();
    3332             : 
    3333             :   // Delete the current VisEquation
    3334         242 :   if(ve_p) delete ve_p; ve_p=0;
    3335             : 
    3336         242 :   return true;
    3337             : 
    3338             : }
    3339             : 
    3340             : // Parse refant specification
    3341          32 : Vector<Int> Calibrater::getRefantIdxList(const String& refant) {
    3342             : 
    3343          32 :   Vector<Int> irefant;
    3344          32 :   if (refant.length()==0) {
    3345             :     // Nothing specified, return -1 in single-element vector
    3346           0 :     irefant.resize(1);
    3347           0 :     irefant(0)=-1;
    3348             :   }
    3349             :   else {
    3350             :     // parse the specification
    3351          32 :     MSSelection msselect;
    3352          32 :     msselect.setAntennaExpr(refant);
    3353          32 :     Vector<Int> iref=msselect.getAntenna1List(mssel_p);
    3354          32 :     if (anyLT(iref,0))
    3355           0 :       cout << "Negated selection (via '!') not yet implemented for refant," << endl << " and will be ignored." << endl;
    3356          32 :     irefant=iref(iref>-1).getCompressedArray();
    3357          32 :     if (irefant.nelements()==0) {
    3358           0 :       irefant.resize(1);
    3359           0 :       irefant(0)=-1;
    3360             :     }
    3361          32 :   }
    3362             : 
    3363          32 :   return irefant;
    3364           0 : }
    3365             : 
    3366             : 
    3367             : // Interpret refant *index*
    3368           0 : Vector<Int> Calibrater::getAntIdx(const String& antenna) {
    3369             : 
    3370           0 :     MSSelection msselect;
    3371           0 :     msselect.setAntennaExpr(antenna);
    3372           0 :     return msselect.getAntenna1List(mssel_p);
    3373             : 
    3374           0 : }
    3375             : 
    3376             : // Interpret field indices (MSSelection)
    3377          41 : Vector<Int> Calibrater::getFieldIdx(const String& fields) {
    3378             : 
    3379          41 :   MSSelection mssel;
    3380          41 :   mssel.setFieldExpr(fields);
    3381          82 :   return mssel.getFieldList(mssel_p);
    3382             : 
    3383          41 : }
    3384             : 
    3385             : // Interpret spw indices (MSSelection)
    3386           7 : Vector<Int> Calibrater::getSpwIdx(const String& spws) {
    3387             : 
    3388           7 :   MSSelection mssel;
    3389           7 :   mssel.setSpwExpr(spws);
    3390             : 
    3391             :   /*
    3392             :   cout << "mssel.getSpwList(mssel_p) = " << mssel.getSpwList(mssel_p) << endl;
    3393             :   cout << "mssel.getChanList(mssel_p) = " << mssel.getChanList(mssel_p) << endl;  cout << "Vector<Int>() = " << Vector<Int>() << endl;
    3394             :   */
    3395             : 
    3396             :   // Use getChanList (column 0 for spw) because it is 
    3397             :   //  more reliable about the number and order of specified spws.
    3398             :   //  return mssel.getSpwList(mssel_p);
    3399           7 :   Matrix<Int> chanmat=mssel.getChanList(mssel_p);
    3400           7 :   if (chanmat.nelements()>0) 
    3401           0 :     return chanmat.column(0);
    3402             :   else
    3403           7 :     return Vector<Int>();
    3404             : 
    3405           7 : }
    3406             : 
    3407          32 : Matrix<Int> Calibrater::getChanIdx(const String& spw) {
    3408             : 
    3409          32 :   MSSelection mssel;
    3410          32 :   mssel.setSpwExpr(spw);
    3411             : 
    3412          64 :   return mssel.getChanList(mssel_p);
    3413             : 
    3414          32 : }
    3415             : 
    3416             : 
    3417             : // Query apply types if we are calibrating the weights
    3418           0 : Bool Calibrater::calWt() {
    3419             : 
    3420           0 :   Int napp(vc_p.nelements());
    3421             :   // Return true as soon as we find a type which is cal'ing wts
    3422           0 :   for (Int iapp=0;iapp<napp;++iapp)
    3423           0 :     if (vc_p[iapp] && vc_p[iapp]->calWt())
    3424           0 :       return true;
    3425             : 
    3426             :   // None cal'd weights, so return false
    3427           0 :   return false;
    3428             : 
    3429             : }
    3430             : 
    3431          71 : Bool Calibrater::ok() {
    3432             : 
    3433          71 :   if ((simdata_p || 
    3434          71 :        (ms_p && mssel_p))
    3435          71 :       && ve_p) {
    3436          71 :     return true;
    3437             :   }
    3438             :   else {
    3439           0 :     logSink() << "Calibrater is not yet initialized" << LogIO::POST;
    3440           0 :     return false;
    3441             :   }
    3442             : }
    3443             : // The standard solving mechanism
    3444          32 : casacore::Bool Calibrater::genericGatherAndSolve()  
    3445             : {
    3446             : 
    3447             : #ifdef _OPENMP
    3448          32 :   Double Tsetup(0.0),Tgather(0.0),Tsolve(0.0),Tadd(0.0);
    3449          32 :   Double time0=omp_get_wtime();
    3450             : #endif
    3451             : 
    3452             :   // Create record to store results
    3453          32 :   resRec_ = Record();
    3454          32 :   Record attemptRec;
    3455          32 :   attemptRec = Record();
    3456             :     
    3457             :   // Condition solint values 
    3458          32 :   svc_p->reParseSolintForVI2();
    3459             : 
    3460             :   // Organize VI2 layers for solving:
    3461          32 :   CalSolVi2Organizer vi2org;
    3462             : 
    3463             :   //-------------------------------------------------
    3464             :   //  NB: Populating the vi2org should probably be delegated to the svc_p
    3465             :   //      since that is where most of the required (non-data) info is,
    3466             :   //      and then some calibration types may introduce layers that are
    3467             :   //      very specific to them (e.g., SD data selection, etc.)
    3468             :   //  e.g., replace the following with something like:
    3469             :   //
    3470             :   //  svc_p->formVi2LayerFactories(vi2org,mssel_p,ve_p);
    3471             :   //                                      ssvp_p          // a simdata version
    3472             :   //
    3473             : 
    3474             :   // Add the (bottom) data access layer
    3475          32 :   if (simdata_p)
    3476             :     // Simulated data (used for testing)
    3477           0 :     vi2org.addSimIO(ssvp_p);
    3478             :   else
    3479             :   {
    3480             :     // Real (selected) data in an MS (channel selection handled by addDiskIO method)
    3481             :     //   The iteration time-interval is the solution interval
    3482          32 :     vi2org.addDiskIO(mssel_p,svc_p->solTimeInterval(),
    3483          32 :                      svc_p->combobs(),svc_p->combscan(),
    3484          32 :                      svc_p->combfld(),svc_p->combspw(),
    3485             :                      true,     // use MSIter2
    3486          32 :                      frequencySelections_p);  // Tell VI2 factory about the freq selection!
    3487             :   }
    3488             : 
    3489             :   // Add ad hoc SD section layer (e.g., OTF select of raster boundaries, etc.)
    3490             :   // only double circle gain calibration is implemented
    3491          32 :   bool SD = svc_p->longTypeName().startsWith("SDGAIN_OTFD");
    3492          32 :   if (SD) {
    3493           0 :     vi2org.addCalFilter(calFilterConfig_p);
    3494             :   }
    3495             : 
    3496             :   // Add pre-cal layer, using the VisEquation
    3497             :   //  (include control for corr-dep flags)
    3498          32 :   vi2org.addCalForSolving(*ve_p,corrDepFlags_);
    3499             : 
    3500             : 
    3501             :   // Add the freq-averaging layer, if needed
    3502             :   //cout << "svc_p->fintervalChV() = " << svc_p->fintervalChV() << endl;                                                    
    3503             :   //cout << "svc_p->fsolint() = " << svc_p->fsolint() << endl;
    3504             :   // TBD: improve the following logic with new method in SVC...
    3505          64 :   if (!svc_p->freqDepMat() ||       // entirely unchannelized cal  OR
    3506          32 :       (svc_p->freqDepPar() &&            // channelized par and
    3507           0 :        svc_p->fsolint()!="none" &&       // some partial channel averaging
    3508          32 :        anyGT(svc_p->fintervalChV(),1.0)) // explicity specified (non-trivially)
    3509             :       ) { 
    3510           0 :     Vector<Int> chanbin(svc_p->fintervalChV().nelements());
    3511           0 :     convertArray(chanbin,svc_p->fintervalChV());
    3512           0 :     vi2org.addChanAve(chanbin);  
    3513           0 :   }
    3514             : 
    3515             :   // Add the time-averaging layer, if needed
    3516             :   //  NB: There is some evidence that doing time-averaging _after_ 
    3517             :   //      channel averaging may be more expensive then doing it _before_, 
    3518             :   //      but this ensures that the meta-info (e.g. time, timeCentroid, etc.)
    3519             :   //      appear correctly in the VB2 accessed at this scope.
    3520             :   //      The problem is that AveragingTvi2 has not explicitly
    3521             :   //      implemented all of the relevant data accessors; it just
    3522             :   //      assumes---incorrectly---that you are going to use its VB2.
    3523             :   //      Making AveragingTvi2 the top layer ensures you do use it.
    3524             :   //      (Hard-wired use of AveragingTvi2 in MSTransform set it up
    3525             :   //       as the top [last] layer, and has been well-tested...)
    3526             : 
    3527             :   //cout << "svc_p->solint() = " << svc_p->solint() << endl;
    3528             :   //cout << "svc_p->solTimeInterval() = " << svc_p->solTimeInterval() << endl;
    3529             :   //cout << "svc_p->preavg() = " << svc_p->preavg() << endl;
    3530          64 :   if (!svc_p->solint().contains("int") &&      // i.e., not "int")
    3531          32 :       svc_p->preavg() != -DBL_MAX) {
    3532           0 :     Float avetime(svc_p->solTimeInterval());   // avetime is solint, nominally
    3533             :     // Use preavg instead, if...
    3534           0 :     if (svc_p->preavg()>FLT_EPSILON &&             // ...set meaningfully
    3535           0 :         svc_p->preavg()<svc_p->solTimeInterval())  // ...and less than solint
    3536           0 :       avetime=svc_p->preavg();
    3537           0 :     vi2org.addTimeAve(avetime);  // use min of solint and preavg here!
    3538             :   }
    3539             :   // small@jive.eu (2021-12-17): Currently we only handle the corrcomb
    3540             :   // cases of "all" and "none"; there will be a need to extend this, but the
    3541             :   // PolAverageTVILayerFactory that underlies this feature will also need to be extended
    3542             :   // to make that possible
    3543             :   // gmoellen (2024-08-06): We now support 'stokes' (forms Stokes I) and 'parallel' (direct
    3544             :   //   statistical combo of parallel hands).  If one parallel-hand is flagged, 'stokes'
    3545             :   //   effectively flags both; 'parallel' will retain the unflagged parallel hand.
    3546          61 :   if (svc_p->corrcomb().contains("stokes") ||
    3547          29 :       svc_p->corrcomb().contains("parallel") ) {
    3548             :     //cerr << "Calibrater::genericGatherAndSolve(): Combining correlations: "
    3549             :     //   << svc_p->corrcomb()
    3550             :     //   << endl;
    3551           5 :     vi2org.addCorrCombine(svc_p->corrcomb());
    3552             :   }
    3553             :   //else {
    3554             :   //    cerr << "Calibrater::genericGatherAndSolve(): Not combining correlations!" << endl;
    3555             :   //}
    3556             : 
    3557             :   //  vi2org should be fully configured at this point
    3558             :   //-------------------------------------------------
    3559             : 
    3560             : 
    3561             :   // Form the VI2 to drive data iteration below
    3562          32 :   vi::VisibilityIterator2& vi(vi2org.makeFullVI());
    3563             :   //  cout << "VI Layers: " << vi.ViiType() << endl;
    3564             : 
    3565             :   // Establish output freq meta data prior to solving  (CAS-12735 and related)
    3566             : 
    3567             :   // Discern (even implicitly-)selected spw subset
    3568          32 :   set<uInt> selspwset;
    3569          32 :   if (!simdata_p)  {
    3570             : 
    3571             :     // We can't proceed rationally if we have more than one freqSelection (multiple MSs)
    3572             :     //  (this is a sort-of out-of-the-blue test here....)
    3573          32 :     AlwaysAssert(frequencySelections_p->size()<2,AipsError);
    3574             : 
    3575             :     // TBD can we use the msmc_p?  (or maybe it is for the whole MS, not just the selected one?)
    3576          32 :     MSMetaData msmdtmp(mssel_p,50.0);
    3577          32 :     selspwset=msmdtmp.getSpwIDs();
    3578          32 :   } 
    3579             : 
    3580             :   // Extract selected spw list as a Vector<uInt>
    3581          32 :   Vector<uInt> selspwlist;
    3582          32 :   if (!simdata_p && selspwset.size()>0) {
    3583          32 :     Vector<uInt> vtmp(selspwset.begin(),selspwset.size(),0);
    3584          32 :     selspwlist.reference(vtmp);
    3585          32 :   } else {
    3586             :     // All spws in the MS  (this is a last resort!)
    3587             :     // NB: This is used in simdata_p=True context!
    3588           0 :     selspwlist.resize(msmc_p->nSpw());
    3589           0 :     indgen(selspwlist);
    3590             :   }
    3591             :   //  cout << "selspwlist = " << selspwlist << endl;
    3592             : 
    3593             :   // Delegate freq meta calculation to the SVC (wherein this info is stored)
    3594          32 :   svc_p->discernAndSetSolnFrequencies(vi,selspwlist);
    3595             : 
    3596             : 
    3597             :   // Access to the net VB2 for forming SolveDataBuffers in the SDBList below
    3598             :   //  NB: this assumes that the internal address of the VI2's VB2 will never change!
    3599          31 :   vi::VisBuffer2 *vb = vi.getImpl()->getVisBuffer();
    3600             : 
    3601             :   // VI2 should now be ready....
    3602             : 
    3603             :   // Discern number of Solutions and how many VI2 chunks per each
    3604          31 :   Int nSol(0);
    3605          31 :   Vector<Int> nChPSol(1000,0);  // nominal size; will enlarge as needed, and trim at end
    3606             : 
    3607             :   {
    3608             :     //cout << "Counting chunks and solutions..." << endl;
    3609          31 :     uInt isol(0);
    3610             :     //    uInt ichk(0);
    3611         268 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    3612             :       // NB: this loop NEVER touches the the subChunks, since
    3613             :       //     this would cause data I/O, cal, averaging, etc.
    3614             : 
    3615             :       //      int frame=vi.getImpl()->getReportingFrameOfReference();
    3616             :       //      cout << "ichk=" << ichk << " freqs= " << vi.getImpl()->getFrequencies(-1.0e0,frame,selspwlist(ispw),0);
    3617             : 
    3618             : 
    3619             :       // Enlarge nChPSol Vector, if necessary
    3620         237 :       if (isol>nChPSol.nelements()-1) {
    3621             :         //cout << "   ...At isol=" << isol << ", resizing nchPSol: " << nChPSol.nelements() << "-->";
    3622           0 :         nChPSol.resize(isol*2,True);        // double length, copy existing elements
    3623           0 :         nChPSol(Slice(isol,isol,1)).set(0); // init new elements
    3624             :         //cout << nChPSol.nelements() << endl;
    3625             :         //cout << "sol counting: " << isol << " " << nChPSol << " (" << ntrue(nChPSol>0) << "/" << nChPSol.nelements() << ")" << endl;
    3626             :       }
    3627             : 
    3628             :       // incr chunk counter for current solution
    3629         237 :       ++nChPSol(isol);  
    3630             :       //cout << "sol counting: " << isol << " " << nChPSol(Slice(0,min(isol+2,nChPSol.nelements()),1))
    3631             :       //     << " (" << ntrue(nChPSol>0) << "/" << nChPSol.nelements() << ")" 
    3632             :       //     << "  keyCh=" << vi.keyChange()
    3633             :       //     << endl;
    3634             : 
    3635             :       // next chunk is nominally next solution
    3636         237 :       ++isol;           
    3637             : 
    3638             :       // If combining spw or field, and the next chunk changes by
    3639             :       //   DATA_DESC_ID or FIELD_ID (and _not_ TIME, which is
    3640             :       //   changing slower than these when combine is on),
    3641             :       //   then the next chunk should be counted in the same soln
    3642         699 :       if ( (svc_p->combspw() && vi.keyChange()=="DATA_DESC_ID") ||
    3643         462 :            (svc_p->combfld() && vi.keyChange()=="FIELD_ID") )
    3644          12 :         --isol; // next one is the same solution interval
    3645             : 
    3646             :     }
    3647             :     // Trim list to realized length, which is the number of solutions we'll 
    3648             :     //   attempt below
    3649          31 :     nSol=ntrue(nChPSol>0);
    3650          31 :     nChPSol.resize(nSol,true);
    3651             :     //cout << "nSol   =" << nSol << endl;
    3652             :     //cout << "nChPSol=" << nChPSol << endl;
    3653             : 
    3654             :     /*  from SVC...
    3655             :     if (svc_p->combobs())
    3656             :       logSink() << "Combining observation Ids." << LogIO::POST;
    3657             :     if (svc_p->combscan())
    3658             :       logSink() << "Combining scans." << LogIO::POST;
    3659             :     if (svc_p->combspw()) 
    3660             :       logSink() << "Combining spws: " << spwlist << " -> " << spwlab << LogIO::POST;
    3661             :     if (svc_p->combfld()) 
    3662             :       logSink() << "Combining fields." << LogIO::POST;
    3663             :     */
    3664             : 
    3665          31 :     logSink() << "For solint = " << svc_p->solint() << ", found "
    3666             :               <<  nSol << " solution intervals."
    3667          31 :               << LogIO::POST;
    3668             :   }
    3669             : 
    3670             :   //  throw(AipsError("EARLY ESCAPE!!"));
    3671             : 
    3672             :   // Create the output caltable                                                                                             
    3673             :   //  (this version doesn't revise frequencies)                                                                             
    3674          31 :   svc_p->createMemCalTable2();
    3675             : 
    3676          31 :   Vector<Float> spwwts(msmc_p->nSpw(),-1.0);
    3677          31 :   Vector<Int64> nexp(msmc_p->nSpw(),0), natt(msmc_p->nSpw(),0),nsuc(msmc_p->nSpw(),0), nbelowsnr(msmc_p->nSpw(),0), nbelowbl(msmc_p->nSpw(),0);
    3678             :     
    3679             :   // Start Collecting counts
    3680          31 :   CalCounts* calCounts = new CalCounts();
    3681          31 :   calCounts->initCounts(msmc_p->nSpw(),msmc_p->nAnt(), svc_p->nPar());
    3682             :   // Set up results record
    3683          31 :   std::map<Int, std::map<String, Vector<Int>>> resultMap;
    3684             :   
    3685             :     
    3686             : #ifdef _OPENMP
    3687          31 :   Tsetup+=(omp_get_wtime()-time0);
    3688             : #endif
    3689             : 
    3690          31 :   Int nGood(0);
    3691          31 :   vi.originChunks();
    3692          31 :   Int nGlobalChunks=0;  // counts VI chunks globally
    3693         256 :   for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
    3694             : 
    3695             : #ifdef _OPENMP
    3696         225 :     time0=omp_get_wtime();
    3697             : #endif
    3698             : 
    3699             :     // Data will accumulate here                                                                                            
    3700         225 :     SDBList sdbs;
    3701             : 
    3702             :     // Gather the chunks/VBs for this solution                                                                              
    3703             :     //   Solution boundaries will ALWAYS occur on chunk boundaries,
    3704             :     //   though some chunk boundaries will be ignored in the 
    3705             :     //   combine='spw' or 'field' context
    3706             : 
    3707         225 :     for (Int ichunk=0;                                // count chunks in this solution
    3708         462 :          ichunk<nChPSol(isol)&&vi.moreChunks();  // while more chunks needed _and_ available
    3709         237 :          ++ichunk,vi.nextChunk()) {                     // advance to next chunk
    3710             : 
    3711             :       // Global chunk counter
    3712         237 :       ++nGlobalChunks;
    3713             : 
    3714             :       //  Loop over VB2s in this chunk
    3715             :       //    (we get more then one when preavg<solint)
    3716         237 :       Int ivb(0);
    3717         237 :       for (vi.origin();
    3718       27756 :            vi.more();
    3719       27519 :            ++ivb,vi.next()) {
    3720             :           
    3721             :         // Add this VB to the SDBList                                                                                       
    3722             : #ifdef _OPENMP
    3723       27519 :         Double Tadd0=omp_get_wtime();
    3724             : #endif
    3725             : 
    3726       27519 :         sdbs.add(*vb);
    3727             : 
    3728             : #ifdef _OPENMP
    3729       27519 :         Tadd+=(omp_get_wtime()-Tadd0);
    3730             : #endif
    3731             : 
    3732             :         // Keep track of spws seen but not included in solving
    3733       27519 :         Int ispw=vb->spectralWindows()(0);
    3734       27519 :         if (spwwts(ispw)<0) spwwts(ispw)=0.0f;
    3735       27519 :         spwwts(ispw)+=sum(vb->weightSpectrum());
    3736             : 
    3737             :         /*
    3738             :         Double modv(86400.0);
    3739             :         cout.precision(7);
    3740             :         cout << "isol=" << isol
    3741             :              << " ichk="<<ichunk
    3742             :              << " ivb="<<ivb
    3743             :              << " sc="<<vb->scan()(0)
    3744             :              << " fld="<<vb->fieldId()(0)
    3745             :              << " spw="<<vb->spectralWindows()(0)
    3746             :              << " nr="<<vb->nRows()
    3747             :              << " nch="<<vb->nChannels() << flush;
    3748             :         cout << " f="<<mean(vb->getFrequencies(0))/1e9
    3749             :              << "->"<< mean(sdbs.freqs())/1e9
    3750             :              << " t="<<fmod(mean(vb->time()),modv)
    3751             :              << "->"<< fmod(sdbs.aggregateTime(),modv)
    3752             :              << " tC="<<fmod(mean(vb->timeCentroid()),modv)
    3753             :              << "->"<< fmod(sdbs.aggregateTimeCentroid(),modv)
    3754             :              << " wt="<<sum(vb->weightSpectrum())
    3755             :              << " nSDB=" << sdbs.nSDB() 
    3756             :              << " nGlChks=" << nGlobalChunks
    3757             :              << " (keych=" << vi.keyChange() << ")"
    3758             :              << endl;
    3759             :         //*/
    3760             : 
    3761             :       }  // VI2 subchunks (VB2s)
    3762             :     } // VI2 chunks
    3763             : 
    3764             :     // Which spw is this?
    3765         225 :     Int thisSpw(sdbs.aggregateSpw());
    3766             : 
    3767             :     // Expecting a solution                                                                                                 
    3768         225 :     nexp(thisSpw)+=1;
    3769             :     // Initialize the antennaMap_ in svc
    3770         225 :     svc_p->clearMap();
    3771             :     // Get expected and data unflagged accumulation
    3772         225 :     svc_p->expectedUnflagged(sdbs);
    3773             :       
    3774             : 
    3775             : #ifdef _OPENMP
    3776         225 :     Tgather+=(omp_get_wtime()-time0);
    3777         225 :     time0=omp_get_wtime();
    3778             : #endif
    3779             : 
    3780             : 
    3781         225 :     if (sdbs.Ok()) {
    3782             :         
    3783             :       // Some unflagged data, so Attempting a solution                                                                      
    3784         225 :       natt(thisSpw)+=1;
    3785             : 
    3786             :       // make phase- or amp-only, if necessary                                                                              
    3787         225 :       sdbs.enforceAPonData(svc_p->apmode());
    3788             : 
    3789             :       // zero cross-hand weights, if necessary                                                                              
    3790         225 :       sdbs.enforceSolveWeights(svc_p->phandonly());
    3791             : 
    3792             :       // Synchronize meta-info in SVC                                                                                       
    3793         225 :       svc_p->syncSolveMeta(sdbs);
    3794             : 
    3795             :       // Set or verify freqs in the caltable                                                                                
    3796             :       //svc_p->setOrVerifyCTFrequencies(thisSpw);                                                                     
    3797         225 :       svc_p->setCTFrequencies(thisSpw);                                                                     
    3798             : 
    3799             :       // Size the solvePar arrays inside SVC                                                                                
    3800             :       //  (smart:  if freqDepPar()=F, uses 1)                                                                               
    3801             :       //  returns the number of channel solutions to iterate over                                                           
    3802             :       //Int nChanSol=svc_p->sizeSolveParCurrSpw(sdbs.nChannels());
    3803         225 :       Int nChanSol=svc_p->sizeSolveParCurrSpw((svc_p->freqDepPar() ? sdbs.nChannels() : 1));
    3804             : 
    3805         225 :       if (svc_p->useGenericSolveOne()) {
    3806             : 
    3807             :         // We'll use the generic solver                                                                                     
    3808           0 :         VisCalSolver2 vcs(svc_p->solmode(),svc_p->rmsthresh());
    3809             : 
    3810             :         // Guess from the data                                                                                              
    3811           0 :         svc_p->guessPar(sdbs,corrDepFlags_);
    3812             : 
    3813           0 :         Bool totalGoodSol(False);  // Will be set True if any channel is good                                               
    3814             :         //for (Int ich=0;ich<nChanSol;++ich) {
    3815           0 :         for (Int ich=nChanSol-1;ich>-1;--ich) {
    3816           0 :           svc_p->markTimer();
    3817           0 :           svc_p->focusChan()=ich;
    3818             : 
    3819             :           // Execute the solve                                                                                              
    3820           0 :           Bool goodsol=vcs.solve(*ve_p,*svc_p,sdbs);
    3821             : 
    3822           0 :           if (goodsol) {
    3823           0 :             totalGoodSol=True;
    3824             : 
    3825           0 :             svc_p->formSolveSNR();
    3826           0 :             svc_p->applySNRThreshold();
    3827             :           }
    3828             :           else
    3829           0 :             svc_p->currMetaNote();
    3830             : 
    3831             :           // Record solution in its channel, good or bad                                                                    
    3832           0 :           if (svc_p->freqDepPar())
    3833           0 :             svc_p->keep1(ich);
    3834             : 
    3835             :         } // ich                                                                                                            
    3836             : 
    3837           0 :         if (totalGoodSol) {
    3838             :           // Keep this good solution, and count it                                                                          
    3839           0 :           svc_p->keepNCT();
    3840           0 :           ++nGood;
    3841           0 :           nsuc(thisSpw)+=1;
    3842             :         }
    3843             : 
    3844           0 :       } // useGenericSolveOne                                                                                               
    3845             :       else {
    3846             :         // Use self-directed individual solve                                                                               
    3847             :         //   TBD: return T/F for goodness?                                                                                  
    3848             :         //cout << "Calling selfSolveOne()!!!!!!" << endl;
    3849         225 :         svc_p->selfSolveOne(sdbs);
    3850             : 
    3851             :         // Keep this good solution, and count it                                                                            
    3852         225 :         svc_p->keepNCT();
    3853         225 :         ++nGood;
    3854         225 :         nsuc(thisSpw)+=1;
    3855             :       }
    3856             : 
    3857             :     } // sdbs.Ok()
    3858             :     else {
    3859             :       // Synchronize meta-info in SVC
    3860           0 :       svc_p->syncSolveMeta(sdbs);
    3861           0 :       cout << "Found no unflagged data at:";
    3862           0 :       svc_p->currMetaNote();
    3863             :     }
    3864             :     //cout << endl;
    3865             :     // Get all the antenna value counts
    3866         225 :     resultMap = svc_p->getAntennaMap();
    3867         225 :     calCounts->addAntennaCounts(thisSpw,msmc_p->nAnt(), svc_p->nPar(), resultMap);
    3868             : 
    3869             : #ifdef _OPENMP
    3870         225 :     Tsolve+=(omp_get_wtime()-time0);
    3871             : #endif    
    3872             :     
    3873             :     //    throw(AipsError("EARLY ESCAPE!!"));
    3874             : 
    3875         225 :   } // isol
    3876             :     
    3877             :   // Report nGood to logger
    3878             :   logSink() << "  Found good " 
    3879          31 :             << svc_p->typeName() << " solutions in "
    3880             :             << nGood << " solution intervals."
    3881          31 :             << LogIO::POST;
    3882             : 
    3883             : #ifdef _OPENMP
    3884             :  #ifdef REPORT_CAL_TIMING
    3885             :   cout << "Calibrater::genericGatherAndSolve Timing: " << endl;
    3886             :   cout << " setup=" << Tsetup
    3887             :        << " gather=" << Tgather 
    3888             :        << " (SDBadd=" << Tadd << ")"
    3889             :        << " solve=" << Tsolve 
    3890             :        << " total=" << Tsetup+Tgather+Tsolve
    3891             :     //       << " tick=" << omp_get_wtick()
    3892             :        << endl;
    3893             :  #endif
    3894             : #endif
    3895             : 
    3896             :   // Report spws that were seen but not solved
    3897          31 :   Vector<Bool> unsolspw=(spwwts==0.0f); 
    3898          31 :   summarize_uncalspws(unsolspw, "solv");                                                                                  
    3899             : 
    3900             :   //  throw(AipsError("EARLY ESCAPE!!"));
    3901             : 
    3902          31 :   if (nGood>0) {
    3903          31 :     if (svc_p->typeName()!="BPOLY") {  // needed?                                                                           
    3904             :       // apply refant, etc.
    3905          31 :       svc_p->clearRefantMap();
    3906          31 :       svc_p->globalPostSolveTinker();
    3907             : 
    3908             :       // write to disk                                                                                                      
    3909          31 :       svc_p->storeNCT();
    3910             :     }
    3911             :   }
    3912             :   else {
    3913             :     logSink() << "No output calibration table written."
    3914           0 :               << LogIO::POST;
    3915             :   }
    3916             :     
    3917             :   // Collect and update the refants
    3918          31 :   std::map<Int, std::map<Int, Int>> refantMap;
    3919          31 :   refantMap = svc_p->getRefantMap();
    3920          31 :   calCounts->updateRefants(msmc_p->nSpw(), msmc_p->nAnt(), refantMap);
    3921             :   // Compile all accumulated counts into a record
    3922          31 :   resRec_ = calCounts->makeRecord(msmc_p->nAnt(), vi.nPolarizationIds());
    3923             :       
    3924             :   // print a matrix to the logger
    3925          31 :   logSink() << "----- PER ANTENNA INFO -----" << LogIO::POST;
    3926             :   // print the antenna list
    3927          31 :   logSink() << "      ";
    3928         347 :   for (Int ant=0; ant<msmc_p->nAnt(); ant++) {
    3929         316 :       logSink() << " ANT: " << ant << "   ";
    3930             :   }
    3931          31 :   logSink() << LogIO::POST;
    3932             :       
    3933         155 :   for (Int spw=0; spw < msmc_p->nSpw(); spw++) {
    3934             :           
    3935         124 :       logSink() << LogIO::NORMAL << "SPW: " << spw;
    3936             :           
    3937        1388 :       for (Int ant=0; ant < msmc_p->nAnt(); ant++) {
    3938        1264 :           logSink() << " " << calCounts->antMapVal(spw, ant, "above_minsnr") << " ";
    3939             :       }
    3940         124 :       logSink() << LogIO::POST;
    3941             :   }
    3942             :       
    3943          31 :   logSink() << "----- PER SPW INFO -----" << LogIO::POST;
    3944             :   // print the result fields
    3945          31 :   logSink() << "      ";
    3946          31 :   logSink() << " expected  data_unflagged  above_minblperant  above_minsnr";
    3947          31 :   logSink() << LogIO::POST;
    3948         155 :   for (Int spw = 0; spw < msmc_p->nSpw(); spw++) {
    3949         124 :       logSink() << LogIO::NORMAL << "SPW: " << spw << " ";
    3950         124 :       logSink() << calCounts->spwMapVal(spw, "expected") << "  ";
    3951         124 :       logSink() << calCounts->spwMapVal(spw, "data_unflagged") << "        ";
    3952         124 :       logSink() << calCounts->spwMapVal(spw, "above_minblperant") << "            ";
    3953         124 :       logSink() << calCounts->spwMapVal(spw, "above_minsnr");
    3954         124 :       logSink() << LogIO::POST;
    3955             :   }
    3956             :       
    3957          31 :   logSink() << "----- GLOBAL INFO -----" << LogIO::POST;
    3958          31 :   logSink() << "expected  data_unflagged  above_minblperant  above_minsnr";
    3959          31 :   logSink() << LogIO::POST;
    3960          31 :   logSink() << calCounts->totalMapVal("expected") << "  ";
    3961          31 :   logSink() << calCounts->totalMapVal("data_unflagged") << "        ";
    3962          31 :   logSink() << calCounts->totalMapVal("above_minblperant") << "            ";
    3963          31 :   logSink() << calCounts->totalMapVal("above_minsnr");
    3964          31 :   logSink() << LogIO::POST;
    3965             : 
    3966             :   // Fill activity record
    3967             :   
    3968          31 :   actRec_ = Record();
    3969          31 :   actRec_.define("origin","Calibrater::genericGatherAndSolve");
    3970          31 :   actRec_.define("nExpected",nexp);
    3971          31 :   actRec_.define("nAttempt",natt);
    3972          31 :   actRec_.define("nSucceed",nsuc);
    3973             :     
    3974             :   //cout << nexp << ", " << natt << ", " << nsuc << endl;
    3975             : 
    3976             :   { 
    3977          31 :     Record solveRec=svc_p->solveActionRec();
    3978          31 :     if (solveRec.nfields()>0)
    3979           0 :       actRec_.merge(solveRec);
    3980          31 :   }
    3981             : 
    3982             :   // Reach here, all is good
    3983          31 :   return True;
    3984             : 
    3985          35 : }
    3986             : 
    3987             : 
    3988           0 : void Calibrater::writeHistory(LogIO& /*os*/, Bool /*cliCommand*/)
    3989             : {
    3990             :   // Disabled 2016/04/19: avoid direct MS.HISTORY updates from
    3991             :   //   below the python level, FOR NOW
    3992             : 
    3993           0 :   return;
    3994             :   /*
    3995             :   if (!historytab_p.isNull()) {
    3996             :     if (histLockCounter_p == 0) {
    3997             :       historytab_p.lock(false);
    3998             :     }
    3999             :     ++histLockCounter_p;
    4000             : 
    4001             :     os.postLocally();
    4002             :     if (cliCommand) {
    4003             :       hist_p->cliCommand(os);
    4004             :     } else {
    4005             :       hist_p->addMessage(os);
    4006             :     }
    4007             : 
    4008             :     if (histLockCounter_p == 1) {
    4009             :       historytab_p.unlock();
    4010             :     }
    4011             :     if (histLockCounter_p > 0) {
    4012             :       --histLockCounter_p;
    4013             :     }
    4014             :   } else {
    4015             :     os << LogIO::SEVERE << "calibrater is not yet initialized" << LogIO::POST;
    4016             :   }
    4017             :   */
    4018             : }
    4019             : 
    4020          32 : void Calibrater::setCalFilterConfiguration(String const &type,
    4021             :     Record const &config) {
    4022             :   // currently only SDDoubleCircleGainCal requires data filtering
    4023          32 :   if (type.startsWith("SDGAIN_OTFD")) {
    4024           0 :     calFilterConfig_p.define("mode", "SDGAIN_OTFD");
    4025           0 :     if (config.isDefined("smooth")) {
    4026           0 :       calFilterConfig_p.define("smooth", config.asBool("smooth"));
    4027             :     }
    4028           0 :     if (config.isDefined("radius")) {
    4029           0 :       calFilterConfig_p.define("radius", config.asString("radius"));
    4030             :     }
    4031             :   }
    4032          32 : }
    4033             : 
    4034             : // *********************************************
    4035             : //  OldCalibrater implementations that use vs_p
    4036             : 
    4037           0 : OldCalibrater::OldCalibrater(): 
    4038             :   Calibrater(),
    4039           0 :   vs_p(0), 
    4040           0 :   rawvs_p(0)
    4041             : {
    4042             :   //  cout << "This is the OLD VI2-aware Calibrater" << endl;
    4043           0 : }
    4044             : 
    4045           0 : OldCalibrater::OldCalibrater(String msname): 
    4046             :   Calibrater(msname),
    4047           0 :   vs_p(0), 
    4048           0 :   rawvs_p(0)
    4049             : {
    4050           0 : }
    4051             : 
    4052             : /*
    4053             : OldCalibrater::OldCalibrater(const OldCalibrater & other) :
    4054             :   Calibrater(other)
    4055             : {
    4056             :   operator=(other);
    4057             : }
    4058             : 
    4059             : OldCalibrater& OldCalibrater::operator=(const OldCalibrater & other)
    4060             : {
    4061             :   Calibrater::operator=(other); // copy parental units
    4062             :   vs_p=other.vs_p;
    4063             :   rawvs_p=other.rawvs_p;
    4064             :   return *this;
    4065             : }
    4066             : */
    4067             : 
    4068           0 : OldCalibrater::~OldCalibrater()
    4069             : {
    4070           0 :   OldCalibrater::cleanupVisSet();
    4071           0 : }
    4072             : 
    4073             : 
    4074             : // Select data (using MSSelection syntax)
    4075           0 : void OldCalibrater::selectvis(const String& time,
    4076             :                               const String& spw,
    4077             :                               const String& scan,
    4078             :                               const String& field,
    4079             :                               const String& intent,
    4080             :                               const String& obsIDs,
    4081             :                               const String& baseline,
    4082             :                               const String& uvrange,
    4083             :                               const String& chanmode,
    4084             :                               const Int& nchan,
    4085             :                               const Int& start, 
    4086             :                               const Int& step,
    4087             :                               const MRadialVelocity& mStart,
    4088             :                               const MRadialVelocity& mStep,
    4089             :                               const String& msSelect)
    4090             : {
    4091             : // Define primary measurement set selection criteria
    4092             : // Inputs:
    4093             : //    time
    4094             : //    spw
    4095             : //    scan
    4096             : //    field
    4097             : //    intent
    4098             : //    obsIDs
    4099             : //    baseline
    4100             : //    uvrange
    4101             : //    chanmode     const String&            Frequency/velocity selection mode
    4102             : //                                          ("channel", "velocity" or 
    4103             : //                                           "opticalvelocity")
    4104             : //    nchan        const Int&               No of channels to select
    4105             : //    start        const Int&               Start channel to select
    4106             : //    step         const Int&               Channel increment
    4107             : //    mStart       const MRadialVelocity&   Start radial vel. to select
    4108             : //    mStep        const MRadialVelocity&   Radial velocity increment
    4109             : //    msSelect     const String&            MS selection string (TAQL)
    4110             : // Output to private data:
    4111             : //
    4112           0 :   logSink() << LogOrigin("Calibrater","selectvis") << LogIO::NORMAL3;
    4113             :   
    4114             :   try {
    4115             : 
    4116             :  /*   
    4117             :     cout << "time     = " << time << " " << time.length() <<endl;
    4118             :     cout << "spw      = " << spw << " " << spw.length() <<endl;
    4119             :     cout << "scan     = " << scan << " " << scan.length() <<endl;
    4120             :     cout << "field    = " << field << " " << field.length() <<endl;
    4121             :     cout << "baseline = " << baseline << " " << baseline.length() << endl;
    4122             :     cout << "uvrange  = " << uvrange << " " << uvrange.length() << endl;
    4123             :  */
    4124             : 
    4125           0 :     logSink() << "Selecting data" << LogIO::POST;
    4126             :     
    4127             :     // Apply selection to the original MeasurementSet
    4128           0 :     logSink() << "Performing selection on MeasurementSet" << endl;
    4129             :     
    4130           0 :     if (mssel_p) {
    4131           0 :       delete mssel_p;
    4132           0 :       mssel_p=0;
    4133             :     };
    4134             : 
    4135             :     // Report non-trivial user selections
    4136           0 :     if (time!="")
    4137           0 :       logSink() << " Selecting on time: '" << time << "'" << endl;
    4138           0 :     if (spw!="")
    4139           0 :       logSink() << " Selecting on spw: '" << spw << "'" << endl;
    4140           0 :     if (scan!="")
    4141           0 :       logSink() << " Selecting on scan: '" << scan << "'" << endl;
    4142           0 :     if (field!="")
    4143           0 :       logSink() << " Selecting on field: '" << field << "'" << endl;
    4144           0 :     if (intent!="")
    4145           0 :       logSink() << " Selecting on intent: '" << intent << "'" << endl;
    4146           0 :     if(obsIDs != "")
    4147           0 :       logSink() << " Selecting by observation IDs: '" << obsIDs << "'" << endl;
    4148           0 :     if (baseline!="")
    4149           0 :       logSink() << " Selecting on antenna/baseline: '" << baseline << "'" << endl;
    4150           0 :     if (uvrange!="")
    4151           0 :       logSink() << " Selecting on uvrange: '" << uvrange << "'" << endl;
    4152           0 :     if (msSelect!="")
    4153           0 :       logSink() << " Selecting with TaQL: '" << msSelect << "'" << endl;
    4154           0 :     logSink() << LogIO::POST;
    4155             : 
    4156             : 
    4157             :     // Assume no selection, for starters
    4158             :     // gmoellen 2012/01/30    mssel_p = new MeasurementSet(sorted, ms_p);
    4159           0 :     mssel_p = new MeasurementSet(*ms_p);
    4160             : 
    4161             :     // Apply user-supplied selection
    4162           0 :     Bool nontrivsel=false;
    4163             :     // gmoellen 2012/01/30    nontrivsel= mssSetData(MeasurementSet(sorted, ms_p),
    4164             : 
    4165             :     // Ensure use of a fresh MSSelection object
    4166           0 :     if (mss_p) { delete mss_p; mss_p=NULL; }
    4167           0 :     mss_p=new MSSelection();
    4168           0 :     nontrivsel= mssSetData(*ms_p,
    4169           0 :                            *mssel_p,"",
    4170             :                            time,baseline,
    4171             :                            field,spw,
    4172             :                            uvrange,msSelect,
    4173             :                            "",scan,"",intent, obsIDs,mss_p);
    4174             : 
    4175             :     // Keep any MR status for the MS
    4176           0 :     mssel_p->setMemoryResidentSubtables(ms_p->getMrsEligibility());
    4177             : 
    4178             :     // If non-trivial MSSelection invoked and nrow reduced:
    4179           0 :     if(nontrivsel && mssel_p->nrow()<ms_p->nrow()) {
    4180             : 
    4181             :       // Escape if no rows selected
    4182           0 :       if (mssel_p->nrow()==0) 
    4183           0 :         throw(AipsError("Specified selection selects zero rows!"));
    4184             : 
    4185             :       // ...otherwise report how many rows are selected
    4186           0 :       logSink() << "By selection " << ms_p->nrow() 
    4187           0 :                 << " rows are reduced to " << mssel_p->nrow() 
    4188           0 :                 << LogIO::POST;
    4189             :     }
    4190             :     else {
    4191             :       // Selection did nothing:
    4192           0 :       logSink() << "Selection did not drop any rows" << LogIO::POST;
    4193             :     }
    4194             : 
    4195             :     // Now, re-create the associated VisSet
    4196           0 :     if(vs_p) delete vs_p; vs_p=0;
    4197           0 :     Block<int> sort(0);
    4198           0 :     Matrix<Int> noselection;
    4199             :     // gmoellen 2012/01/30    vs_p = new VisSet(*mssel_p,sort,noselection);
    4200           0 :     vs_p = new VisSet(*mssel_p,sort,noselection,false,0.0,false,false);
    4201           0 :     AlwaysAssert(vs_p, AipsError);
    4202             : 
    4203             :     // Attempt to use MSSelection for channel selection
    4204             :     //  if user not using the old way
    4205           0 :     if (chanmode=="none") {
    4206           0 :       selectChannel(spw);
    4207             :     }
    4208             :     else {
    4209             :       // Reluctantly use the old-fashioned way
    4210             :       logSink() << LogIO::WARN 
    4211             :                 << "You have used the old-fashioned mode parameter" << endl
    4212             :                 << "for channel selection.  It still works, for now," << endl
    4213             :                 << "but this will be eliminated in the near future." << endl
    4214             :                 << "Please begin using the new channel selection" << endl
    4215           0 :                 << "syntax in the spw parameter." << LogIO::POST;
    4216           0 :       selectChannel(chanmode,nchan,start,step,mStart,mStep);
    4217             :     }
    4218             : 
    4219           0 :   }
    4220           0 :   catch (MSSelectionError& x) {
    4221             :     // Re-initialize with the existing MS
    4222           0 :     logSink() << LogOrigin("Calibrater","selectvis",WHERE) 
    4223             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    4224           0 :               << LogIO::POST;
    4225             :     // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty
    4226           0 :     initialize(*ms_p,false,false,false);
    4227           0 :     throw(AipsError("Error in data selection specification: " + x.getMesg()));
    4228           0 :   } 
    4229           0 :   catch (AipsError x) {
    4230             :     // Re-initialize with the existing MS
    4231           0 :     logSink() << LogOrigin("Calibrater","selectvis",WHERE) 
    4232             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    4233           0 :               << LogIO::POST;
    4234             :     // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty.
    4235           0 :     initialize(*ms_p,false,false,false);
    4236           0 :     throw(AipsError("Error in Calibrater::selectvis(): " + x.getMesg()));
    4237           0 :   } 
    4238           0 : };
    4239             : 
    4240             : 
    4241           0 : Bool OldCalibrater::setapply (const String& type, 
    4242             :                               const Record& applypar)
    4243             : {
    4244           0 :   logSink() << LogOrigin("Calibrater", "setapply(type, applypar)");
    4245             : 
    4246             :   // First try to create the requested VisCal object
    4247           0 :   VisCal *vc(NULL);
    4248             : 
    4249             :   try {
    4250             : 
    4251           0 :     if(!ok()) 
    4252           0 :       throw(AipsError("Calibrater not prepared for setapply."));
    4253             : 
    4254           0 :     String upType=type;
    4255           0 :     upType.upcase();
    4256             : 
    4257             :     logSink() << LogIO::NORMAL 
    4258             :               << "Arranging to APPLY:"
    4259           0 :               << LogIO::POST;
    4260             : 
    4261             :     // Add a new VisCal to the apply list
    4262           0 :     vc = createVisCal(upType,*vs_p);  
    4263             : 
    4264           0 :     vc->setApply(applypar);       
    4265             : 
    4266             :     logSink() << LogIO::NORMAL << ".   "
    4267           0 :               << vc->applyinfo()
    4268           0 :               << LogIO::POST;
    4269             : 
    4270           0 :   } catch (AipsError x) {
    4271             :     logSink() << LogIO::SEVERE << x.getMesg() 
    4272             :               << " Check inputs and try again."
    4273           0 :               << LogIO::POST;
    4274           0 :     if (vc) delete vc;
    4275           0 :     throw(AipsError("Error in Calibrater::setapply."));
    4276             :     return false;
    4277           0 :   }
    4278             : 
    4279             :   // Creation apparently successful, so add to the apply list
    4280             :   // TBD: consolidate with above?
    4281             :   try {
    4282             : 
    4283           0 :     uInt napp=vc_p.nelements();
    4284           0 :     vc_p.resize(napp+1,false,true);      
    4285           0 :     vc_p[napp] = vc;
    4286           0 :     vc=NULL;
    4287             :    
    4288             :     // Maintain sort of apply list
    4289           0 :     ve_p->setapply(vc_p);
    4290             :     
    4291           0 :     return true;
    4292             : 
    4293           0 :   } catch (AipsError x) {
    4294             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    4295           0 :               << LogIO::POST;
    4296           0 :     if (vc) delete vc;
    4297           0 :     throw(AipsError("Error in Calibrater::setapply."));
    4298             :     return false;
    4299           0 :   } 
    4300             :   return false;
    4301             : }
    4302             : 
    4303             : // Set up apply-able calibration via a Cal Library
    4304           0 : Bool OldCalibrater::setcallib(Record callib) {
    4305             : 
    4306           0 :   logSink() << LogOrigin("Calibrater", "setcallib(callib)");
    4307             : 
    4308             :   //  cout << "Calibrater::setcallib: callib.isFixed() = " << boolalpha << callib.isFixed() << endl;
    4309             : 
    4310           0 :   uInt ntab=callib.nfields();
    4311             : 
    4312             :   //  cout << "callib.nfields() = " << ntab << endl;
    4313             : 
    4314             :   // Do some preliminary per-table verification
    4315           0 :   for (uInt itab=0;itab<ntab;++itab) {
    4316             : 
    4317           0 :     String tabname=callib.name(itab);
    4318             : 
    4319             :     // Insist that the table exists on disk
    4320           0 :     if (!Table::isReadable(tabname))
    4321           0 :       throw(AipsError("Caltable "+tabname+" does not exist."));
    4322             : 
    4323           0 :   }
    4324             : 
    4325             :   // Tables exist, so deploy them...
    4326             : 
    4327           0 :   for (uInt itab=0;itab<ntab;++itab) {
    4328             : 
    4329           0 :     String tabname=callib.name(itab);
    4330             : 
    4331             :     // Get the type from the table
    4332           0 :     String upType=calTableType(tabname);
    4333           0 :     upType.upcase();
    4334             : 
    4335             :     // Add table name to the record
    4336           0 :     Record thistabrec=callib.asrwRecord(itab);
    4337           0 :     thistabrec.define("tablename",tabname);
    4338             : 
    4339             :     // First try to create the requested VisCal object
    4340           0 :     VisCal *vc(NULL);
    4341             : 
    4342             :     try {
    4343             : 
    4344           0 :       if(!ok()) 
    4345           0 :         throw(AipsError("Calibrater not prepared for setapply."));
    4346             :       
    4347             :       logSink() << LogIO::NORMAL 
    4348             :                 << "Arranging to APPLY:"
    4349           0 :                 << LogIO::POST;
    4350             :       
    4351             :       // Add a new VisCal to the apply list
    4352           0 :       vc = createVisCal(upType,*vs_p);  
    4353             : 
    4354             : 
    4355             :       // ingest this table according to its callib
    4356           0 :       vc->setCallib(thistabrec,*mssel_p);
    4357             : 
    4358           0 :     } catch (AipsError x) {
    4359             :       logSink() << LogIO::SEVERE << x.getMesg() 
    4360             :                 << " Check inputs and try again."
    4361           0 :                 << LogIO::POST;
    4362           0 :       if (vc) delete vc;
    4363           0 :       throw(AipsError("Error in Calibrater::setapply."));
    4364             :       return false;
    4365           0 :     }
    4366             : 
    4367             :     // Creation apparently successful, so add to the apply list
    4368             :     // TBD: consolidate with above?
    4369             :     try {
    4370             :       
    4371           0 :       uInt napp=vc_p.nelements();
    4372           0 :       vc_p.resize(napp+1,false,true);      
    4373           0 :       vc_p[napp] = vc;
    4374           0 :       vc=NULL;
    4375             :    
    4376             :       // Maintain sort of apply list
    4377           0 :       ve_p->setapply(vc_p);
    4378             :       
    4379           0 :     } catch (AipsError x) {
    4380             :       logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    4381           0 :                 << LogIO::POST;
    4382           0 :       if (vc) delete vc;
    4383           0 :       throw(AipsError("Error in Calibrater::setapply."));
    4384             :       return false;
    4385           0 :     } 
    4386           0 :   }
    4387             : 
    4388             :   // All ok, if we get this far!
    4389           0 :   return true;
    4390             : 
    4391             : }
    4392             : 
    4393             : 
    4394             : // Set up apply-able calibration via a Cal Library
    4395           0 : Bool OldCalibrater::setcallib2(Record callib, const casacore::MeasurementSet* ms) {
    4396             : 
    4397           0 :   logSink() << LogOrigin("OldCalibrater", "setcallib2(callib)");
    4398             : 
    4399             :   //  cout << "Calibrater::setcallib2(callib) : " << boolalpha << callib << endl;
    4400             : 
    4401           0 :   uInt ntab=callib.nfields();
    4402             : 
    4403             :   //  cout << "callib.nfields() = " << ntab << endl;
    4404             : 
    4405             :   // Do some preliminary per-table verification
    4406           0 :   for (uInt itab=0;itab<ntab;++itab) {
    4407             : 
    4408           0 :     String tabname=callib.name(itab);
    4409             : 
    4410             :     // Trap parang
    4411             :     // TBD...
    4412             :     //    if (tabname=="<parang>")
    4413             :     //      continue;
    4414             : 
    4415             :     // Insist that the table exists on disk
    4416           0 :     if (!Table::isReadable(tabname))
    4417           0 :       throw(AipsError("Caltable "+tabname+" does not exist."));
    4418             : 
    4419           0 :   }
    4420             : 
    4421             :   // Tables exist, so deploy them...
    4422             : 
    4423             :   // Local MS object for callib parsing (only)
    4424             :   //  MeasurementSet lms(msname_p,Table::Update);
    4425             :   //cout << "OLD lms" << endl;
    4426             : 
    4427             : 
    4428             :   // Local const MS object for callib parsing (only)
    4429           0 :   const MeasurementSet *lmsp(0);
    4430           0 :   if (ms) {
    4431             :     // Use supplied MS (from outside), if specified...
    4432             :     // TBD: should we verify same base MS as ms_p/mssel_p?
    4433           0 :     lmsp=ms;
    4434             :   }
    4435             :   else {
    4436             :     // ...use internal one instead
    4437           0 :     lmsp=mssel_p;
    4438             :   }
    4439             :   // Reference for use below
    4440           0 :   const MeasurementSet &lms(*lmsp);
    4441             : 
    4442             :   // Get some global shape info:
    4443           0 :   Int MSnAnt = lms.antenna().nrow();
    4444           0 :   Int MSnSpw = lms.spectralWindow().nrow();
    4445             : 
    4446           0 :   for (uInt itab=0;itab<ntab;++itab) {
    4447             : 
    4448           0 :     String tabname=callib.name(itab);
    4449             : 
    4450             :     // Get the type from the table
    4451           0 :     String upType=calTableType(tabname);
    4452           0 :     upType.upcase();
    4453             : 
    4454             :     // Add table name to the record
    4455           0 :     Record thistabrec=callib.asrwRecord(itab);
    4456           0 :     thistabrec.define("tablename",tabname);
    4457             : 
    4458             :     // First try to create the requested VisCal object
    4459           0 :     VisCal *vc(NULL);
    4460             : 
    4461             :     try {
    4462             : 
    4463             :       //      if(!ok()) 
    4464             :       //        throw(AipsError("Calibrater not prepared for setapply."));
    4465             :       
    4466             :       logSink() << LogIO::NORMAL 
    4467             :                 << "Arranging to APPLY:"
    4468           0 :                 << LogIO::POST;
    4469             :       
    4470             :       // Add a new VisCal to the apply list
    4471           0 :       vc = createVisCal(upType,msname_p,MSnAnt,MSnSpw);  
    4472             : 
    4473             :       // ingest this table according to its callib
    4474           0 :       vc->setCallib(thistabrec,lms);
    4475             : 
    4476           0 :     } catch (AipsError x) {
    4477             :       logSink() << LogIO::SEVERE << x.getMesg() 
    4478             :                 << " Check inputs and try again."
    4479           0 :                 << LogIO::POST;
    4480           0 :       if (vc) delete vc;
    4481           0 :       throw(AipsError("Error in Calibrater::callib2."));
    4482             :       return false;
    4483           0 :     }
    4484             : 
    4485             :     // Creation apparently successful, so add to the apply list
    4486             :     // TBD: consolidate with above?
    4487             :     try {
    4488             :       
    4489           0 :       uInt napp=vc_p.nelements();
    4490           0 :       vc_p.resize(napp+1,false,true);      
    4491           0 :       vc_p[napp] = vc;
    4492           0 :       vc=NULL;
    4493             :    
    4494             :       // Maintain sort of apply list
    4495           0 :       ve_p->setapply(vc_p);
    4496             :       
    4497           0 :     } catch (AipsError x) {
    4498             :       logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    4499           0 :                 << LogIO::POST;
    4500           0 :       if (vc) delete vc;
    4501           0 :       throw(AipsError("Error in Calibrater::setapply."));
    4502             :       return false;
    4503           0 :     } 
    4504           0 :   }
    4505             :   // All ok, if we get this far!
    4506           0 :   return true;
    4507             : 
    4508             : }
    4509             : 
    4510             : 
    4511           0 : Bool OldCalibrater::setsolve (const String& type, 
    4512             :                               const Record& solvepar) {
    4513             : 
    4514             :   // Attempt to create the solvable object
    4515           0 :   SolvableVisCal *svc(NULL);
    4516             :   try {
    4517             : 
    4518           0 :     if(!ok()) 
    4519           0 :       throw(AipsError("Calibrater not prepared for setsolve."));
    4520             : 
    4521           0 :     String upType = type;
    4522           0 :     upType.upcase();
    4523             : 
    4524             :     // Clean out any old solve that was lying around
    4525           0 :     unsetsolve();
    4526             : 
    4527             :     logSink() << LogIO::NORMAL 
    4528             :               << "Arranging to SOLVE:"
    4529           0 :               << LogIO::POST;
    4530             : 
    4531             :     // Create the new SolvableVisCal
    4532           0 :     svc = createSolvableVisCal(upType,*vs_p);
    4533           0 :     svc->setSolve(solvepar);
    4534             :     
    4535             :     logSink() << LogIO::NORMAL << ".   "
    4536           0 :               << svc->solveinfo()
    4537           0 :               << LogIO::POST;
    4538             : 
    4539             :     // Creation apparently successful, keep it
    4540           0 :     svc_p=svc;
    4541           0 :     svc=NULL;
    4542             : 
    4543           0 :     return true;
    4544             : 
    4545           0 :   } catch (AipsError x) {
    4546             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    4547           0 :               << LogIO::POST;
    4548           0 :     unsetsolve();
    4549           0 :     if (svc) delete svc;
    4550           0 :     throw(AipsError("Error in Calibrater::setsolve."));
    4551             :     return false;
    4552           0 :   } 
    4553             :   return false;
    4554             : }
    4555             : 
    4556           0 : Bool OldCalibrater::correct(String mode)
    4557             : {
    4558           0 :     logSink() << LogOrigin("Calibrater","correct") << LogIO::NORMAL;
    4559             : 
    4560           0 :     Bool retval = true;
    4561             : 
    4562             :     try {
    4563             : 
    4564             :         // make mode all-caps
    4565           0 :         String upmode=mode;
    4566           0 :         upmode.upcase();
    4567             : 
    4568             :         // If trialmode=T, only the flags will be set
    4569             :         //   (and only written if not TRIAL)
    4570           0 :         Bool trialmode=(upmode.contains("TRIAL") || 
    4571           0 :                         upmode.contains("FLAGONLY"));
    4572             : 
    4573             :         // Set up VisSet and its VisibilityIterator.
    4574             : 
    4575           0 :         VisibilityIterator::DataColumn whichOutCol = configureForCorrection ();
    4576             : 
    4577           0 :         VisIter& vi(vs_p->iter());
    4578           0 :         VisBufferAutoPtr vb (vi);
    4579           0 :         vi.origin();
    4580             : 
    4581             :         // Pass each timestamp (VisBuffer) to VisEquation for correction
    4582             : 
    4583           0 :         Vector<Bool> uncalspw(vi.numberSpw());    // Used to accumulate error messages
    4584           0 :         uncalspw.set(false);                    // instead of bombing the user
    4585           0 :         uncalspw.set(False);                    // instead of bombing the user
    4586             :                                         // in a loop.
    4587             : 
    4588           0 :         for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    4589             : 
    4590           0 :             for (vi.origin(); vi.more(); vi++) {
    4591             : 
    4592           0 :                 uInt spw = vb->spectralWindow();
    4593             : 
    4594             :                 // Re-initialize weights from sigma column
    4595           0 :                 vb->resetWeightMat();
    4596             : 
    4597             :                 // If we can calibrate this vb, do it...
    4598           0 :                 if (ve_p->spwOK(spw)){
    4599             :                   
    4600             :                   // throws exception if nothing to apply
    4601           0 :                   ve_p->correct(*vb,trialmode);
    4602             :                     
    4603             :                 }
    4604             :                 // ...else don't, prepare warning, and possibly set flags
    4605             :                 else{
    4606             : 
    4607             :                   // set uncalspw for warning message
    4608           0 :                   uncalspw[spw] = true;
    4609             :                   // set the flags, if we are being strict
    4610           0 :                   if (upmode.contains("STRICT"))
    4611             :                     // set the flags
    4612             :                     // (don't touch the data/weights, which are initialized)
    4613           0 :                     vb->flag().set(true);
    4614             :                 }
    4615             : 
    4616             :                 // Only if not a trial run, trigger write to disk
    4617           0 :                 if (!upmode.contains("TRIAL")) {
    4618             :                       
    4619           0 :                   if (upmode.contains("CAL")) {
    4620           0 :                     vi.setVis (vb->visCube(), whichOutCol);
    4621           0 :                     vi.setWeightMat(vb->weightMat()); 
    4622             :                   }
    4623             :                   
    4624           0 :                   if (upmode.contains("FLAG"))
    4625           0 :                     vi.setFlag (vb->flag());
    4626             :                   
    4627             :                 }
    4628             :                 
    4629             :             }
    4630             :         }
    4631             : 
    4632           0 :         vs_p->flush (); // Flush to disk
    4633             : 
    4634             :         // Now that we're out of the loop, summarize any errors.
    4635             : 
    4636           0 :         retval = summarize_uncalspws(uncalspw, "correct",
    4637           0 :                                      upmode.contains("STRICT"));
    4638             : 
    4639           0 :         actRec_=Record();
    4640           0 :         actRec_.define("origin","Calibrater::correct");
    4641           0 :         actRec_.defineRecord("VisEquation",ve_p->actionRec());
    4642             : 
    4643           0 :     }
    4644           0 :     catch (AipsError x) {
    4645             :         logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    4646           0 :                       << LogIO::POST;
    4647             : 
    4648           0 :         logSink() << "Resetting all calibration application settings." << LogIO::POST;
    4649           0 :         unsetapply();
    4650             : 
    4651           0 :         throw(AipsError("Error in Calibrater::correct."));
    4652             :         retval = false;         // Not that it ever gets here...
    4653           0 :     }
    4654           0 :     return retval;
    4655             : }
    4656             : 
    4657           0 : Bool OldCalibrater::corrupt() {
    4658             :   
    4659           0 :   logSink() << LogOrigin("Calibrater","corrupt") << LogIO::NORMAL;
    4660           0 :   Bool retval = true;
    4661             : 
    4662             :   try {
    4663             : 
    4664           0 :     if (!ok())
    4665           0 :       throw(AipsError("Calibrater not prepared for corrupt!"));
    4666             : 
    4667             :     // Nominally, we write out to the MODEL_DATA, unless absent
    4668           0 :     VisibilityIterator::DataColumn whichOutCol(VisibilityIterator::Model);
    4669             : 
    4670           0 :     if (!ms_p->tableDesc().isColumn("MODEL_DATA"))
    4671           0 :       throw(AipsError("MODEL_DATA column unexpectedly absent. Cannot corrupt."));
    4672             : 
    4673             :     // Ensure apply list non-zero and properly sorted
    4674           0 :     ve_p->setapply(vc_p);
    4675             : 
    4676             :     // Report the types that will be applied
    4677           0 :     applystate();
    4678             : 
    4679             :     // Arrange for iteration over data
    4680           0 :     Block<Int> columns;
    4681             :     // include scan iteration
    4682           0 :     columns.resize(5);
    4683           0 :     columns[0]=MS::ARRAY_ID;
    4684           0 :     columns[1]=MS::SCAN_NUMBER;
    4685           0 :     columns[2]=MS::FIELD_ID;
    4686           0 :     columns[3]=MS::DATA_DESC_ID;
    4687           0 :     columns[4]=MS::TIME;
    4688           0 :     vs_p->resetVisIter(columns,0.0);
    4689           0 :     VisIter& vi(vs_p->iter());
    4690           0 :     VisBuffer vb(vi);
    4691             :     
    4692             :     // Pass each timestamp (VisBuffer) to VisEquation for corruption.
    4693           0 :     Vector<Bool> uncalspw(vi.numberSpw());        // Used to accumulate error messages
    4694           0 :     uncalspw.set(false);                        // instead of bombing the user
    4695             :                                                 // in a loop.
    4696           0 :     for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    4697           0 :       Int spw = vi.spectralWindow();
    4698             : 
    4699             :       // Only proceed if spw can be calibrated
    4700           0 :       if (ve_p->spwOK(spw)) {
    4701             : 
    4702           0 :         for (vi.origin(); vi.more(); vi++) {
    4703             :           
    4704             :           // Corrupt the MODEL_DATA
    4705             :           //  (note we are not treating weights and flags)
    4706           0 :           ve_p->corrupt(vb);    // throws exception if nothing to apply
    4707           0 :           vi.setVis(vb.modelVisCube(),whichOutCol);
    4708             : 
    4709             :         }
    4710             :       }
    4711             :       else 
    4712           0 :         uncalspw[spw] = true;
    4713             :     }
    4714             :     // Flush to disk
    4715           0 :     vs_p->flush();
    4716             : 
    4717             :     // Now that we're out of the loop, summarize any errors.
    4718           0 :     retval = summarize_uncalspws(uncalspw, "corrupt");
    4719           0 :   }
    4720           0 :   catch (AipsError x) {
    4721             :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    4722           0 :               << LogIO::POST;
    4723             : 
    4724           0 :     logSink() << "Resetting all calibration application settings." << LogIO::POST;
    4725           0 :     unsetapply();
    4726             : 
    4727           0 :     throw(AipsError("Error in Calibrater::corrupt."));
    4728             :     retval = false;  // Not that it ever gets here...
    4729           0 :   } 
    4730           0 :   return retval;
    4731             : }
    4732             : 
    4733           0 : Bool OldCalibrater::initWeightsWithTsys(String wtmode, Bool dowtsp,
    4734             :                                         String tsystable, String gainfield, String interp, Vector<Int> spwmap) {
    4735             : 
    4736           0 :         logSink() << LogOrigin("Calibrater", "initWeightsWithTsys")
    4737           0 :                         << LogIO::NORMAL;
    4738           0 :         Bool retval = true;
    4739             : 
    4740             :         try {
    4741             : 
    4742           0 :                 if (!ok())
    4743           0 :                         throw(AipsError("Calibrater not prepared for initWeights!"));
    4744             : 
    4745           0 :                 String uptype = calTableType(tsystable);
    4746           0 :                 if (!uptype.contains("TSYS")) {
    4747           0 :                         throw(AipsError(
    4748           0 :                                         "Invalid calibration table type for Tsys weighting."));
    4749             :                 }
    4750             :                 // Set record format for calibration table application information
    4751           0 :                 RecordDesc applyparDesc;
    4752           0 :                 applyparDesc.addField("t", TpDouble);
    4753           0 :                 applyparDesc.addField("table", TpString);
    4754           0 :                 applyparDesc.addField("interp", TpString);
    4755           0 :                 applyparDesc.addField("spw", TpArrayInt);
    4756           0 :                 applyparDesc.addField("fieldstr", TpString);
    4757           0 :                 applyparDesc.addField("calwt", TpBool);
    4758           0 :                 applyparDesc.addField("spwmap", TpArrayInt);
    4759           0 :                 applyparDesc.addField("opacity", TpArrayDouble);
    4760             : 
    4761             :                 // Create record with the requisite field values
    4762           0 :                 Record applypar(applyparDesc);
    4763           0 :                 applypar.define("t", 0.0);
    4764           0 :                 applypar.define("table", tsystable);
    4765           0 :                 applypar.define("interp", interp);
    4766           0 :                 applypar.define("spw", getSpwIdx(""));
    4767           0 :                 applypar.define("fieldstr", gainfield);
    4768           0 :                 applypar.define("calwt", true);
    4769           0 :                 applypar.define("spwmap", spwmap);
    4770           0 :                 applypar.define("opacity", Vector<Double>(1, 0.0));
    4771             : 
    4772           0 :                 if (vc_p.nelements() > 0) {
    4773           0 :                         logSink() << LogIO::WARN << "Resetting all calibration application settings." << LogIO::POST;
    4774           0 :                         unsetapply();
    4775             :                 }
    4776           0 :                 logSink() << LogIO::NORMAL << "Weight initialization does not support selection. Resetting MS selection." << LogIO::POST;
    4777           0 :                 selectvis();
    4778           0 :                 StandardTsys vc = StandardTsys(*vs_p);
    4779           0 :                 vc.setApply(applypar);
    4780             : 
    4781           0 :                 logSink() << LogIO::NORMAL << ".   " << vc.applyinfo() << LogIO::POST;
    4782           0 :                 PtrBlock<VisCal*> vcb(1, &vc);
    4783             :                 // Maintain sort of apply list
    4784           0 :                 ve_p->setapply(vcb);
    4785             : 
    4786             :                 // Detect WEIGHT_SPECTRUM and SIGMA_SPECTRUM
    4787           0 :                 TableDesc mstd = ms_p->actualTableDesc();
    4788           0 :                 String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
    4789           0 :                 Bool wtspexists = mstd.isColumn(colWtSp);
    4790           0 :                 String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    4791           0 :                 Bool sigspexists = mstd.isColumn(colSigSp);
    4792           0 :                 Bool addsigsp = (dowtsp && !sigspexists);
    4793             : 
    4794             :                 // Some log info
    4795           0 :                 bool use_exposure = false;
    4796           0 :                 if (wtmode == "tsys") {
    4797             :                         logSink()
    4798             :                                         << "Initializing SIGMA and WEIGHT according to channel bandwidth and Tsys. NOTE this is an expert mode."
    4799           0 :                                         << LogIO::WARN << LogIO::POST;
    4800           0 :                 } else if (wtmode == "tinttsys") {
    4801             :                         logSink()
    4802             :                                         << "Initializing SIGMA and WEIGHT according to channel bandwidth, integration time, and Tsys. NOTE this is an expert mode."
    4803           0 :                                         << LogIO::WARN << LogIO::POST;
    4804           0 :                         use_exposure = true;
    4805             :                 } else {
    4806           0 :                         throw(AipsError("Unrecognized wtmode specified: " + wtmode));
    4807             :                 }
    4808             : 
    4809             :                 // Force dowtsp if the column already exists
    4810           0 :                 if (wtspexists && !dowtsp) {
    4811             :                         logSink() << "Found WEIGHT_SPECTRUM; will force its initialization."
    4812           0 :                                         << LogIO::POST;
    4813           0 :                         dowtsp = true;
    4814             :                 }
    4815             : 
    4816             :                 // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
    4817           0 :                 if (dowtsp) {
    4818             : 
    4819             :                         // Ensure WEIGHT_SPECTRUM really exists at all
    4820             :                         //   (often it exists but is empty)
    4821           0 :                         if (!wtspexists) {
    4822           0 :                                 logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
    4823             : 
    4824             :                                 // Nominal defaulttileshape
    4825           0 :                                 IPosition dts(3, 4, 32, 1024);
    4826             : 
    4827             :                                 // Discern DATA's default tile shape and use it
    4828           0 :                                 const Record dminfo = ms_p->dataManagerInfo();
    4829           0 :                                 for (uInt i = 0; i < dminfo.nfields(); ++i) {
    4830           0 :                                         Record col = dminfo.asRecord(i);
    4831             :                                         //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    4832           0 :                                         if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
    4833           0 :                                                 dts = IPosition(
    4834           0 :                                                                 col.asRecord("SPEC").asArrayInt(
    4835           0 :                                                                                 "DEFAULTTILESHAPE"));
    4836             :                                                 //cout << "Found DATA's default tile: " << dts << endl;
    4837           0 :                                                 break;
    4838             :                                         }
    4839           0 :                                 }
    4840             : 
    4841             :                                 // Add the column
    4842           0 :                                 String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
    4843           0 :                                 TableDesc tdWtSp;
    4844           0 :                                 tdWtSp.addColumn(
    4845           0 :                                                 ArrayColumnDesc<Float>(colWtSp, "weight spectrum", 2));
    4846           0 :                                 TiledShapeStMan wtSpStMan("TiledWgtSpectrum", dts);
    4847           0 :                                 ms_p->addColumn(tdWtSp, wtSpStMan);
    4848           0 :                         } else
    4849           0 :                                 logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
    4850             :                         // Ensure WEIGHT_SPECTRUM really exists at all
    4851             :                         //   (often it exists but is empty)
    4852           0 :                 if (!sigspexists) {
    4853           0 :                                 logSink() << "Creating SIGMA_SPECTRUM." << LogIO::POST;
    4854             : 
    4855             :                                 // Nominal defaulttileshape
    4856           0 :                                 IPosition dts(3, 4, 32, 1024);
    4857             : 
    4858             :                                 // Discern DATA's default tile shape and use it
    4859           0 :                                 const Record dminfo = ms_p->dataManagerInfo();
    4860           0 :                                 for (uInt i = 0; i < dminfo.nfields(); ++i) {
    4861           0 :                                         Record col = dminfo.asRecord(i);
    4862             :                                         //if (upcase(col.asString("NAME"))=="TILEDDATA") {
    4863           0 :                                         if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
    4864           0 :                                                 dts = IPosition(
    4865           0 :                                                                 col.asRecord("SPEC").asArrayInt(
    4866           0 :                                                                                 "DEFAULTTILESHAPE"));
    4867             :                                                 //cout << "Found DATA's default tile: " << dts << endl;
    4868           0 :                                                 break;
    4869             :                                         }
    4870           0 :                                 }
    4871             : 
    4872             :                                 // Add the column
    4873           0 :                                 String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    4874           0 :                                 TableDesc tdSigSp;
    4875           0 :                                 tdSigSp.addColumn(
    4876           0 :                                                 ArrayColumnDesc<Float>(colSigSp, "sigma spectrum", 2));
    4877           0 :                                 TiledShapeStMan sigSpStMan("TiledSigtSpectrum", dts);
    4878           0 :                                 ms_p->addColumn(tdSigSp, sigSpStMan);
    4879             :                                 {
    4880           0 :                                   TableDesc loctd = ms_p->actualTableDesc();
    4881           0 :                                   String loccolSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
    4882           0 :                                   AlwaysAssert(loctd.isColumn(loccolSigSp),AipsError);
    4883           0 :                                 }
    4884           0 :                 }
    4885             :                 }
    4886             :                 else {
    4887           0 :     if (sigspexists) {
    4888           0 :       logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
    4889             :       if (true || ms_p->canRemoveColumn(colSigSp)) {
    4890           0 :         ms_p->removeColumn(colSigSp);
    4891             :       }
    4892             :       else
    4893             :         logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
    4894             :     }
    4895             :                 }
    4896             : 
    4897             :                 // Arrange for iteration over data
    4898             :                 //  TBD: Be sure this sort is optimal for creating WS?
    4899           0 :                 Block<Int> columns;
    4900             :                 // include scan iteration
    4901           0 :                 columns.resize(5);
    4902           0 :                 columns[0] = MS::ARRAY_ID;
    4903           0 :                 columns[1] = MS::SCAN_NUMBER;
    4904           0 :                 columns[2] = MS::FIELD_ID;
    4905           0 :                 columns[3] = MS::DATA_DESC_ID;
    4906           0 :                 columns[4] = MS::TIME;
    4907             : 
    4908           0 :                 vi::SortColumns sc(columns);
    4909           0 :                 vi::VisibilityIterator2 vi2(*ms_p, sc, true);
    4910           0 :                 vi::VisBuffer2 *vb = vi2.getVisBuffer();
    4911             : 
    4912           0 :                 MSColumns mscol(*ms_p);
    4913           0 :                 const MSSpWindowColumns& msspw(mscol.spectralWindow());
    4914           0 :                 uInt nSpw = msspw.nrow();
    4915           0 :                 Vector<Double> effChBw(nSpw, 0.0);
    4916           0 :                 for (uInt ispw = 0; ispw < nSpw; ++ispw) {
    4917           0 :                         effChBw[ispw] = mean(msspw.effectiveBW()(ispw));
    4918             :                 }
    4919             : 
    4920           0 :                 Int ivb(0);
    4921           0 :                 for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
    4922             : 
    4923           0 :                         for (vi2.origin(); vi2.more(); vi2.next(), ++ivb) {
    4924             : 
    4925           0 :                                 Int spw = vb->spectralWindows()(0);
    4926             : 
    4927           0 :                                 auto nrow = vb->nRows();
    4928           0 :                                 Int nchan = vb->nChannels();
    4929           0 :                                 Int ncor = vb->nCorrelations();
    4930             : 
    4931             :                                 // Prepare for WEIGHT_SPECTRUM and SIGMA_SPECTRUM, if nec.
    4932           0 :                                 Cube<Float> newwtsp(0, 0, 0), newsigsp(0, 0, 0);
    4933           0 :                                 if (dowtsp) {
    4934           0 :                                   newwtsp.resize(ncor, nchan, nrow);
    4935           0 :                                   newwtsp.set(1.0);
    4936           0 :                                   newsigsp.resize(ncor, nchan, nrow);
    4937           0 :                                   newsigsp.set(1.0);
    4938             :                                 }
    4939             : 
    4940           0 :                                 if (ve_p->spwOK(spw)) {
    4941             : 
    4942             :                                         // Re-initialize weight info from sigma info
    4943             :                                         //   This is smart wrt spectral weights, etc.
    4944             :                                         //   (this makes W and WS, if present, "dirty" in the vb)
    4945             :                                         // TBD: only do this if !trial (else: avoid the I/O)
    4946             :                                         // vb->resetWeightsUsingSigma();
    4947             :                                         // Handle non-trivial modes
    4948             :                                         // Init WEIGHT, SIGMA  from bandwidth & time
    4949           0 :                                         Matrix<Float> newwt(ncor, nrow), newsig(ncor, nrow);
    4950           0 :                                         newwt.set(1.0);
    4951           0 :                                         newsig.set(1.0);
    4952             : 
    4953             :                                         // Detect ACs
    4954           0 :                                         const Vector<Int> a1(vb->antenna1());
    4955           0 :                                         const Vector<Int> a2(vb->antenna2());
    4956           0 :                                         Vector<Bool> ac(a1 == a2);
    4957             : 
    4958             :                                         // XCs need an extra factor of 2
    4959           0 :                                         Vector<Float> xcfactor(nrow, 2.0);
    4960           0 :                                         xcfactor(ac) = 1.0;                             // (but not ACs)
    4961             : 
    4962             :                                         // The row-wise integration time
    4963           0 :                                         Vector<Float> expo(nrow);
    4964           0 :                                         convertArray(expo, vb->exposure());
    4965             : 
    4966             :                                         // Set weights to channel bandwidth first.
    4967           0 :                                         newwt.set(Float(effChBw(spw)));
    4968             : 
    4969             :                                         // For each correlation, apply exposure and xcfactor
    4970           0 :                                         for (Int icor = 0; icor < ncor; ++icor) {
    4971             : 
    4972           0 :                                                 Vector<Float> wt(newwt.row(icor));
    4973           0 :                                                 if (use_exposure) {
    4974           0 :                                                         wt *= expo;
    4975             :                                                 }
    4976           0 :                                                 wt *= xcfactor;
    4977           0 :                                                 if (dowtsp) {
    4978           0 :                                                         for (Int ich = 0; ich < nchan; ++ich) {
    4979             :                                                                 Vector<Float> wtspi(
    4980           0 :                                                                                 newwtsp(Slice(icor, 1, 1),
    4981           0 :                                                                                                 Slice(ich, 1, 1), Slice()).nonDegenerate(
    4982           0 :                                                                                                 IPosition(1, 2)));
    4983           0 :                                                                 wtspi = wt;
    4984           0 :                                                         }
    4985             :                                                 }
    4986           0 :                                         }
    4987             :                                         // Handle SIGMA_SPECTRUM
    4988           0 :                                         if (dowtsp) {
    4989           0 :                                           newsigsp = 1.0f / sqrt(newwtsp);
    4990             :                                         }
    4991             :                                         // sig from wt is inverse sqrt
    4992           0 :                                         newsig = 1.0f / sqrt(newwt);
    4993             : 
    4994             :                                         // Arrange write-back of both SIGMA and WEIGHT
    4995           0 :                                         vb->setSigma(newsig);
    4996           0 :                                         vb->setWeight(newwt);
    4997           0 :                                         if (dowtsp) {
    4998           0 :                                           vb->initWeightSpectrum(newwtsp);
    4999           0 :                                           vb->initSigmaSpectrum(newsigsp);
    5000             :                                         }
    5001             :                                         // Force writeback to disk (need to initialize weight/sigma before applying cal table)
    5002           0 :                                         vb->writeChangesBack();
    5003             : 
    5004             :                                         // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
    5005             :                                         //   (this makes CD "dirty" in the vb)
    5006             :                                         // TBD: only do this if !trial (else: avoid the I/O)
    5007           0 :                                         vb->setVisCubeCorrected(vb->visCube());
    5008             : 
    5009             :                                         // Make flagcube dirty in the vb
    5010             :                                         //  NB: we must _always_ do this I/O  (even trial mode)
    5011           0 :                                         vb->setFlagCube(vb->flagCube());
    5012             : 
    5013             :                                         // Make all vb "not dirty"; we'll carefully arrange the writeback below
    5014           0 :                                         vb->dirtyComponentsClear();
    5015             : 
    5016             :                                         // throws exception if nothing to apply
    5017           0 :                                         ve_p->correct2(*vb, false, dowtsp);
    5018             : 
    5019           0 :                                         if (dowtsp) {
    5020           0 :                                                 vb->setWeightSpectrum(vb->weightSpectrum());
    5021             :                                                 // If WS was calibrated, set W to its channel-axis median
    5022           0 :                                                 vb->setWeight( partialMedians(vb->weightSpectrum(), IPosition(1, 1)) );
    5023           0 :                                                 newsigsp = 1.0f / sqrt(vb->weightSpectrum());
    5024           0 :                                                 vb->initSigmaSpectrum(newsigsp);
    5025           0 :                                                 vb->setSigma( partialMedians(newsigsp, IPosition(1, 1)) );
    5026             :                                         } else {
    5027           0 :                                                 vb->setWeight(vb->weight());
    5028           0 :                                                 newsig = 1.0f / sqrt(vb->weight());
    5029           0 :                                                 vb->setSigma(newsig);
    5030             :                                         }
    5031             :                                         // Force writeback to disk
    5032           0 :                                         vb->writeChangesBack();
    5033             : 
    5034           0 :                                 } else {//Not calibrating the spw
    5035           0 :                                   if (dowtsp && !wtspexists) {
    5036             :                                     // newly created WS Need to initialize
    5037           0 :                                     vb->initWeightSpectrum(newwtsp);
    5038             :                                   }
    5039           0 :                                   if (addsigsp) {
    5040             :                                     // newly created SS Need to initialize
    5041           0 :                                     vb->initSigmaSpectrum(newsigsp);
    5042           0 :                                     vb->writeChangesBack();
    5043             :                                   }
    5044             :                                 }
    5045           0 :                         }
    5046             :                 }
    5047             :                 // clear-up Tsys caltable from list of apply
    5048           0 :                 unsetapply();
    5049             : 
    5050           0 :         } catch (AipsError x) {
    5051             :                 logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    5052           0 :                                 << LogIO::POST;
    5053             : 
    5054             :                 logSink() << "Resetting all calibration application settings."
    5055           0 :                                 << LogIO::POST;
    5056           0 :                 unsetapply();
    5057             : 
    5058           0 :                 throw(AipsError("Error in Calibrater::initWeights."));
    5059             :                 retval = false;  // Not that it ever gets here...
    5060           0 :         }
    5061           0 :         return retval;
    5062             : }
    5063             : 
    5064           0 : Bool OldCalibrater::solve() {
    5065             : 
    5066           0 :   logSink() << LogOrigin("Calibrater","solve") << LogIO::NORMAL3;
    5067             : 
    5068             :   try {
    5069             : 
    5070           0 :     if (!ok()) 
    5071           0 :       throw(AipsError("Calibrater not prepared for solve."));
    5072             : 
    5073             :     // Handle nothing-to-solve-for case
    5074           0 :     if (!svc_p)
    5075           0 :       throw(AipsError("Please run setsolve before attempting to solve."));
    5076             : 
    5077             :     // Handle specified caltable
    5078           0 :     if (true && svc_p) {
    5079             : 
    5080             :       /*      
    5081             :       cout << "name: " << svc_p->calTableName() << endl;
    5082             :       cout << boolalpha;
    5083             :       cout << "append?   " << svc_p->append() << endl;
    5084             :       cout << "opened?   " << Table::isOpened(svc_p->calTableName()) << endl;
    5085             :       cout << "readable? " << Table::isReadable(svc_p->calTableName()) << endl;
    5086             :       //      cout << "writable? " << Table::isWritable(svc_p->calTableName()) << endl;
    5087             :       cout << "canDelete? " << Table::canDeleteTable(svc_p->calTableName(),true) << endl;
    5088             :       */
    5089             : 
    5090             :       // If table exists (readable) and not deletable
    5091             :       //   we have to abort (append=T requires deletable)
    5092           0 :       if ( Table::isReadable(svc_p->calTableName()) &&
    5093           0 :            !TableUtil::canDeleteTable(svc_p->calTableName()) ) {
    5094           0 :         throw(AipsError("Specified caltable ("+svc_p->calTableName()+") exists and\n cannot be replaced (or appended to) because it appears to be open somewhere (Quit plotcal?)."));
    5095             :       }
    5096             :     }
    5097             : 
    5098             :     // Arrange VisEquation for solve
    5099           0 :     ve_p->setsolve(*svc_p);
    5100             : 
    5101             :     // Ensure apply list properly sorted w.r.t. solvable term
    5102           0 :     ve_p->setapply(vc_p);
    5103             : 
    5104             :     // Report what is being applied and solved-for
    5105           0 :     applystate();
    5106           0 :     solvestate();
    5107             : 
    5108             : 
    5109             :     // Report correct/corrupt apply order
    5110             :     //    ve_p->state();
    5111             : 
    5112             :     // Set the channel mask
    5113           0 :     svc_p->setChanMask(chanmask_);
    5114             : 
    5115             :     // Generally use standard solver
    5116           0 :     if (svc_p->useGenericGatherForSolve())
    5117           0 :       genericGatherAndSolve();   // using VisBuffGroupAcc
    5118             :     else {
    5119             :       //cout << "Fully self-directed data gather and solve" << endl;
    5120             :       // Fully self-directed data gather and solve
    5121           0 :       svc_p->selfGatherAndSolve(*vs_p,*ve_p);
    5122             :     }
    5123             : 
    5124           0 :     svc_p->clearChanMask();
    5125             : 
    5126           0 :   } catch (AipsError x) {
    5127           0 :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
    5128             : 
    5129           0 :     logSink() << "Reseting entire solve/apply state." << LogIO::POST;
    5130           0 :     reset();
    5131             : 
    5132           0 :     throw(AipsError("Error in Calibrater::solve."));
    5133             :     return false;
    5134           0 :   } 
    5135             : 
    5136           0 :   return true;
    5137             : 
    5138             : }
    5139             : 
    5140           0 : Vector<Double> OldCalibrater::modelfit(const Int& niter,
    5141             :                                        const String& stype,
    5142             :                                        const Vector<Double>& par,
    5143             :                                        const Vector<Bool>& vary,
    5144             :                                        const String& file) {
    5145             : 
    5146             :  /*
    5147             :   cout << "Calibrater::modelfit" << endl;
    5148             :   cout << " niter = " << niter << endl;
    5149             :   cout << " stype = " << stype << endl;
    5150             :   cout << " par   = " << par << endl;
    5151             :   cout << " vary  = " << vary << endl;
    5152             :   cout << " file  = " << file << endl;
    5153             :  */
    5154             :   //  logSink() << LogOrigin("Calibrater","modelfit") << LogIO::NORMAL;
    5155             :   
    5156             :   try {
    5157           0 :     if(!ok()) throw(AipsError("Calibrater not ok()"));
    5158             : 
    5159             :     // Construct UVMod with the VisSet
    5160           0 :     UVMod uvmod(*vs_p);
    5161             : 
    5162           0 :     if (stype=="P")
    5163           0 :       uvmod.setModel(ComponentType::POINT, par, vary);
    5164           0 :     else if (stype=="G")
    5165           0 :       uvmod.setModel(ComponentType::GAUSSIAN, par, vary);
    5166           0 :     else if (stype=="D")
    5167           0 :       uvmod.setModel(ComponentType::DISK, par, vary);
    5168             :     else
    5169           0 :       throw(AipsError("Unrecognized component type in Calibrater::modelfit."));
    5170             :     
    5171             :     // Run the fit
    5172           0 :     uvmod.modelfit(niter,file);
    5173             : 
    5174             :     // Return the parameter vector
    5175           0 :     return uvmod.par();
    5176             : 
    5177           0 :   } catch (AipsError x) {
    5178           0 :     logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
    5179           0 :     throw(AipsError("Error in Calibrater::modelfit."));
    5180             :     
    5181             :     return Vector<Double>();
    5182           0 :   } 
    5183             : 
    5184             : }
    5185             : 
    5186           0 : void OldCalibrater::fluxscale(const String& infile, 
    5187             :                               const String& outfile,
    5188             :                               const Vector<Int>& refField, 
    5189             :                               const Vector<Int>& refSpwMap, 
    5190             :                               const Vector<Int>& tranField,
    5191             :                               const Bool& append,
    5192             :                               const Float& inGainThres,
    5193             :                               const String& antSel,
    5194             :                               const String& timerangeSel,
    5195             :                               const String& scanSel,
    5196             :                               SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
    5197             :                               const String& oListFile,
    5198             :                               const Bool& incremental,
    5199             :                               const Int& fitorder,
    5200             :                               const Bool& display) {
    5201             : 
    5202             :   //  throw(AipsError("Method 'fluxscale' is temporarily disabled."));
    5203             : 
    5204             :   // TBD: write inputs to MSHistory
    5205           0 :   logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
    5206             : 
    5207           0 :   SolvableVisCal *fsvj_(NULL);
    5208             :   try {
    5209             :     // If infile is Calibration table
    5210           0 :     if (Table::isReadable(infile) && 
    5211           0 :         TableUtil::tableInfo(infile).type()=="Calibration") {
    5212             : 
    5213             :       // get calibration type
    5214           0 :       String caltype;
    5215           0 :       caltype = TableUtil::tableInfo(infile).subType();
    5216             :       logSink() << "Table " << infile 
    5217             :                 << " is of type: "<< caltype 
    5218           0 :                 << LogIO::POST;
    5219           0 :       String message="Table "+infile+" is of type: "+caltype;
    5220           0 :       MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    5221             :       
    5222             :       // form selection
    5223           0 :       String select="";
    5224             :       // Selection is empty for case of no tran specification
    5225           0 :       if (tranField.nelements()>0) {
    5226             :         
    5227             :         // All selected fields
    5228           0 :         Vector<Int> allflds = concatenateArray(refField,tranField);
    5229             :         
    5230             :         // Assemble TaQL
    5231           0 :         ostringstream selectstr;
    5232           0 :         selectstr << "FIELD_ID IN [";
    5233           0 :         for (Int iFld=0; iFld<allflds.shape(); iFld++) {
    5234           0 :           if (iFld>0) selectstr << ", ";
    5235           0 :           selectstr << allflds(iFld);
    5236             :         }
    5237           0 :         selectstr << "]";
    5238           0 :         select=selectstr.str();
    5239           0 :       }
    5240             : 
    5241             :       // Construct proper SVC object
    5242           0 :       if (caltype == "G Jones") {
    5243           0 :         fsvj_ = createSolvableVisCal("G",*vs_p);
    5244           0 :       } else if (caltype == "T Jones") {
    5245           0 :         fsvj_ = createSolvableVisCal("T",*vs_p);
    5246             :       } else {
    5247             :         // Can't process other than G and T (add B?)
    5248           0 :         ostringstream typeErr;
    5249           0 :         typeErr << "Type " << caltype 
    5250           0 :                << " not supported in fluxscale.";
    5251             : 
    5252           0 :         throw(AipsError(typeErr.str()));
    5253           0 :       }
    5254             : 
    5255             :       // fill table with selection
    5256           0 :       RecordDesc applyparDesc;
    5257           0 :       applyparDesc.addField ("table", TpString);
    5258           0 :       applyparDesc.addField ("select", TpString);
    5259           0 :       Record applypar(applyparDesc);
    5260           0 :       applypar.define ("table", infile);
    5261           0 :       applypar.define ("select", select);
    5262           0 :       fsvj_->setApply(applypar);
    5263             : 
    5264             :       //Bool incremental=false;
    5265             :       // Make fluxscale calculation
    5266           0 :       Vector<String> fldnames(MSFieldColumns(ms_p->field()).name().getColumn());
    5267             :       //fsvj_->fluxscale(refField,tranField,refSpwMap,fldnames,oFluxScaleFactor,
    5268           0 :       fsvj_->fluxscale(outfile,refField,tranField,refSpwMap,fldnames,inGainThres,antSel,
    5269             :         timerangeSel,scanSel,oFluxScaleFactor, oListFile,incremental,fitorder,display);
    5270             : //        oListFile);
    5271             :      
    5272             :       // If no outfile specified, use infile (overwrite!)
    5273           0 :       String out(outfile);
    5274           0 :       if (out.length()==0)
    5275           0 :         out = infile;
    5276             : 
    5277             :       // Store result
    5278           0 :       if (append) {
    5279           0 :         logSink() << "Appending result to " << out << LogIO::POST;
    5280           0 :         String message="Appending result to "+out;
    5281           0 :         MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    5282           0 :       } else {
    5283           0 :         logSink() << "Storing result in " << out << LogIO::POST;
    5284           0 :         String message="Storing result in "+out;
    5285           0 :         MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    5286           0 :       }
    5287           0 :       fsvj_->storeNCT(out,append);
    5288             :       
    5289             :       // Clean up
    5290           0 :       delete fsvj_;
    5291             : 
    5292           0 :     } else {
    5293             :       // Table not found/unreadable, or not Calibration
    5294           0 :       ostringstream tabErr;
    5295           0 :       tabErr << "File " << infile
    5296           0 :              << " does not exist or is not a Calibration Table.";
    5297             : 
    5298           0 :       throw(AipsError(tabErr.str()));
    5299             : 
    5300           0 :     }
    5301           0 :   } catch (AipsError x) {
    5302             : 
    5303             :     logSink() << LogIO::SEVERE
    5304             :               << "Caught Exception: "
    5305             :               << x.getMesg()
    5306           0 :               << LogIO::POST;
    5307             :     
    5308             :     // Clean up
    5309           0 :     if (fsvj_) delete fsvj_;
    5310             : 
    5311             :     // Write to MS History table
    5312             :     //    String message="Caught Exception: "+x.getMesg();
    5313             :     //    MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
    5314             : 
    5315           0 :     throw(AipsError("Error in Calibrater::fluxscale."));
    5316             : 
    5317             :     return;
    5318             : 
    5319           0 :   }
    5320           0 :   return;
    5321             : 
    5322             : 
    5323             : }
    5324             : 
    5325           0 : void OldCalibrater::accumulate(const String& intab,
    5326             :                                const String& incrtab,
    5327             :                                const String& outtab,
    5328             :                                const String& fields,
    5329             :                                const String& calFields,
    5330             :                                const String& interp,
    5331             :                                const Double& t,
    5332             :                                const Vector<Int>& spwmap) {
    5333             :   
    5334             :   //  logSink() << LogOrigin("Calibrater","accumulate") << LogIO::NORMAL;
    5335             : 
    5336           0 :   logSink() << "Beginning accumulate." << LogIO::POST;
    5337             : 
    5338             :   // SVJ objects:
    5339           0 :   SolvableVisCal *incal_(NULL), *incrcal_(NULL);
    5340             : 
    5341             :   try {
    5342             :     
    5343             :   /*
    5344             :     cout << "intab     = " << intab << endl;
    5345             :     cout << "incrtab   = " << incrtab << endl;
    5346             :     cout << "outtab    = " << outtab << endl;
    5347             :     cout << "fields    = " << fields << endl;
    5348             :     cout << "calFields = " << calFields << endl;
    5349             :     cout << "interp    = " << interp << endl;
    5350             :     cout << "t         = " << t << endl;
    5351             :   */
    5352             : 
    5353             :     // Incremental table's type sets the type we are dealing with
    5354           0 :     String caltype=calTableType(incrtab);
    5355             : 
    5356             :     // If no input cumulative timescale specified, then
    5357             :     //   a valid input cumulative table must be specified
    5358           0 :     if (t < 0.0) {
    5359             : 
    5360           0 :       String intype=calTableType(intab);
    5361             : 
    5362           0 :       if (intype!=caltype) {
    5363             :       
    5364           0 :         ostringstream typeErr;
    5365           0 :         typeErr << "Table " << intab
    5366           0 :                 << " is not the same type as "
    5367           0 :                 << incrtab << " (" << caltype << ")";
    5368           0 :         throw(AipsError(typeErr.str()));
    5369           0 :       }
    5370           0 :     }
    5371             : 
    5372             :     // At this point all is ok; we will:
    5373             :     //  o fill from intab and accumulate to it (t<0), OR
    5374             :     //  o create a new cumulative table from scratch (t>0)
    5375             : 
    5376             :     // If creating a new cumulative table, it must span the whole dataset,
    5377             :     //   so reset data selection to whole MS, and setup iterator
    5378           0 :     if (t>0.0) {
    5379           0 :       selectvis();
    5380           0 :       Block<Int> columns;
    5381           0 :       columns.resize(4);
    5382           0 :       columns[0]=MS::ARRAY_ID;
    5383           0 :       columns[1]=MS::TIME;
    5384           0 :       columns[2]=MS::FIELD_ID;
    5385           0 :       columns[3]=MS::DATA_DESC_ID;
    5386           0 :       vs_p->resetVisIter(columns,t);
    5387           0 :     }
    5388             : 
    5389             :     //  logSink() << "Table " << infile 
    5390             :     //            << " is of type: "<< caltype 
    5391             :     //            << LogIO::POST;
    5392             : 
    5393           0 :     incal_ = createSolvableVisCal(caltype,*vs_p);
    5394           0 :     incrcal_ = createSolvableVisCal(caltype,*vs_p);
    5395             :     
    5396             :     // TBD: move to svj.setAccumulate?
    5397           0 :     if ( !(incal_->accumulatable()) ) {
    5398           0 :       ostringstream typeErr;
    5399           0 :       typeErr << "Type " << caltype 
    5400           0 :               << " not yet supported in accumulate.";
    5401           0 :       throw(AipsError(typeErr.str()));
    5402           0 :     }
    5403             : 
    5404             :     // At this point, accumulation apparently supported,
    5405             :     //   so continue...
    5406             :     
    5407             :     // initialize the cumulative solutions
    5408           0 :     incal_->setAccumulate(*vs_p,intab,"",t,-1);
    5409             :     
    5410             : 
    5411             :     /*
    5412             :     // form selection on incr table
    5413             :     String incrSel="";
    5414             :     if (calFields.shape()>0) {
    5415             :       
    5416             :       // Assemble TaQL
    5417             :       ostringstream selectstr;
    5418             :       selectstr << "FIELD_ID IN [";
    5419             :       for (Int iFld=0; iFld<calFields.shape(); iFld++) {
    5420             :         if (iFld>0) selectstr << ", ";
    5421             :         selectstr << calFields(iFld);
    5422             :       }
    5423             :       selectstr << "]";
    5424             :       incrSel=selectstr.str();
    5425             :     }
    5426             :     */
    5427             :     
    5428             :     // fill incr table with selection
    5429             :     logSink() << "Preparing to accumulate calibration from table: "
    5430             :               << incrtab
    5431           0 :               << LogIO::POST;
    5432             : 
    5433             :     // Set record format for calibration table application information
    5434           0 :     RecordDesc applyparDesc;
    5435           0 :     applyparDesc.addField ("t", TpDouble);
    5436           0 :     applyparDesc.addField ("table", TpString);
    5437             :     //    applyparDesc.addField ("select", TpString);
    5438           0 :     applyparDesc.addField ("fieldstr", TpString);
    5439           0 :     applyparDesc.addField ("interp", TpString);
    5440           0 :     applyparDesc.addField ("spwmap",TpArrayInt);
    5441             :     
    5442             :     // Create record with the requisite field values
    5443           0 :     Record applypar(applyparDesc);
    5444           0 :     applypar.define ("t", t);
    5445           0 :     applypar.define ("table", incrtab);
    5446             :     //    applypar.define ("select", incrSel);
    5447           0 :     applypar.define ("fieldstr", calFields);
    5448           0 :     applypar.define ("interp", interp);
    5449           0 :     applypar.define ("spwmap",spwmap);
    5450             : 
    5451           0 :     incrcal_->setApply(applypar);
    5452             : 
    5453           0 :     Vector<Int> fldidx(0);
    5454           0 :     if (fields.length()>0)
    5455           0 :       fldidx=getFieldIdx(fields);
    5456             : 
    5457             :     // All ready, now do the accumulation
    5458           0 :     incal_->accumulate(incrcal_,fldidx);
    5459             :     
    5460             :     // ...and store the result
    5461             :     logSink() << "Storing accumulated calibration in table: " 
    5462             :               << outtab
    5463           0 :               << LogIO::POST;
    5464             : 
    5465           0 :     if (outtab != "") 
    5466           0 :       incal_->calTableName()=outtab;
    5467             : 
    5468           0 :     incal_->storeNCT();
    5469             :     
    5470           0 :     delete incal_;
    5471           0 :     delete incrcal_;
    5472             : 
    5473             :     logSink() << "Finished accumulation." 
    5474           0 :               << LogIO::POST;
    5475             : 
    5476           0 :   } catch (AipsError x) {
    5477             :     logSink() << LogIO::SEVERE
    5478             :               << "Caught Exception: "
    5479             :               << x.getMesg()
    5480           0 :               << LogIO::POST;
    5481             : 
    5482           0 :     if (incal_) delete incal_;
    5483           0 :     if (incrcal_) delete incrcal_;
    5484             :     
    5485           0 :     throw(AipsError("Error in Calibrater::accumulate."));
    5486             :     return;
    5487           0 :   }
    5488           0 :   return;
    5489             : 
    5490             : }
    5491             : 
    5492           0 : void OldCalibrater::specifycal(const String& type,
    5493             :                                const String& caltable,
    5494             :                                const String& time,
    5495             :                                const String& spw,
    5496             :                                const String& antenna,
    5497             :                                const String& pol,
    5498             :                                const Vector<Double>& parameter,
    5499             :                                const String& infile,
    5500             :                                const Bool& uniform) {
    5501             : 
    5502           0 :   logSink() << LogOrigin("Calibrater","specifycal") << LogIO::NORMAL;
    5503             : 
    5504             :   // SVJ objects:
    5505           0 :   SolvableVisCal *cal_(NULL);
    5506             : 
    5507             :   try {
    5508             :                             
    5509             :     // Set record format for calibration table application information
    5510           0 :     RecordDesc specifyDesc;
    5511           0 :     specifyDesc.addField ("caltable", TpString);
    5512           0 :     specifyDesc.addField ("time", TpString);
    5513           0 :     specifyDesc.addField ("spw", TpArrayInt);
    5514           0 :     specifyDesc.addField ("antenna", TpArrayInt);
    5515           0 :     specifyDesc.addField ("pol", TpString);
    5516           0 :     specifyDesc.addField ("parameter", TpArrayDouble);
    5517           0 :     specifyDesc.addField ("caltype",TpString);
    5518           0 :     specifyDesc.addField ("infile",TpString);
    5519           0 :     specifyDesc.addField ("uniform",TpBool);
    5520             : 
    5521             :     // Create record with the requisite field values
    5522           0 :     Record specify(specifyDesc);
    5523           0 :     specify.define ("caltable", caltable);
    5524           0 :     specify.define ("time", time);
    5525           0 :     if (spw=="*")
    5526           0 :       specify.define ("spw",Vector<Int>(1,-1));
    5527             :     else
    5528           0 :       specify.define ("spw",getSpwIdx(spw));
    5529           0 :     if (antenna=="*")
    5530           0 :       specify.define ("antenna",Vector<Int>(1,-1) );
    5531             :     else
    5532           0 :       specify.define ("antenna",getAntIdx(antenna));
    5533           0 :     specify.define ("pol",pol);
    5534           0 :     specify.define ("parameter",parameter);
    5535           0 :     specify.define ("caltype",type);
    5536           0 :     specify.define ("infile",infile);
    5537           0 :     specify.define ("uniform",uniform);
    5538             : 
    5539             :     // Now do it
    5540           0 :     String utype=upcase(type);
    5541           0 :     if (utype=="G" || utype.contains("AMP") || utype.contains("PH"))
    5542           0 :       cal_ = createSolvableVisCal("G",*vs_p);
    5543           0 :     else if (utype=='K' || utype.contains("SBD") || utype.contains("DELAY"))
    5544           0 :       cal_ = createSolvableVisCal("K",*vs_p);
    5545           0 :     else if (utype.contains("MBD"))
    5546           0 :       cal_ = createSolvableVisCal("K",*vs_p);  // as of 5.3, KMBD is just K
    5547           0 :     else if (utype.contains("ANTPOS"))
    5548           0 :       cal_ = createSolvableVisCal("KANTPOS",*vs_p);
    5549           0 :     else if (utype.contains("TSYS"))
    5550           0 :       cal_ = createSolvableVisCal("TSYS",*vs_p);
    5551           0 :     else if (utype.contains("EVLAGAIN") ||
    5552           0 :              utype.contains("SWP") ||
    5553           0 :              utype.contains("RQ"))
    5554           0 :       cal_ = createSolvableVisCal("EVLASWP",*vs_p);
    5555           0 :     else if (utype.contains("OPAC"))
    5556           0 :       cal_ = createSolvableVisCal("TOPAC",*vs_p);
    5557           0 :     else if (utype.contains("GC") || utype.contains("EFF"))
    5558           0 :       cal_ = createSolvableVisCal("GAINCURVE",*vs_p);
    5559           0 :     else if (utype.contains("TEC"))
    5560           0 :       cal_ = createSolvableVisCal("TEC",*vs_p);
    5561           0 :     else if (utype.contains("SDSKY_PS"))
    5562           0 :       cal_ = createSolvableVisCal("SDSKY_PS",*vs_p);
    5563           0 :     else if (utype.contains("SDSKY_RASTER"))
    5564           0 :       cal_ = createSolvableVisCal("SDSKY_RASTER",*vs_p);
    5565           0 :     else if (utype.contains("SDSKY_OTF"))
    5566           0 :       cal_ = createSolvableVisCal("SDSKY_OTF",*vs_p);
    5567             :     else
    5568           0 :       throw(AipsError("Unrecognized caltype."));
    5569             : 
    5570             :     // set up for specification (set up the CalSet)
    5571           0 :     cal_->setSpecify(specify);
    5572             : 
    5573             :     // fill with specified values
    5574           0 :     cal_->specify(specify);
    5575             : 
    5576             :     // Store result
    5577           0 :     cal_->storeNCT();
    5578             : 
    5579           0 :     delete cal_;
    5580             : 
    5581           0 :   } catch (AipsError x) {
    5582             :     logSink() << LogIO::SEVERE
    5583             :               << "Caught Exception: "
    5584             :               << x.getMesg()
    5585           0 :               << LogIO::POST;
    5586             : 
    5587           0 :     if (cal_) delete cal_;
    5588             :     
    5589           0 :     throw(AipsError("Error in Calibrater::specifycal."));
    5590             :     return;
    5591           0 :   }
    5592           0 :   return;
    5593             : 
    5594             : }
    5595             : 
    5596           0 : Bool OldCalibrater::smooth(const String& infile, 
    5597             :                            String& outfile,  // const Bool& append,
    5598             :                            const String& smoothtype,
    5599             :                            const Double& smoothtime,
    5600             :                            const String& fields,
    5601             :          const bool ratesmooth)
    5602             : {
    5603             : 
    5604             :   // TBD: support append?
    5605             :   // TBD: spw selection?
    5606             : 
    5607           0 :   logSink() << LogOrigin("Calibrater","smooth") << LogIO::NORMAL;
    5608             : 
    5609           0 :   logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
    5610             : 
    5611             : 
    5612             :   // A pointer to an SVC
    5613           0 :   SolvableVisCal *svc(NULL);
    5614             : 
    5615             :   try {
    5616             :     
    5617             :     // Handle no in file 
    5618           0 :     if (infile=="")
    5619           0 :       throw(AipsError("Please specify an input calibration table."));
    5620             : 
    5621             :     // Handle bad smoothtype
    5622           0 :     if (smoothtype!="mean" && smoothtype!="median")
    5623           0 :       throw(AipsError("Unrecognized smooth type!"));
    5624             : 
    5625             :     // Handle bad smoothtime
    5626           0 :     if (smoothtime<=0)
    5627           0 :       throw(AipsError("Please specify a strictly positive smoothtime."));
    5628             : 
    5629             :     // Handle no outfile
    5630           0 :     if (outfile=="") {
    5631           0 :       outfile=infile;
    5632             :       logSink() << "Will overwrite input file with smoothing result." 
    5633           0 :                 << LogIO::POST;
    5634             :     }
    5635             : 
    5636             : 
    5637           0 :     svc = createSolvableVisCal(calTableType(infile),*vs_p);
    5638             :     
    5639           0 :     if (svc->smoothable()) {
    5640             :       
    5641             :       // Fill calibration table using setApply
    5642           0 :       RecordDesc applyparDesc;
    5643           0 :       applyparDesc.addField ("table", TpString);
    5644           0 :       Record applypar(applyparDesc);
    5645           0 :       applypar.define ("table", infile);
    5646           0 :       svc->setApply(applypar);
    5647             : 
    5648             :       // Convert refFields/transFields to index lists
    5649           0 :       Vector<Int> fldidx(0);
    5650           0 :       if (fields.length()>0)
    5651           0 :         fldidx=getFieldIdx(fields);
    5652             : 
    5653             :       // Delegate to SVC
    5654           0 :       svc->smooth(fldidx,smoothtype,smoothtime,ratesmooth);
    5655             :       
    5656             :       // Store the result on disk
    5657             :       //    if (append) logSink() << "Appending result to " << outfile << LogIO::POST;
    5658             :       //else 
    5659           0 :       logSink() << "Storing result in " << outfile << LogIO::POST;
    5660             :       
    5661             :       
    5662           0 :       if (outfile != "") 
    5663           0 :         svc->calTableName()=outfile;
    5664           0 :       svc->storeNCT();
    5665             : 
    5666             :       // Clean up
    5667           0 :       if (svc) delete svc; svc=NULL;
    5668             :       
    5669             :       // Apparently, it worked
    5670           0 :       return true;
    5671             : 
    5672           0 :     }
    5673             :     else
    5674           0 :       throw(AipsError("This type ("+svc->typeName()+") does not support smoothing."));
    5675             : 
    5676           0 :   } catch (AipsError x) {
    5677             :    
    5678             :     logSink() << LogIO::SEVERE
    5679             :               << "Caught Exception: "
    5680             :               << x.getMesg()
    5681           0 :               << LogIO::POST;
    5682             :     // Clean up
    5683           0 :     if (svc) delete svc; svc=NULL;
    5684             : 
    5685           0 :     throw(AipsError("Error in Calibrater::smooth."));
    5686             : 
    5687             :     return false;
    5688           0 :   }
    5689             :   return false;
    5690             : }
    5691             : 
    5692             : // List a calibration table
    5693           0 : Bool OldCalibrater::listCal(const String& infile,
    5694             :                             const String& field,
    5695             :                             const String& antenna,
    5696             :                             const String& spw,
    5697             :                             const String& listfile,
    5698             :                             const Int& pagerows) {
    5699             :     
    5700           0 :     SolvableVisCal *svc(NULL);
    5701           0 :     logSink() << LogOrigin("Calibrater","listCal");
    5702             :     
    5703             :     try {
    5704             :         
    5705             :         // Trap (currently) unsupported types
    5706           0 :         if (upcase(calTableType(infile))=="GSPLINE" ||
    5707           0 :             upcase(calTableType(infile))=="BPOLY")
    5708           0 :             throw(AipsError("GSPLINE and BPOLY tables cannot currently be listed."));
    5709             :         
    5710             :         // Get user's selected fields, ants
    5711           0 :         Vector<Int> ufldids=getFieldIdx(field);
    5712           0 :         Vector<Int> uantids=getAntIdx(antenna);
    5713             :         
    5714           0 :         String newSpw = spw;
    5715           0 :         Bool defaultSelect = false;
    5716           0 :         if (spw.empty()) { // list all channels (default)
    5717           0 :             defaultSelect = true;
    5718           0 :             newSpw = "*"; 
    5719             :             logSink() << LogIO::NORMAL1 << "Spws selected: ALL" << endl
    5720           0 :                       << "Channels selected: ALL" << LogIO::POST;
    5721             :         }
    5722             :         // Get user's selected spw and channels
    5723           0 :         Vector<Int> uspwids=getSpwIdx(newSpw);
    5724           0 :         Matrix<Int> uchanids=getChanIdx(newSpw);
    5725           0 :         if (!defaultSelect) {
    5726             :             logSink() << LogIO::NORMAL1 << "Spw and Channel selection matrix: "
    5727             :                       << endl << "Each rows shows: [ Spw , Start Chan , Stop Chan , Chan Step ]"
    5728           0 :                       << endl << uchanids << LogIO::POST;
    5729             :         }
    5730             :         logSink() << LogIO::DEBUG2 
    5731             :                   << "uspwids = "  << uspwids  << endl
    5732           0 :                   << "uchanids = " << uchanids << LogIO::POST;
    5733             :         
    5734             :         // By default, do first spw, first chan
    5735           0 :         if (uspwids.nelements()==0) {
    5736           0 :             uchanids.resize(1,4);
    5737           0 :             uchanids=0;
    5738             :         } 
    5739             :         
    5740             :         // Set record format for calibration table application information
    5741           0 :         RecordDesc applyparDesc;
    5742           0 :         applyparDesc.addField ("table", TpString);
    5743             :         
    5744             :         // Create record with the requisite field values
    5745           0 :         Record applypar(applyparDesc);
    5746           0 :         applypar.define ("table", infile);
    5747             :         
    5748             :         // Generate the VisCal to be listed
    5749           0 :         svc = createSolvableVisCal(calTableType(infile),*vs_p);  
    5750           0 :         svc->setApply(applypar);       
    5751             :         
    5752             :         // list it
    5753           0 :         svc->listCal(ufldids,uantids,uchanids,  //uchanids(0,0),uchanids(0,1),
    5754             :                      listfile,pagerows);
    5755             :         
    5756           0 :         if (svc) delete svc; svc=NULL;
    5757             :         
    5758           0 :         return true;
    5759             :         
    5760           0 :     } catch (AipsError x) {
    5761             :         
    5762             :         logSink() << LogIO::SEVERE
    5763             :                   << "Caught Exception: "
    5764             :                   << x.getMesg()
    5765           0 :                   << LogIO::POST;
    5766             :         // Clean up
    5767           0 :         if (svc) delete svc; svc=NULL;
    5768             :         
    5769           0 :         throw(AipsError("Error in Calibrater::listCal."));
    5770             :         
    5771             :         return false;
    5772           0 :     }
    5773             :     return false;
    5774             :     
    5775             : }
    5776             : 
    5777           0 : Bool OldCalibrater::initialize(MeasurementSet& inputMS, 
    5778             :                                Bool compress,
    5779             :                                Bool addScratch, Bool addModel)  {
    5780             :   
    5781           0 :   logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL3;
    5782             :   
    5783             :   try {
    5784           0 :     timer_p.mark();
    5785             : 
    5786             :     // Set pointer ms_p from input MeasurementSet
    5787           0 :     if (ms_p) {
    5788           0 :       *ms_p=inputMS;
    5789             :     } else {
    5790           0 :       ms_p = new MeasurementSet(inputMS);
    5791           0 :       AlwaysAssert(ms_p,AipsError);
    5792             :     };
    5793             : 
    5794             :     // Disabled 2016/04/19 (gmoellen): avoid direct MS.HISTORY 
    5795             :     //   updates from below the python level, FOR NOW
    5796             : 
    5797             :     /*
    5798             : 
    5799             :     // Setup to write LogIO to HISTORY Table in MS
    5800             :     if(!(Table::isReadable(ms_p->historyTableName()))){
    5801             :       // create a new HISTORY table if its not there
    5802             :       TableRecord &kws = ms_p->rwKeywordSet();
    5803             :       SetupNewTable historySetup(ms_p->historyTableName(),
    5804             :                                  MSHistory::requiredTableDesc(),Table::New);
    5805             :       kws.defineTable(MS::keywordName(MS::HISTORY), Table(historySetup));
    5806             :       MSHistoryHandler::addMessage(*ms_p, "HISTORY Table added by Calibrater",
    5807             :                                    "Calibrater","","Calibrater::initialize()");
    5808             :     }
    5809             :     historytab_p=Table(ms_p->historyTableName(),
    5810             :                        TableLock(TableLock::UserNoReadLocking), Table::Update);
    5811             :     // jagonzal (CAS-4110): When the selectvis method throws an exception the initialize method
    5812             :     // is called again to leave the calibrater in a proper state, and since there was a previous
    5813             :     // initialization the history handler was already created, and has to be destroyed before
    5814             :     // creating a new one to avoid leaveing the HISTORY table opened.
    5815             :     if (hist_p) delete hist_p;
    5816             :     hist_p= new MSHistoryHandler(*ms_p, "calibrater");
    5817             : 
    5818             :     // (2016/04/19) */
    5819             : 
    5820             :     // Remember the ms's name
    5821           0 :     msname_p=ms_p->tableName();
    5822             : 
    5823             : 
    5824             :     // Add/init scr cols, if requested (init is hard-wired)
    5825           0 :     if (addScratch || addModel) {
    5826           0 :       Bool alsoinit=true;
    5827           0 :       VisSetUtil::addScrCols(*ms_p,addModel,addScratch,alsoinit,compress);
    5828             :     }
    5829             : 
    5830             :     // Set the selected MeasurementSet to be the same initially
    5831             :     // as the input MeasurementSet
    5832           0 :     if (mssel_p) delete mssel_p;
    5833           0 :     mssel_p=new MeasurementSet(*ms_p);
    5834             :     
    5835             :     logSink() << LogIO::NORMAL
    5836             :               << "Initializing nominal selection to the whole MS."
    5837           0 :               << LogIO::POST;
    5838             : 
    5839             : 
    5840             :     // Create a VisSet with no selection
    5841             :     // (gmoellen 2012/02/06: this merely makes a VisIter now)
    5842           0 :     if (vs_p) {
    5843           0 :       delete vs_p;
    5844           0 :       vs_p=0;
    5845             :     };
    5846           0 :     Block<Int> nosort(0);
    5847           0 :     Matrix<Int> noselection;
    5848           0 :     Double timeInterval=0;
    5849             :     // gmoellen 2012/02/06    vs_p=new VisSet(*ms_p,nosort,noselection,addScratch,timeInterval,compress, addModel);
    5850           0 :     vs_p=new VisSet(*ms_p,nosort,noselection,false,timeInterval,false,false);
    5851             : 
    5852             :     // Size-up the chanmask PB
    5853           0 :     initChanMask();
    5854             : 
    5855             :     // Create the associated VisEquation
    5856             :     //  TBD: move to ctor and make it non-pointer
    5857           0 :     if (ve_p) {
    5858           0 :       delete ve_p;
    5859           0 :       ve_p=0;
    5860             :     };
    5861           0 :     ve_p=new VisEquation();
    5862             : 
    5863             :     // Reset the apply/solve VisCals
    5864           0 :     reset(true,true);
    5865             : 
    5866           0 :     return true;
    5867             : 
    5868           0 :   } catch (AipsError x) {
    5869           0 :     logSink() << LogOrigin("Calibrater","initialize",WHERE) 
    5870             :               << LogIO::SEVERE << "Caught exception: " << x.getMesg() 
    5871           0 :               << LogIO::POST;
    5872           0 :     cleanup();
    5873           0 :     cleanupVisSet();
    5874           0 :     if (ms_p) delete ms_p; ms_p=NULL;
    5875           0 :     if (hist_p) delete hist_p; hist_p=NULL;
    5876             : 
    5877           0 :     throw(AipsError("Error in Calibrater::initialize()"));
    5878             :     return false;
    5879           0 :   } 
    5880             :   return false;
    5881             : }
    5882             : 
    5883           0 : Bool OldCalibrater::initCalSet(const Int& calSet) 
    5884             : {
    5885             : 
    5886             :   //  logSink() << LogOrigin("Calibrater","initCalSet") << LogIO::NORMAL3;
    5887             : 
    5888           0 :   if (vs_p) {
    5889             : 
    5890           0 :     Block<Int> columns;
    5891             :     // include scan iteration, for more optimal iteration
    5892           0 :     columns.resize(5);
    5893           0 :     columns[0]=MS::ARRAY_ID;
    5894           0 :     columns[1]=MS::SCAN_NUMBER;
    5895           0 :     columns[2]=MS::FIELD_ID;
    5896           0 :     columns[3]=MS::DATA_DESC_ID;
    5897           0 :     columns[4]=MS::TIME;
    5898           0 :     vs_p->resetVisIter(columns,0.0);
    5899             : 
    5900           0 :     vs_p->initCalSet(calSet);
    5901           0 :     return true;
    5902           0 :   }
    5903             :   else {
    5904           0 :     throw(AipsError("Calibrater cannot initCalSet"));
    5905             :     return false;
    5906             :   }
    5907             : }
    5908             : 
    5909           0 : Bool OldCalibrater::cleanupVisSet() {
    5910             : 
    5911             :   //  logSink() << LogOrigin("OldCalibrater","cleanupVisSet") << LogIO::NORMAL;
    5912             : 
    5913           0 :   if(vs_p) delete vs_p; vs_p=0;
    5914             : 
    5915             :   // Delete chanmask
    5916           0 :   initChanMask();
    5917             : 
    5918           0 :   return true;
    5919             : 
    5920             : }
    5921             : 
    5922           0 : VisibilityIterator::DataColumn OldCalibrater::configureForCorrection ()
    5923             : {
    5924           0 :     if (!ok())
    5925           0 :       throw(AipsError("Calibrater not prepared for correct!"));
    5926             : 
    5927             :     // Nominally, we write out to the CORRECTED_DATA, unless absent
    5928           0 :     VisibilityIterator::DataColumn whichOutCol(VisibilityIterator::Corrected);
    5929             : 
    5930           0 :     if (!ms_p->tableDesc().isColumn("CORRECTED_DATA"))
    5931           0 :       throw(AipsError("CORRECTED_DATA column unexpectedly absent. Cannot correct."));
    5932             : 
    5933             :     // Ensure apply list non-zero and properly sorted
    5934           0 :     ve_p->setapply(vc_p);
    5935             : 
    5936             :     // Report the types that will be applied
    5937           0 :     applystate();
    5938             : 
    5939             :     // Arrange for iteration over data
    5940           0 :     Block<Int> columns;
    5941             :     // include scan iteration
    5942           0 :     columns.resize(5);
    5943           0 :     columns[0]=MS::ARRAY_ID;
    5944           0 :     columns[1]=MS::SCAN_NUMBER;
    5945           0 :     columns[2]=MS::FIELD_ID;
    5946           0 :     columns[3]=MS::DATA_DESC_ID;
    5947           0 :     columns[4]=MS::TIME;
    5948             : 
    5949             :     // Reset the VisibilityIterator in the VisSet. 
    5950           0 :     vs_p->resetVisIter (columns, 0.0);
    5951             : 
    5952           0 :     return whichOutCol;
    5953           0 : }
    5954             : 
    5955           0 : void OldCalibrater::selectChannel(const String& spw) {
    5956             : 
    5957             :   // Initialize the chanmask_
    5958           0 :   initChanMask();
    5959             : 
    5960           0 :   if (mss_p && mssel_p) {
    5961             : 
    5962             :     // Refresh the frequencySelections object to feed to VI2, if relevant
    5963           0 :     frequencySelections_p.reset(new vi::FrequencySelections());
    5964             : 
    5965           0 :     vi::FrequencySelectionUsingChannels usingChannels;
    5966           0 :     usingChannels.add(*mss_p,mssel_p);
    5967           0 :     frequencySelections_p->add(usingChannels);
    5968             : 
    5969             :     //    cout << usingChannels.toString() << endl;
    5970             :     //    cout << "FS.size() = " << frequencySelections_p->size() << endl;
    5971             : 
    5972           0 :   }
    5973             : 
    5974           0 :   Matrix<Int> chansel = getChanIdx(spw);
    5975           0 :   uInt nselspw=chansel.nrow();
    5976             : 
    5977           0 :   if (nselspw==0)
    5978             :     logSink() << "Frequency selection: Selecting all channels in all spws." 
    5979           0 :               << LogIO::POST;
    5980             :   else {
    5981             : 
    5982           0 :     logSink() << "Frequency selection: " << LogIO::POST;
    5983             : 
    5984             :     // Trap non-unit step (for now)
    5985           0 :     if (ntrue(chansel.column(3)==1)!=nselspw) {
    5986             :       logSink() << LogIO::WARN
    5987             :                 << "Calibration does not support non-unit channel stepping; "
    5988             :                 << "using step=1."
    5989           0 :                 << LogIO::POST;
    5990           0 :       chansel.column(3)=1;
    5991             :     }
    5992             : 
    5993           0 :     Int nspw=vs_p->numberSpw();
    5994           0 :     Vector<Int> nChan0;
    5995           0 :     nChan0 = vs_p->numberChan();
    5996             : 
    5997           0 :     Vector<Int> uspw(chansel.column(0));
    5998           0 :     Vector<Int> ustart(chansel.column(1));
    5999           0 :     Vector<Int> uend(chansel.column(2));
    6000             : 
    6001           0 :     Vector<Int> start(nspw,INT_MAX);
    6002           0 :     Vector<Int> end(nspw,-INT_MAX);
    6003           0 :     logSink() << LogIO::NORMAL;
    6004           0 :     for (uInt i=0;i<nselspw;++i) {
    6005             :       
    6006           0 :       Int& spw=uspw(i);
    6007             : 
    6008             :       // Initialize this spw mask, if necessary (def = masked)
    6009           0 :       if (!chanmask_[spw])
    6010           0 :         chanmask_[spw]=new Vector<Bool>(nChan0(spw),true);
    6011             : 
    6012             :       // revise net start/end/nchan
    6013           0 :       start(spw)=min(start(spw),ustart(i));
    6014           0 :       end(spw)=max(end(spw),uend(i));
    6015           0 :       Int nchan=end(spw)-start(spw)+1;  // net inclusive nchan
    6016             : 
    6017             :       // User's 
    6018           0 :       Int step=chansel(i,3);
    6019           0 :       Int unchan=uend(i)-ustart(i)+1;
    6020             :       
    6021             :       // Update the mask (false = valid)
    6022           0 :       (*chanmask_[spw])(Slice(ustart(i),unchan))=false;
    6023             : 
    6024             : 
    6025             :       logSink() << ".  Spw " << spw << ":"
    6026           0 :                 << ustart(i) << "~" << uend(i) 
    6027           0 :                 << " (" << uend(i)-ustart(i)+1 << " channels,"
    6028             :                 << " step by " << step << ")"
    6029           0 :                 << endl;
    6030             : 
    6031             :   /*
    6032             :       cout << i << " " << spw << " {" 
    6033             :            << start(spw) << " [" << ustart(i) << " " 
    6034             :            << uend(i) << "] " << end(spw) << "}" << endl;
    6035             :       cout << "chanmask = ";
    6036             :       for (Int j=0;j<nChan0(spw);++j) cout << (*chanmask_[spw])(j);
    6037             :       cout << endl << endl;
    6038             :   */
    6039             :         
    6040             :       // Call via VisSet (avoid call to VisIter::origin)
    6041           0 :       vs_p->selectChannel(1,start(spw),nchan,step,spw,false);
    6042             :         
    6043             :     } // i
    6044           0 :     logSink() << LogIO::POST;
    6045             : 
    6046           0 :   } // non-triv spw selection
    6047             : 
    6048             :   // For testing:
    6049             :   if (false) {
    6050             : 
    6051             :     VisIter& vi(vs_p->iter());
    6052             :     VisBuffer vb(vi);
    6053             :     
    6054             :     // Pass each timestamp (VisBuffer) to VisEquation for correction
    6055             :     for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    6056             :       vi.origin();
    6057             :       //      for (vi.origin(); vi.more(); vi++)
    6058             :         cout << vb.spectralWindow() << " "
    6059             :              << vb.nChannel() << " "
    6060             :              << vb.channel() << " "
    6061             :              << vb.visCube().shape()
    6062             :              << endl;
    6063             :     }
    6064             :   }
    6065             : 
    6066           0 : }
    6067             : 
    6068           0 : void OldCalibrater::initChanMask() {
    6069             : 
    6070           0 :   for (uInt i=0;i<chanmask_.nelements();++i) 
    6071           0 :     if (chanmask_[i])
    6072           0 :       delete chanmask_[i];
    6073           0 :   if (vs_p) {
    6074           0 :     chanmask_.resize(vs_p->numberSpw(),true);
    6075           0 :     chanmask_=NULL;
    6076             :   }
    6077             :   else {
    6078             :     //    throw(AipsError("Trouble sizing chanmask!"));
    6079             :     // just don't support channel masking:
    6080           0 :     chanmask_.resize(0,true);
    6081             :   }
    6082             : 
    6083           0 : }
    6084             : 
    6085             : // Select on channel in the VisSet
    6086           0 : void OldCalibrater::selectChannel(const String& mode, 
    6087             :                                const Int& nchan, 
    6088             :                                const Int& start, const Int& step,
    6089             :                                const MRadialVelocity& mStart,
    6090             :                                const MRadialVelocity& mStep) {
    6091             :   
    6092             :   // Set data selection variables
    6093           0 :   dataMode_p=mode;
    6094           0 :   dataNchan_p=nchan;
    6095           0 :   if (dataNchan_p<0) dataNchan_p=0; 
    6096           0 :   dataStart_p=start;
    6097           0 :   if (dataStart_p<0) dataNchan_p=0; 
    6098           0 :   dataStep_p=step;
    6099           0 :   if (dataStep_p<1) dataNchan_p=1; 
    6100             :   
    6101           0 :   mDataStart_p=mStart;
    6102           0 :   mDataStep_p=mStep;
    6103             :   
    6104             :   // Select on frequency channel
    6105           0 :   if(dataMode_p=="channel") {
    6106             :     // *** this bit here is temporary till we unifomize data selection
    6107             :     //Getting the selected SPWs
    6108           0 :     MSMainColumns msc(*mssel_p);
    6109           0 :     Vector<Int> dataDescID = msc.dataDescId().getColumn();
    6110             :     Bool dum;
    6111           0 :     Sort sort( dataDescID.getStorage(dum),sizeof(Int) );
    6112           0 :     sort.sortKey((uInt)0,TpInt);
    6113           0 :     Vector<uInt> index,uniq;
    6114           0 :     sort.sort(index,dataDescID.nelements());
    6115           0 :     uInt nSpw = sort.unique(uniq,index);
    6116             :     
    6117           0 :     Vector<Int> selectedSpw(nSpw);
    6118           0 :     Vector<Int> nChan(nSpw);
    6119           0 :     for (uInt k=0; k < nSpw; ++k) {
    6120           0 :       selectedSpw[k]=dataDescID[index[uniq[k]]];
    6121           0 :       nChan[k]=vs_p->numberChan()(selectedSpw[k]);
    6122             :       
    6123             :     }
    6124           0 :     if(dataNchan_p==0) dataNchan_p=vs_p->numberChan()(selectedSpw[0]);
    6125           0 :     if(dataStart_p<0) {
    6126             :       logSink() << LogIO::SEVERE << "Illegal start pixel = " 
    6127           0 :                 << dataStart_p << LogIO::POST;
    6128             :     }
    6129           0 :     Int end = Int(dataStart_p) + Int(dataNchan_p) * Int(dataStep_p);
    6130           0 :     for (uInt k=0; k < selectedSpw.nelements() ; ++k){
    6131           0 :       if(end < 1 || end > nChan[k]) {
    6132             :         logSink() << LogIO::SEVERE << "Illegal step pixel = " << dataStep_p
    6133           0 :                   << " in Spw " << selectedSpw[k]
    6134           0 :                   << LogIO::POST;
    6135             :       }
    6136             :       logSink() << "Selecting "<< dataNchan_p
    6137             :                 << " channels, starting at visibility channel "
    6138             :                 << dataStart_p  << " stepped by "
    6139           0 :                 << dataStep_p << " in Spw " << selectedSpw[k] << LogIO::POST;
    6140             :       
    6141             :       // Set frequency channel selection for all spectral window id's
    6142             :       Int nch;
    6143             :       //Vector<Int> nChan=vs_p->numberChan();
    6144             :       //Int nSpw=vs_p->numberSpw();
    6145           0 :       if (dataNchan_p==0) {
    6146           0 :         nch=nChan(k);
    6147             :       }else {
    6148           0 :         nch=dataNchan_p;
    6149             :       };
    6150           0 :       vs_p->selectChannel(1,dataStart_p,nch,dataStep_p,selectedSpw[k]);
    6151             :       
    6152             :     }
    6153           0 :   }
    6154             :   // Select on velocity
    6155           0 :   else if (dataMode_p=="velocity") {
    6156           0 :     MVRadialVelocity mvStart(mDataStart_p.get("m/s"));
    6157           0 :     MVRadialVelocity mvStep(mDataStep_p.get("m/s"));
    6158             :     MRadialVelocity::Types
    6159           0 :       vType((MRadialVelocity::Types)mDataStart_p.getRefPtr()->getType());
    6160             :     logSink() << "Selecting "<< dataNchan_p
    6161             :               << " channels, starting at radio velocity " << mvStart
    6162             :               << " stepped by " << mvStep << ", reference frame is "
    6163           0 :               << MRadialVelocity::showType(vType) << LogIO::POST;
    6164           0 :     vs_p->iter().selectVelocity(Int(dataNchan_p), mvStart, mvStep,
    6165             :                                 vType, MDoppler::RADIO);
    6166           0 :   }
    6167             :   
    6168             :   // Select on optical velocity
    6169           0 :   else if (dataMode_p=="opticalvelocity") {
    6170           0 :     MVRadialVelocity mvStart(mDataStart_p.get("m/s"));
    6171           0 :     MVRadialVelocity mvStep(mDataStep_p.get("m/s"));
    6172             :     MRadialVelocity::Types
    6173           0 :       vType((MRadialVelocity::Types)mDataStart_p.getRefPtr()->getType());
    6174             :     logSink() << "Selecting "<< dataNchan_p
    6175             :               << " channels, starting at optical velocity " << mvStart
    6176             :               << " stepped by " << mvStep << ", reference frame is "
    6177           0 :               << MRadialVelocity::showType(vType) << LogIO::POST;
    6178           0 :     vs_p->iter().selectVelocity(Int(dataNchan_p), mvStart, mvStep,
    6179             :                                 vType, MDoppler::OPTICAL);
    6180           0 :   }
    6181             :   
    6182             :   
    6183           0 : }
    6184             : 
    6185           0 : Bool OldCalibrater::ok() {
    6186             : 
    6187           0 :   if(vs_p && ms_p && mssel_p && ve_p) {
    6188           0 :     return true;
    6189             :   }
    6190             :   else {
    6191           0 :     logSink() << "Calibrater is not yet initialized" << LogIO::POST;
    6192           0 :     return false;
    6193             :   }
    6194             : }
    6195             : 
    6196           0 : Bool OldCalibrater::genericGatherAndSolve() {
    6197             : 
    6198             : #ifdef _OPENMP
    6199           0 :   Double Tsetup(0.0),Tgather(0.0),Tsolve(0.0);
    6200           0 :   Double time0=omp_get_wtime();
    6201             : #endif
    6202             : 
    6203             :   //cout << "Generic gather and solve." << endl;
    6204             : 
    6205             :   // Create the solver
    6206           0 :   VisCalSolver vcs;
    6207             :   
    6208             :    // Inform logger/history
    6209           0 :   logSink() << "Solving for " << svc_p->typeName()
    6210           0 :             << LogIO::POST;
    6211             :   
    6212             :   // Initialize the svc according to current VisSet
    6213             :   //  (this counts intervals, sizes CalSet)
    6214           0 :   Vector<Int> nChunkPerSol;
    6215           0 :   Int nSol = svc_p->sizeUpSolve(*vs_p,nChunkPerSol);
    6216             : 
    6217             :   // Create the in-memory (New)CalTable
    6218           0 :   svc_p->createMemCalTable();
    6219             : 
    6220             :   // The iterator, VisBuffer
    6221           0 :   VisIter& vi(vs_p->iter());
    6222           0 :   VisBuffer vb(vi);
    6223             :   
    6224           0 :   Vector<Int> slotidx(vs_p->numberSpw(),-1);
    6225             : 
    6226             :   // We will remember which spws couldn't be processed
    6227           0 :   Vector<Bool> unsolspw(vi.numberSpw());  
    6228           0 :   unsolspw.set(false);                 
    6229             : 
    6230             :   // Manage verbosity of partial channel averaging
    6231           0 :   Vector<Bool> verb(vi.numberSpw(),true);
    6232             : 
    6233           0 :   Vector<Int64> nexp(vi.numberSpw(),0), natt(vi.numberSpw(),0),nsuc(vi.numberSpw(),0);
    6234             : 
    6235             : #ifdef _OPENMP
    6236           0 :   Tsetup+=(omp_get_wtime()-time0);
    6237             : #endif
    6238             : 
    6239           0 :   Int nGood(0);
    6240           0 :   vi.originChunks();
    6241           0 :   for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
    6242             : 
    6243             : #ifdef _OPENMP
    6244           0 :     time0=omp_get_wtime();
    6245             : #endif
    6246             : 
    6247           0 :     nexp(vi.spectralWindow())+=1;
    6248             : 
    6249             :     // capture obs, scan info so we can set it later 
    6250             :     //   (and not rely on what the VB averaging code can't properly do)
    6251           0 :     Vector<Int> scv,obsv;
    6252           0 :     Int solscan=vi.scan(scv)(0),solobs=vi.observationId(obsv)(0);
    6253             : 
    6254             :     // Arrange to accumulate 
    6255             :     //    VisBuffAccumulator vba(vs_p->numberAnt(),svc_p->preavg(),false); 
    6256           0 :     VisBuffGroupAcc vbga(vs_p->numberAnt(),vs_p->numberSpw(),vs_p->numberFld(),svc_p->preavg()); 
    6257             :     
    6258           0 :     for (Int ichunk=0;ichunk<nChunkPerSol(isol);++ichunk) {
    6259             :     
    6260             :       // Current _chunk_'s spw
    6261           0 :       Int spw(vi.spectralWindow());
    6262             :     
    6263             :       // Only accumulate for solve if we can pre-calibrate
    6264           0 :       if (ve_p->spwOK(spw)) {
    6265             : 
    6266             :         // Collapse each timestamp in this chunk according to VisEq
    6267             :         //  with calibration and averaging
    6268           0 :         for (vi.origin(); vi.more(); vi++) {
    6269             :           
    6270             :           // Force read of the field Id
    6271           0 :           vb.fieldId();
    6272             : 
    6273             :           // Apply the channel mask (~no-op, if unnecessary)
    6274           0 :           svc_p->applyChanMask(vb);
    6275             :           
    6276             :           // This forces the data/model/wt I/O, and applies
    6277             :           //   any prior calibrations
    6278           0 :           ve_p->collapse(vb);
    6279             :           
    6280             :           // If permitted/required by solvable component, normalize
    6281           0 :           if (svc_p->normalizable()) 
    6282           0 :             vb.normalize();
    6283             :           
    6284             :           // If this solve not freqdep, and channels not averaged yet, do so
    6285           0 :           if (!svc_p->freqDepMat() && vb.nChannel()>1)
    6286           0 :             vb.freqAveCubes();
    6287             : 
    6288           0 :           if (svc_p->freqDepPar() && 
    6289           0 :               svc_p->fsolint()!="none" &&
    6290           0 :               svc_p->fintervalCh()>0.0) {
    6291             :             //      cout << "svc_p->currSpw() = " << svc_p->currSpw() << endl;
    6292           0 :             if (verb(spw)) 
    6293             :               logSink() << " Reducing nchan in spw " 
    6294             :                         << spw
    6295           0 :                         << " from " << vb.nChannel();
    6296           0 :             vb.channelAve(svc_p->chanAveBounds(spw));
    6297             : 
    6298             :             // Kludge for 3.4 to reset corr-indep flag to correct channel axis shape
    6299             :             // (because we use vb.flag() below, rather than vb.flagCube())
    6300           0 :             vb.flag().assign(operator>(partialNTrue(vb.flagCube(),IPosition(1,0)),0UL));
    6301             : 
    6302           0 :             if (verb(spw)) {
    6303             :               logSink() << " to " 
    6304           0 :                         << vb.nChannel() << LogIO::POST;
    6305           0 :               verb(spw)=false;  // suppress future verbosity in this spw
    6306             :             }
    6307             :           }
    6308             :           
    6309             :           // Accumulate collapsed vb in a time average
    6310             :           //  (only if the vb contains any unflagged data)
    6311           0 :           if (nfalse(vb.flag())>0)
    6312           0 :             vbga.accumulate(vb);
    6313             :           
    6314             :         }
    6315             :       }
    6316             :       else
    6317             :         // This spw not accumulated for solve
    6318           0 :         unsolspw(spw)=true;
    6319             : 
    6320             :       // Advance the VisIter, if possible
    6321           0 :       if (vi.moreChunks()) vi.nextChunk();
    6322             : 
    6323             :     }
    6324             :     
    6325             :     // Finalize the averged VisBuffer
    6326           0 :     vbga.finalizeAverage();
    6327             : 
    6328             :     // Establish meta-data for this interval
    6329             :     //  (some of this may be used _during_ solve)
    6330             :     //  (this sets currSpw() in the SVC)
    6331           0 :     Bool vbOk=(vbga.nBuf()>0 && svc_p->syncSolveMeta(vbga));
    6332             : 
    6333           0 :     svc_p->overrideObsScan(solobs,solscan);
    6334             : 
    6335             : #ifdef _OPENMP
    6336           0 :     Tgather+=(omp_get_wtime()-time0);
    6337           0 :     time0=omp_get_wtime();
    6338             : #endif
    6339             : 
    6340           0 :     if (vbOk) {
    6341             : 
    6342             :       // Use spw of first VB in vbga
    6343             :       // TBD: (currSpw==thisSpw) here??  (I.e., use svc_p->currSpw()?  currSpw is prot!)
    6344           0 :       Int thisSpw=svc_p->spwMap()(vbga(0).spectralWindow());
    6345             :     
    6346           0 :       natt(thisSpw)+=1;
    6347             : 
    6348           0 :       slotidx(thisSpw)++;
    6349             :       
    6350             :       // Make data amp- or phase-only, if needed
    6351           0 :       vbga.enforceAPonData(svc_p->apmode());
    6352             :       
    6353             :       // Select on correlation via weights, according to the svc
    6354           0 :       vbga.enforceSolveCorrWeights(svc_p->phandonly());
    6355             : 
    6356           0 :       if (svc_p->useGenericSolveOne()) {
    6357             :         // generic individual solve
    6358             : 
    6359             :         //cout << "Generic individual solve: isol=" << isol << endl;
    6360             : 
    6361             :         // First guess
    6362           0 :         svc_p->guessPar(vbga(0));
    6363             :         
    6364             :         // Solve for each parameter channel (in curr Spw)
    6365             :         
    6366             :         // (NB: force const version of nChanPar()  [why?])
    6367             :         //      for (Int ich=0;ich<((const SolvableVisCal*)svc_p)->nChanPar();++ich) {
    6368           0 :         Bool totalGoodSol(false);
    6369           0 :         for (Int ich=((const SolvableVisCal*)svc_p)->nChanPar()-1;ich>-1;--ich) {
    6370             :           // for (Int ich=0;ich<((const SolvableVisCal*)svc_p)->nChanPar();++ich) {
    6371             :           
    6372             :           // If pars chan-dep, SVC mechanisms for only one channel at a time
    6373           0 :           svc_p->markTimer();
    6374           0 :           svc_p->focusChan()=ich;
    6375             :           
    6376             :           //      svc_p->state();
    6377             :           
    6378             :           //      cout << "Starting solution..." << endl;
    6379             : 
    6380             :           // Pass VE, SVC, VB to solver
    6381           0 :           Bool goodSoln=vcs.solve(*ve_p,*svc_p,vbga);
    6382             :           
    6383             :           //      cout << "goodSoln= " << boolalpha << goodSoln << endl;
    6384             : 
    6385             :           // If good... 
    6386           0 :           if (goodSoln) {
    6387           0 :             totalGoodSol=true;
    6388             :             
    6389           0 :             svc_p->formSolveSNR();
    6390           0 :             svc_p->applySNRThreshold();
    6391             :             
    6392             :             // ..and file this solution in the correct slot
    6393           0 :             if (svc_p->freqDepPar())
    6394           0 :               svc_p->keep1(ich);
    6395             :             //      svc_p->keep(slotidx(thisSpw));
    6396             :             //      Int n=svc_p->nSlots(thisSpw);
    6397             :             //      svc_p->printActivity(n,slotidx(thisSpw),vi.fieldId(),thisSpw,nGood);           
    6398             :             
    6399             :           }
    6400             :           else {
    6401             :             // report where this failure occured
    6402           0 :             svc_p->currMetaNote();
    6403           0 :             if (svc_p->freqDepPar())
    6404             :               // We must record a flagged solution for this channel
    6405           0 :               svc_p->keep1(ich);
    6406             :           }
    6407             :           
    6408             :         } // parameter channels
    6409             : 
    6410           0 :         if (totalGoodSol) {
    6411           0 :           svc_p->keepNCT();
    6412           0 :           nsuc(thisSpw)+=1;
    6413             :         }
    6414             :         
    6415             :         // Count good solutions.
    6416           0 :         if (totalGoodSol)       nGood++;
    6417             :         
    6418             :       }
    6419             :       else {
    6420             :         //cout << "Self-directed individual solve: isol=" << isol << endl;
    6421             :         // self-directed individual solve
    6422             :         // TBD: selfSolveOne should return T/F for "good"
    6423           0 :         svc_p->selfSolveOne(vbga);
    6424             : 
    6425             :         // File this solution in the correct slot of the CalSet
    6426           0 :         svc_p->keepNCT();
    6427             : 
    6428           0 :         nGood++;
    6429           0 :         nsuc(thisSpw)+=1;
    6430             :       } 
    6431             :         
    6432             :     } // vbOK
    6433             : 
    6434             : #ifdef _OPENMP
    6435           0 :     Tsolve+=(omp_get_wtime()-time0);
    6436             : #endif
    6437             : 
    6438           0 :   } // isol
    6439             : 
    6440             :   logSink() << "  Found good " 
    6441           0 :             << svc_p->typeName() << " solutions in "
    6442             :             << nGood << " slots."
    6443           0 :             << LogIO::POST;
    6444             : #ifdef _OPENMP
    6445             :  #ifdef REPORT_CAL_TIMING
    6446             :   cout << "OldCalibrater::genericGatherAndSolve Timing: " << endl;
    6447             :   cout << " setup=" << Tsetup
    6448             :        << " gather=" << Tgather 
    6449             :        << " solve=" << Tsolve 
    6450             :        << " total=" << Tsetup+Tgather+Tsolve
    6451             :        << endl;
    6452             :  #endif
    6453             : #endif
    6454             : 
    6455           0 :   summarize_uncalspws(unsolspw, "solv");
    6456             :   
    6457             :   // Store whole of result in a caltable
    6458           0 :   if (nGood==0) {
    6459             :     logSink() << "No output calibration table written."
    6460           0 :               << LogIO::POST;
    6461             :   }
    6462             :   else {
    6463             : 
    6464             :     // TBD: Remove BPOLY specificity here
    6465           0 :     if (svc_p->typeName()!="BPOLY") {
    6466             :       // Do global post-solve tinkering (e.g., phase-only, normalization, etc.)
    6467           0 :       svc_p->globalPostSolveTinker();
    6468             : 
    6469             :       // write the table
    6470           0 :       svc_p->storeNCT();
    6471             : 
    6472             :     }
    6473             :   }
    6474             : 
    6475             :   // Fill activity record
    6476           0 :   actRec_=Record();
    6477           0 :   actRec_.define("origin","Calibrater::genericGatherAndSolve");
    6478           0 :   actRec_.define("nExpected",nexp);
    6479           0 :   actRec_.define("nAttempt",natt);
    6480           0 :   actRec_.define("nSucceed",nsuc);
    6481             : 
    6482             :   { 
    6483           0 :     Record solveRec=svc_p->solveActionRec();
    6484           0 :     if (solveRec.nfields()>0)
    6485           0 :       actRec_.merge(solveRec);
    6486           0 :   }
    6487             : 
    6488             : 
    6489             : 
    6490           0 :   return true;
    6491             : 
    6492           0 : }
    6493             : 
    6494             : 
    6495             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16