LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SynthesisImager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 125 1341 9.3 %
Date: 2025-08-21 08:01:32 Functions: 9 49 18.4 %

          Line data    Source code
       1             : //# SynthesisImager.cc: Implementation of SynthesisImager.h
       2             : //# Copyright (C) 1997-2016
       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$
      27             : 
      28             : #include <casacore/casa/Exceptions/Error.h>
      29             : #include <iostream>
      30             : #include <sstream>
      31             : 
      32             : #include <casacore/casa/Arrays/Matrix.h>
      33             : #include <casacore/casa/Arrays/ArrayMath.h>
      34             : #include <casacore/casa/Arrays/ArrayLogical.h>
      35             : 
      36             : 
      37             : #include <casacore/casa/Logging.h>
      38             : #include <casacore/casa/Logging/LogIO.h>
      39             : #include <casacore/casa/Logging/LogMessage.h>
      40             : #include <casacore/casa/Logging/LogSink.h>
      41             : #include <casacore/casa/Logging/LogMessage.h>
      42             : #include <casacore/casa/System/ProgressMeter.h>
      43             : 
      44             : #include <casacore/casa/OS/DirectoryIterator.h>
      45             : #include <casacore/casa/OS/File.h>
      46             : #include <casacore/casa/OS/HostInfo.h>
      47             : #include <casacore/casa/OS/Path.h>
      48             : //#include <casa/OS/Memory.h>
      49             : 
      50             : #include <casacore/lattices/LRegions/LCBox.h>
      51             : 
      52             : #include <casacore/measures/Measures/MeasTable.h>
      53             : 
      54             : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
      55             : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
      56             : #include <casacore/ms/MSSel/MSSelection.h>
      57             : 
      58             : #include <casacore/tables/Tables/TableUtil.h>
      59             : 
      60             : #include <synthesis/ImagerObjects/SynthesisImager.h>
      61             : 
      62             : #include <synthesis/ImagerObjects/SynthesisUtilMethods.h>
      63             : #include <synthesis/ImagerObjects/SIImageStore.h>
      64             : #include <synthesis/ImagerObjects/SIImageStoreMultiTerm.h>
      65             : 
      66             : #include <synthesis/MeasurementEquations/ImagerMultiMS.h>
      67             : #include <synthesis/MeasurementEquations/VPManager.h>
      68             : #include <msvis/MSVis/MSUtil.h>
      69             : #include <msvis/MSVis/VisSetUtil.h>
      70             : #include <msvis/MSVis/VisImagingWeight.h>
      71             : 
      72             : #include <synthesis/TransformMachines/GridFT.h>
      73             : #include <synthesis/TransformMachines/WPConvFunc.h>
      74             : #include <synthesis/TransformMachines/WProjectFT.h>
      75             : #include <synthesis/TransformMachines/VisModelData.h>
      76             : #include <synthesis/TransformMachines/AWProjectFT.h>
      77             : #include <synthesis/TransformMachines/HetArrayConvFunc.h>
      78             : #include <synthesis/TransformMachines/MosaicFTNew.h>
      79             : #include <synthesis/TransformMachines/MultiTermFTNew.h>
      80             : #include <synthesis/TransformMachines/AWProjectWBFTNew.h>
      81             : #include <synthesis/TransformMachines/AWConvFunc.h>
      82             : #include <synthesis/TransformMachines/AWConvFuncEPJones.h>
      83             : #include <synthesis/TransformMachines/NoOpATerm.h>
      84             : 
      85             : #include <casacore/casa/Utilities/Regex.h>
      86             : #include <casacore/casa/OS/Directory.h>
      87             : 
      88             : //#include <casadbus/utilities/BusAccess.h>
      89             : //#include <casadbus/session/DBusSession.h>
      90             : 
      91             : #include <sys/types.h>
      92             : #include <unistd.h>
      93             : 
      94             : 
      95             : using namespace std;
      96             : 
      97             : using namespace casacore;
      98             : namespace casa { //# NAMESPACE CASA - BEGIN
      99             :   
     100             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     101             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     102             : 
     103          34 :   SynthesisImager::SynthesisImager() : itsMappers(SIMapperCollection()), writeAccess_p(True),
     104          17 :                                        gridpars_p(), impars_p(), movingSource_p(""), doingCubeGridding_p(True)
     105             :   {
     106             : 
     107          17 :      imwgt_p=VisImagingWeight("natural");
     108          17 :      imageDefined_p=false;
     109          17 :      useScratch_p=false;
     110          17 :      readOnly_p=true;
     111             : 
     112          17 :      mss4vi_p.resize(0);
     113          17 :      wvi_p=0;
     114          17 :      rvi_p=0;
     115             : 
     116          17 :      facetsStore_p=-1;
     117          17 :      chanChunksStore_p=-1;
     118          17 :      unFacettedImStore_p=NULL;
     119          17 :      unChanChunkedImStore_p=NULL;
     120          17 :      dataSel_p.resize();
     121             : 
     122          17 :      nMajorCycles=0;
     123             : 
     124          17 :      itsDataLoopPerMapper=false;
     125             : 
     126          17 :   }
     127             :   
     128             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     129             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     130             : 
     131          17 :   SynthesisImager::~SynthesisImager() 
     132             :   {
     133          34 :     LogIO os( LogOrigin("SynthesisImager","destructor",WHERE) );
     134          17 :     os << LogIO::DEBUG1 << "SynthesisImager destroyed" << LogIO::POST;
     135          17 :     cleanupTempFiles();
     136          17 :     if(rvi_p) delete rvi_p;
     137          17 :     rvi_p=NULL;
     138             :     //    cerr << "IN DESTR"<< endl;
     139             :     //    VisModelData::listModel(mss4vi_p[0]);
     140             : 
     141          17 :     SynthesisUtilMethods::getResource("End SynthesisImager");
     142          17 :   }
     143             : 
     144             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     145             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     146             :   
     147           0 :   Bool SynthesisImager::selectData(const String& msname, 
     148             :                                    const String& spw, 
     149             :                                    const String& freqBeg, 
     150             :                                    const String& freqEnd, 
     151             :                                    const MFrequency::Types freqframe, 
     152             :                                    const String& field, 
     153             :                                    const String& antenna, 
     154             :                                    const String& timestr,
     155             :                                    const String& scan, 
     156             :                                    const String& obs, 
     157             :                                    const String& state,
     158             :                                    const String& uvdist, 
     159             :                                    const String& taql,
     160             :                                    const Bool usescratch, 
     161             :                                    const Bool readonly, 
     162             :                                    const Bool incrModel)
     163             :   {
     164           0 :     SynthesisParamsSelect pars;
     165           0 :     pars.msname=msname;
     166           0 :     pars.spw=spw;
     167           0 :     pars.freqbeg=freqBeg;
     168           0 :     pars.freqend=freqEnd;
     169           0 :     pars.freqframe=freqframe;
     170           0 :     pars.field=field;
     171           0 :     pars.antenna=antenna;
     172           0 :     pars.timestr=timestr;
     173           0 :     pars.scan=scan;
     174           0 :     pars.obs=obs;
     175           0 :     pars.state=state;
     176           0 :     pars.uvdist=uvdist;
     177           0 :     pars.taql=taql;
     178           0 :     pars.usescratch=usescratch;
     179           0 :     pars.readonly=readonly;
     180           0 :     pars.incrmodel=incrModel;
     181             : 
     182             : 
     183           0 :     String err = pars.verify();
     184             : 
     185           0 :     if( err.length()>0 ) throw(AipsError("Invalid Selection parameters : " + err));
     186             : 
     187           0 :     selectData( pars );
     188             : 
     189           0 :     return true;
     190           0 :   }
     191             :   
     192           0 :   Bool SynthesisImager::selectData(const SynthesisParamsSelect& selpars)
     193             :   {
     194           0 :     LogIO os( LogOrigin("SynthesisImager","selectData",WHERE) );
     195             : 
     196           0 :     SynthesisUtilMethods::getResource("Start SelectData");
     197             : 
     198             :     try
     199             :       {
     200             : 
     201             :     //Respect the readonly flag...necessary for multi-process access
     202           0 :     MeasurementSet thisms(selpars.msname, TableLock(TableLock::AutoNoReadLocking),
     203           0 :                                 selpars.readonly ? Table::Old : Table::Update);
     204           0 :     thisms.setMemoryResidentSubtables (MrsEligibility::defaultEligible());
     205             : 
     206           0 :     useScratch_p=selpars.usescratch;
     207           0 :     readOnly_p = selpars.readonly;
     208             :     //    cout << "**************** usescr : " << useScratch_p << "     readonly : " << readOnly_p << endl;
     209             :     //if you want to use scratch col...make sure they are there
     210           0 :     if(selpars.usescratch && !selpars.readonly){
     211           0 :       VisSetUtil::addScrCols(thisms, true, false, true, false);
     212           0 :       VisModelData::clearModel(thisms);
     213             :     }
     214           0 :     if(!selpars.incrmodel && !selpars.usescratch && !selpars.readonly)
     215           0 :         VisModelData::clearModel(thisms, selpars.field, selpars.spw);
     216             : 
     217           0 :     os << "MS : " << selpars.msname << " | ";
     218             : 
     219             :     //Some MSSelection 
     220             :     //If everything is empty (which is valid) it will throw an exception..below
     221             :     //So make sure the main defaults are not empy i.e field and spw
     222           0 :     MSSelection thisSelection;
     223           0 :     if(selpars.field != ""){
     224           0 :       thisSelection.setFieldExpr(selpars.field);
     225           0 :       os << "Selecting on fields : " << selpars.field << " | " ;//LogIO::POST;
     226             :     }else
     227           0 :       thisSelection.setFieldExpr("*");
     228           0 :     if(selpars.spw != ""){
     229           0 :         thisSelection.setSpwExpr(selpars.spw);
     230           0 :         os << "Selecting on spw :"<< selpars.spw  << " | " ;//LogIO::POST;
     231             :     }else
     232           0 :       thisSelection.setSpwExpr("*");
     233             :     
     234           0 :     if(selpars.antenna != ""){
     235           0 :       Vector<String> antNames(1, selpars.antenna);
     236             :       // thisSelection.setAntennaExpr(MSSelection::nameExprStr( antNames));
     237           0 :       thisSelection.setAntennaExpr(selpars.antenna);
     238           0 :       os << "Selecting on antenna names : " << selpars.antenna << " | " ;//LogIO::POST;
     239             :         
     240           0 :     }            
     241           0 :     if(selpars.timestr != ""){
     242           0 :         thisSelection.setTimeExpr(selpars.timestr);
     243           0 :         os << "Selecting on time range : " << selpars.timestr << " | " ;//LogIO::POST;    
     244             :       }
     245           0 :     if(selpars.uvdist != ""){
     246           0 :       thisSelection.setUvDistExpr(selpars.uvdist);
     247           0 :       os << "Selecting on uvdist : " << selpars.uvdist << " | " ;//LogIO::POST;   
     248             :     }
     249           0 :     if(selpars.scan != ""){
     250           0 :       thisSelection.setScanExpr(selpars.scan);
     251           0 :       os << "Selecting on scan : " << selpars.scan << " | " ;//LogIO::POST;       
     252             :     }
     253           0 :     if(selpars.obs != ""){
     254           0 :       thisSelection.setObservationExpr(selpars.obs);
     255           0 :       os << "Selecting on Observation Expr : " << selpars.obs << " | " ;//LogIO::POST;    
     256             :     }
     257           0 :     if(selpars.state != ""){
     258           0 :       thisSelection.setStateExpr(selpars.state);
     259           0 :       os << "Selecting on Scan Intent/State : " << selpars.state << " | " ;//LogIO::POST; 
     260             :     }
     261             :     // if(selpars.taql != ""){
     262             :     //  thisSelection.setTaQLExpr(selpars.taql);
     263             :     //  os << "Selecting via TaQL : " << selpars.taql << " | " ;//LogIO::POST;    
     264             :     // }
     265           0 :     os << "[Opened " << (readOnly_p?"in readonly mode":(useScratch_p?"with scratch model column":"with virtual model column"))  << "]" << LogIO::POST;
     266           0 :     TableExprNode exprNode=thisSelection.toTableExprNode(&thisms);
     267           0 :     if(!(exprNode.isNull()))
     268             :       {
     269           0 :         mss4vi_p.resize(mss4vi_p.nelements()+1, false, true);
     270           0 :         MeasurementSet thisMSSelected0 = MeasurementSet(thisms(exprNode));
     271             : 
     272           0 :         if(selpars.taql != "")
     273             :           {
     274           0 :             MSSelection mss0;
     275           0 :             mss0.setTaQLExpr(selpars.taql);
     276           0 :             os << "Selecting via TaQL : " << selpars.taql << " | " ;//LogIO::POST;        
     277             : 
     278           0 :             TableExprNode tenWithTaQL=mss0.toTableExprNode(&thisMSSelected0);
     279           0 :             MeasurementSet thisMSSelected1 = MeasurementSet(thisMSSelected0(tenWithTaQL));
     280             :             //mss4vi_p[mss4vi_p.nelements()-1]=MeasurementSet(thisms(exprNode));
     281           0 :             mss4vi_p[mss4vi_p.nelements()-1]=thisMSSelected1;
     282           0 :           }
     283             :         else
     284           0 :             mss4vi_p[mss4vi_p.nelements()-1]=thisMSSelected0;
     285             :           
     286           0 :         os << "  NRows selected : " << (mss4vi_p[mss4vi_p.nelements()-1]).nrow() << LogIO::POST;
     287           0 :         thisms.unlock();
     288           0 :       }
     289             :     else{
     290           0 :       throw(AipsError("Selection for given MS "+selpars.msname+" is invalid"));
     291             :     }
     292             :     //We should do the select channel here for  the VI construction later
     293             :     //Need a cross check between channel selection and ms
     294             :     // replace below if/when viFrquencySelectionUsingChannels takes in a MSSelection
     295             :     // rather than the following gymnastics
     296             :     {
     297           0 :       Matrix<Int> chanlist = thisSelection.getChanList(  & mss4vi_p[mss4vi_p.nelements()-1] );
     298             :       
     299           0 :       IPosition shape = chanlist.shape();
     300           0 :       uInt nSelections = shape[0];
     301           0 :       Int spw=0,chanStart=0,chanEnd=0,chanStep=1;
     302             : 
     303             :       ///////////////Temporary revert to using Vi/vb
     304           0 :       Int msin=mss4vi_p.nelements();
     305           0 :       blockNChan_p.resize(msin, false, true);
     306           0 :       blockStart_p.resize(msin, false, true);
     307           0 :       blockStep_p.resize(msin, false, true);
     308           0 :       blockSpw_p.resize(msin, false, true);
     309           0 :       msin-=1;
     310           0 :       blockNChan_p[msin].resize(nSelections);
     311           0 :       blockStart_p[msin].resize(nSelections);
     312           0 :       blockStep_p[msin].resize(nSelections);
     313           0 :       blockSpw_p[msin].resize(nSelections);
     314             :       ///////////////////////
     315             :       
     316             :       ////Channel selection 'flags' need for when using old VI/VB
     317             :       //set up Cube for storing the 'flags' for all MSes
     318             :       //find max no. channels from the current ms 
     319           0 :       const MSSpWindowColumns spwc(thisms.spectralWindow());
     320           0 :       uInt nspw = spwc.nrow();
     321           0 :       const ScalarColumn<Int> spwNchans(spwc.numChan());
     322           0 :       Vector<Int> nchanvec = spwNchans.getColumn();
     323           0 :       Int maxnchan = 0;
     324           0 :       for (uInt i=0;i<nchanvec.nelements();i++) {
     325           0 :         maxnchan=max(nchanvec[i],maxnchan);
     326             :       }
     327           0 :       uInt maxnspw = 0;
     328             :       // msin is now zero based index
     329           0 :       for (Int i=0;i<msin+1;i++) {
     330           0 :         maxnspw=max(maxnspw,nspw);
     331             :       }
     332             :       //maxnspw=max(nspw,maxnspw);
     333             :       // update the channel selections and initialize to 1's (all selected)
     334           0 :       chanSel_p.resize(msin+1,nspw,maxnchan,true);
     335           0 :       chanSel_p.yzPlane(msin)=1;
     336             : 
     337           0 :       if(selpars.freqbeg==""){
     338             :           //re-initialize to false 
     339           0 :           chanSel_p.yzPlane(msin)=0;
     340           0 :           Vector<Int> loChans(nspw, -1);
     341             :           /////So this gymnastic is needed
     342           0 :           Int nUsedSpw = 0;
     343           0 :           Vector<Int> chanStepPerSpw(nspw,-1);
     344           0 :           Vector<Int> maxChanEnd(nspw,0); 
     345           0 :           Vector<Int> usedSpw(nspw,-1);
     346           0 :           for(uInt k=0; k < nSelections; ++k)
     347             :           {
     348             : 
     349           0 :                   spw = chanlist(k,0);
     350             : 
     351             :                   // channel selection
     352           0 :                   chanStart = chanlist(k,1);
     353           0 :                   chanEnd = chanlist(k,2);
     354           0 :                   chanStep = chanlist(k,3);
     355             :                   //nchan = chanEnd-chanStart+1;
     356             :                   //nchan = Int(ceil(Double(chanEnd-chanStart+1)/Double(chanStep)));
     357           0 :                   maxChanEnd(spw) = max(maxChanEnd(spw), chanEnd);
     358           0 :                   chanStepPerSpw(spw) = chanStep;
     359             :                   // find lowest selected channel for each spw
     360           0 :                   if(loChans(spw) == -1) { 
     361           0 :                     loChans(spw) = chanStart;
     362           0 :                     nUsedSpw++;
     363           0 :                     usedSpw.resize(nUsedSpw,true);
     364           0 :                     usedSpw(nUsedSpw-1) = spw;
     365             :                   }
     366             :                   else {
     367           0 :                     if ( loChans(spw) > chanStart) loChans(spw) = chanStart;
     368             :                   }
     369             : 
     370             :                   //channelSelector.add (spw, chanStart, nchan,chanStep);
     371             :                   ///////////////Temporary revert to using Vi/vb
     372             :                   // will not work with multi-selections within a spw
     373             :                   //blockNChan_p[msin][k]=nchan;
     374             :                   //blockStart_p[msin][k]=chanStart;
     375             :                   //blockStep_p[msin][k]=chanStep;
     376             :                   //blockSpw_p[msin][k]=spw;
     377             :            }
     378             : 
     379             :            // vi.selectChannel() does not handle multiple chan sels within a spw???
     380             :            // So store a single channel sel(range) per spw... + chanflags...
     381           0 :            blockNChan_p[msin].resize(nUsedSpw);
     382           0 :            blockStart_p[msin].resize(nUsedSpw);
     383           0 :            blockStep_p[msin].resize(nUsedSpw);
     384           0 :            blockSpw_p[msin].resize(nUsedSpw);
     385           0 :            for(uInt j=0; j < (uInt) nUsedSpw; ++j)
     386             :            {
     387           0 :                   Int ispw = usedSpw(j);
     388           0 :                   if(loChans(ispw)!=-1) 
     389             :                   {
     390           0 :                     blockNChan_p[msin][j] = Int(ceil(Double(maxChanEnd(ispw)-loChans(ispw)+1)/Double(chanStepPerSpw(ispw))));
     391           0 :                     blockStart_p[msin][j] = loChans(ispw);
     392           0 :                     blockStep_p[msin][j] = chanStepPerSpw(ispw);
     393           0 :                     blockSpw_p[msin][j] = ispw; 
     394             :                   }
     395             :            }
     396             :  
     397           0 :            Int relStart=0;
     398           0 :            for(uInt k=0; k < nSelections; ++k)
     399             :            {
     400           0 :                   spw = chanlist(k,0);
     401           0 :                   chanStart = chanlist(k,1);
     402           0 :                   chanEnd = chanlist(k,2);
     403             :                   
     404             :                   // for 'channel flags' (for old VI/VB)
     405             :                   // MSSelect will be applied before the channel flags in FTMachine so
     406             :                   // chanSel_p will be relative to the start chan
     407             :                   //for (uInt k=chanStart;k<(chanEnd+1);k+=chanStep) {
     408           0 :                   if (loChans(spw) == chanStart ) {
     409           0 :                     relStart = 0;
     410             :                   }
     411             :                   else {
     412           0 :                     relStart = chanStart - loChans(spw);
     413             :                   }
     414           0 :                   for (uInt k=relStart;k<(uInt)(chanEnd-loChans(spw)+1);k+=chanStep) {
     415           0 :                     chanSel_p(msin,spw,k)=1;
     416             :                     //cerr<<"chanselflag spw="<<spw<<" chan="<<k<<endl;
     417             :                   }
     418             :                   /////////////////////////////////////////
     419             : 
     420             :           }
     421             : 
     422           0 :       }
     423             :       else{
     424           0 :           Quantity freq;
     425           0 :           Quantity::read(freq, selpars.freqbeg);
     426           0 :           Double lowfreq=freq.getValue("Hz");
     427           0 :           Quantity::read(freq, selpars.freqend);
     428           0 :           Double topfreq=freq.getValue("Hz");
     429             :           //////////OLD VI/VB
     430             :           //ImagerMultiMS im;
     431           0 :           Vector<Int> elspw, elstart, elnchan;
     432             :           // Intent can be used to select a field id so check
     433             :           // field ids actually present in the selection-applied MS
     434           0 :           Vector<Int>fields=thisSelection.getFieldList( & mss4vi_p[msin]);
     435           0 :           MSColumns tmpmsc(mss4vi_p[msin]);
     436           0 :           Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
     437           0 :           std::set<Int> ufldids(fldidv.begin(),fldidv.end());
     438           0 :           std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
     439           0 :           fields.resize(tmpv.size());
     440           0 :           uInt count=0;
     441           0 :           for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
     442             :             {
     443           0 :                fields(count) = *it;
     444           0 :                count++;
     445             :             }
     446             : 
     447           0 :           Int fieldid=fields.nelements() ==0 ? 0: fields[0];
     448           0 :           Vector<Int> chanSteps = chanlist.column(3); 
     449           0 :           Vector<Int> spws = chanlist.column(0);
     450           0 :           Int nspw = genSort( spws, Sort::Ascending, (Sort::QuickSort | Sort::NoDuplicates ));
     451           0 :           Vector<Int> chanStepPerSpw(nspw);
     452           0 :           uInt icount = 0; 
     453           0 :           Int prevspw = -1;
     454           0 :           for (uInt j=0; j < spws.nelements(); j++ ) {
     455           0 :             if (spws[j] != prevspw) {
     456           0 :               chanStepPerSpw[icount] =  chanSteps[j];
     457           0 :               prevspw = spws[j];
     458           0 :               icount++;
     459             :             }
     460             :           }
     461             :           //getSpwInFreqRange seems to assume the freqs to be the center of a channel while freqbeg and freqend appear to be
     462             :           //frequencies at the channel range edges. So set freqStep = 0.0 .
     463             :           //MSUtil::getSpwInFreqRange(elspw, elstart,elnchan,mss4vi_p[msin],lowfreq, topfreq,1.0, selpars.freqframe, fieldid);
     464           0 :           MSUtil::getSpwInFreqRange(elspw, elstart,elnchan,mss4vi_p[msin],lowfreq, topfreq,0.0, selpars.freqframe, fieldid);
     465             :           //im.adviseChanSelex(lowfreq, topfreq, 1.0, selpars.freqframe, elspw, elstart, elnchan, selpars.msname, fieldid, false);
     466             :           // Refine elspw if there is spw selection
     467           0 :           if ( elspw.nelements()==0 || elstart.nelements()==0 || elnchan.nelements()==0 )
     468           0 :             throw(AipsError("Failed to select vis. data by frequency range"));
     469           0 :           Vector<Int> tempspwlist, tempnchanlist, tempstartlist;
     470           0 :           uInt nselspw=0;
     471           0 :           if (selpars.spw != "") {
     472           0 :             Vector<Int> spwids = thisSelection.getSpwList( & mss4vi_p[msin]);
     473           0 :             for (uInt k=0; k < elspw.nelements(); k++ ) {
     474           0 :               if (std::find(spwids.begin(), spwids.end(), elspw[k]) != spwids.end()) {
     475           0 :                 tempspwlist.resize(tempspwlist.nelements()+1,true);
     476           0 :                 tempnchanlist.resize(tempnchanlist.nelements()+1,true);
     477           0 :                 tempstartlist.resize(tempstartlist.nelements()+1,true);
     478           0 :                 tempspwlist[nselspw] = elspw[k];
     479           0 :                 tempnchanlist[nselspw] = elnchan[k];
     480           0 :                 tempstartlist[nselspw] = elstart[k];
     481           0 :                 nselspw++;
     482             :               }
     483             :             }
     484           0 :             elspw.resize(tempspwlist.nelements());
     485           0 :             elnchan.resize(tempnchanlist.nelements());
     486           0 :             elstart.resize(tempstartlist.nelements());
     487           0 :             elspw = tempspwlist;
     488           0 :             elnchan = tempnchanlist;
     489           0 :             elstart = tempstartlist;
     490           0 :           }
     491           0 :           blockNChan_p[msin].resize(elspw.nelements());
     492           0 :           blockStart_p[msin].resize(elspw.nelements());
     493           0 :           blockStep_p[msin].resize(elspw.nelements());
     494           0 :           blockSpw_p[msin].resize(elspw.nelements());
     495           0 :           blockNChan_p[msin]=elnchan;
     496           0 :           blockStart_p[msin]=elstart;
     497           0 :           blockStep_p[msin].set(1);
     498           0 :           blockSpw_p[msin]=elspw;
     499             :           //////////////////////
     500           0 :       }
     501           0 :       os << "selected spw " << blockSpw_p[msin] << " start channels " << blockStart_p[msin] << " nchannels "<< blockNChan_p[msin] << LogIO::POST;
     502             : 
     503           0 :     }
     504           0 :     writeAccess_p=writeAccess_p && !selpars.readonly;
     505           0 :     createVisSet(writeAccess_p);
     506             : 
     507             :     /////// Remove this when the new vi/vb is able to get the full freq range.
     508           0 :     mssFreqSel_p.resize();
     509           0 :     mssFreqSel_p  = thisSelection.getChanFreqList(NULL,true);
     510             : 
     511             :     //// Set the data column on which to operate
     512             :     // TT: added checks for the requested data column existace 
     513             :     //    cout << "Using col : " << selpars.datacolumn << endl;
     514           0 :     if( selpars.datacolumn.contains("data") || selpars.datacolumn.contains("obs") ) 
     515           0 :       {    if( thisms.tableDesc().isColumn("DATA") ) { datacol_p = FTMachine::OBSERVED; }
     516           0 :            else { os << LogIO::SEVERE <<"DATA column does not exist" << LogIO::EXCEPTION;}
     517             :       }
     518           0 :     else if( selpars.datacolumn.contains("corr") ) { datacol_p = FTMachine::CORRECTED; }
     519           0 :     else { os << LogIO::WARN << "Invalid data column : " << selpars.datacolumn << ". Using corrected (or observed if corrected doesn't exist)" << LogIO::POST;  datacol_p =  FTMachine::CORRECTED;}
     520             : 
     521             :     /*
     522             :     else if( selpars.datacolumn.contains("corr") ) {    
     523             :       if( thisms.tableDesc().isColumn("CORRECTED_DATA") ) { datacol_p = FTMachine::CORRECTED; } 
     524             :       else 
     525             :         {
     526             :           if( thisms.tableDesc().isColumn("DATA") ) { 
     527             :             datacol_p = FTMachine::OBSERVED;
     528             :             os << "CORRECTED_DATA column does not exist. Using DATA column instead" << LogIO::POST; 
     529             :           }
     530             :           else { 
     531             :             os << LogIO::SEVERE <<"Neither CORRECTED_DATA nor DATA columns exist" << LogIO::EXCEPTION;
     532             :           }
     533             :         }
     534             :         
     535             :       }
     536             :      else { os << LogIO::WARN << "Invalid data column : " << datacol_p << ". Using corrected (or observed if corrected doesn't exist)" << LogIO::POST;  datacol_p = thisms.tableDesc().isColumn("CORRECTED_DATA") ? FTMachine::CORRECTED : FTMachine::OBSERVED; }
     537             : */
     538           0 :     dataSel_p.resize(dataSel_p.nelements()+1, true);
     539             : 
     540           0 :     dataSel_p[dataSel_p.nelements()-1]=selpars;
     541             : 
     542             : 
     543           0 :     unlockMSs();
     544           0 :       }
     545           0 :     catch(AipsError &x)
     546             :       {
     547           0 :         unlockMSs();
     548           0 :         throw( AipsError("Error in selectData() : "+x.getMesg()) );
     549           0 :       }
     550             : 
     551           0 :     return true;
     552             : 
     553           0 :   }
     554             : 
     555             : 
     556           0 :   void SynthesisImager::unlockMSs()
     557             :   {
     558           0 :     LogIO os( LogOrigin("SynthesisImager","unlockMSs",WHERE) );
     559           0 :     for(uInt i=0;i<mss4vi_p.nelements();i++)
     560             :       { 
     561           0 :         os << LogIO::NORMAL2 << "Unlocking : " << mss4vi_p[i].tableName() << LogIO::POST;
     562           0 :         MeasurementSet &ms_l =      const_cast<MeasurementSet& >(mss4vi_p[i]);
     563           0 :         ms_l.unlock(); 
     564           0 :         ms_l.antenna().unlock();
     565           0 :         ms_l.dataDescription().unlock();
     566           0 :         ms_l.feed().unlock();
     567           0 :         ms_l.field().unlock();
     568           0 :         ms_l.observation().unlock();
     569           0 :         ms_l.polarization().unlock();
     570           0 :         ms_l.processor().unlock();
     571           0 :         ms_l.spectralWindow().unlock();
     572           0 :         ms_l.state().unlock();
     573             :         //
     574             :         // Unlock the optional sub-tables as well, if they are present
     575             :         //
     576           0 :         if(!(ms_l.source().isNull()))     ms_l.source().unlock();
     577           0 :         if(!(ms_l.doppler().isNull()))    ms_l.doppler().unlock();
     578           0 :         if(!(ms_l.flagCmd().isNull()))    ms_l.flagCmd().unlock();
     579           0 :         if(!(ms_l.freqOffset().isNull())) ms_l.freqOffset().unlock();
     580           0 :         if(!(ms_l.history().isNull()))    ms_l.history().unlock();
     581           0 :         if(!(ms_l.pointing().isNull()))   ms_l.pointing().unlock();
     582           0 :         if(!(ms_l.sysCal().isNull()))     ms_l.sysCal().unlock();
     583           0 :         if(!(ms_l.weather().isNull()))    ms_l.weather().unlock();
     584             :       }
     585           0 :   }
     586             :   ///////////////////////////////////
     587           0 : bool SynthesisImager::unlockImages()
     588             :   {
     589             : 
     590           0 :     return itsMappers.releaseImageLocks();
     591             : 
     592             :   }
     593             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     594             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     595           0 :   Bool SynthesisImager::defineImage(const String& imagename, const Int nx, const Int ny,
     596             :                                     const Quantity& cellx, const Quantity& celly,
     597             :                                     const String& stokes,
     598             :                                     const MDirection& phaseCenter, 
     599             :                                     const Int nchan,
     600             :                                     const Quantity&freqStart,
     601             :                                     const Quantity& freqStep, 
     602             :                                     const Vector<Quantity>& restFreq,
     603             :                                     const Int facets,
     604             :                                     //s                             const Int chanchunks,
     605             :                                     const String ftmachine, 
     606             :                                     const Int nTaylorTerms,
     607             :                                     const Quantity& refFreq,
     608             :                                     const Projection& projection,
     609             :                                     const Quantity& distance,
     610             :                                     const MFrequency::Types& freqFrame,
     611             :                                     const Bool trackSource, 
     612             :                                     const MDirection& trackDir, 
     613             :                                     const Bool overwrite,
     614             :                                     const Float padding, 
     615             :                                     const Bool useAutocorr, 
     616             :                                     const Bool useDoublePrec, 
     617             :                                     const Int wprojplanes, 
     618             :                                     const String convFunc, 
     619             :                                     //                              const String vpTable,
     620             :                                     const String startmodel,
     621             :                                     // The extra params for WB-AWP
     622             :                                     const Bool aTermOn,//    = true,
     623             :                                     const Bool psTermOn,//   = true,
     624             :                                     const Bool mTermOn,//    = false,
     625             :                                     const Bool wbAWP,//      = true,
     626             :                                     const String cfCache,//  = "",
     627             :                                     const Bool usePointing,// = false,
     628             :                                     const Bool doPBCorr,//   = true,
     629             :                                     const Bool conjBeams,//  = true,
     630             :                                     const Float computePAStep,         //=360.0
     631             :                                     const Float rotatePAStep          //=5.0
     632             :                                     )
     633             : {
     634           0 :   String err("");
     635           0 :   LogIO os( LogOrigin("SynthesisImager","defineImage",WHERE) );
     636           0 :   SynthesisParamsImage impars;
     637           0 :   impars.imageName=imagename;
     638           0 :   Vector<Int> ims(2);ims[0]=nx; ims[1]=ny;
     639           0 :   impars.imsize=ims;
     640           0 :   Vector<Quantity> cells(2); cells[0]=cellx, cells[1]=celly;
     641           0 :   impars.cellsize=cells;
     642           0 :   impars.stokes=stokes;
     643           0 :   impars.phaseCenter=phaseCenter;
     644           0 :   impars.nchan=nchan;
     645           0 :   impars.mode= nchan < 0 ? "mfs" : "cube";
     646           0 :   impars.freqStart=freqStart;
     647           0 :   impars.freqStep=freqStep;
     648           0 :   impars.restFreq=restFreq;
     649           0 :   impars.nTaylorTerms=nTaylorTerms;
     650           0 :   impars.refFreq=refFreq;
     651           0 :   impars.projection=projection;
     652           0 :   impars.freqFrame=freqFrame;
     653           0 :   impars.overwrite=overwrite;
     654           0 :   impars.startModel.resize(1); impars.startModel[0]=startmodel;
     655             : 
     656           0 :   err += impars.verify();
     657             :   
     658           0 :   if(err.length() >0) 
     659           0 :     os << LogIO::WARN  << "impars verify error " << err << LogIO::POST;
     660           0 :   err="";
     661           0 :   SynthesisParamsGrid gridpars;
     662           0 :   gridpars.ftmachine=ftmachine;
     663           0 :   gridpars.distance=distance;
     664           0 :   gridpars.trackSource=trackSource;
     665           0 :   gridpars.trackDir=trackDir;
     666           0 :   gridpars.padding=padding;
     667           0 :   gridpars.facets=facets; 
     668             :   //  gridpars.chanchunks=chanchunks;
     669           0 :   gridpars.useAutoCorr=useAutocorr;
     670           0 :   gridpars.useDoublePrec=useDoublePrec;
     671           0 :   gridpars.wprojplanes=wprojplanes;
     672           0 :   gridpars.convFunc=convFunc;
     673             :   //  gridpars.vpTable=vpTable;
     674           0 :   gridpars.aTermOn=aTermOn;
     675           0 :   gridpars.psTermOn=psTermOn;
     676           0 :   gridpars.mTermOn=mTermOn;
     677           0 :   gridpars.wbAWP=wbAWP;
     678           0 :   gridpars.cfCache=cfCache;
     679           0 :   gridpars.usePointing=usePointing;
     680           0 :   gridpars.doPBCorr=doPBCorr;
     681           0 :   gridpars.conjBeams=conjBeams;
     682           0 :   gridpars.computePAStep=computePAStep;
     683           0 :   gridpars.rotatePAStep=rotatePAStep;
     684           0 :   gridpars.imageName="YAKYAK"; // no clue why gridpars has imageName..verify needs it
     685           0 :   err += gridpars.verify();
     686           0 :   if(err.length() >0) 
     687           0 :     os << LogIO::WARN  << "gridpars verify error " << err << LogIO::POST;
     688             :   //if( err.length()>0 ) throw(AipsError("Invalid Image/Gridding parameters : " + err));
     689             : 
     690           0 :   defineImage( impars, gridpars );
     691             : 
     692           0 :   return true;
     693           0 : }
     694             : 
     695           0 :   Bool SynthesisImager::defineImage(SynthesisParamsImage& impars, 
     696             :                            const SynthesisParamsGrid& gridpars)
     697             :   {
     698             : 
     699           0 :     LogIO os( LogOrigin("SynthesisImager","defineImage",WHERE) );
     700           0 :     if(mss4vi_p.nelements() ==0)
     701           0 :       os << "SelectData has to be run before defineImage" << LogIO::EXCEPTION;
     702             : 
     703           0 :     CoordinateSystem csys;
     704           0 :     CountedPtr<FTMachine> ftm, iftm;
     705             : 
     706           0 :     impars_p = impars;
     707           0 :     gridpars_p = gridpars;
     708             :     try
     709             :       {
     710             : 
     711           0 :         os << "Define image coordinates for [" << impars.imageName << "] : " << LogIO::POST;
     712             : 
     713           0 :         csys = impars.buildCoordinateSystem( rvi_p );
     714           0 :         IPosition imshape = impars.shp();
     715             : 
     716           0 :         os << "Impars : start " << impars.start << LogIO::POST;
     717           0 :         os << "Shape : " << imshape << "Spectral : " << csys.spectralCoordinate().referenceValue() << " at " << csys.spectralCoordinate().referencePixel() << " with increment " << csys.spectralCoordinate().increment() << LogIO::POST;
     718             : 
     719           0 :         if( (itsMappers.nMappers()==0) || 
     720           0 :             (impars.imsize[0]*impars.imsize[1] > itsMaxShape[0]*itsMaxShape[1]))
     721             :           {
     722           0 :             itsMaxShape=imshape;
     723           0 :             itsMaxCoordSys=csys;
     724             :           }
     725           0 :         itsNchan = imshape[3];
     726           0 :         itsCsysRec = impars.getcsys();
     727             :         /*
     728             :         os << "Define image  [" << impars.imageName << "] : nchan : " << impars.nchan 
     729             :            //<< ", freqstart:" << impars.freqStart.getValue() << impars.freqStart.getUnit() 
     730             :            << ", start:" << impars.start
     731             :            <<  ", imsize:" << impars.imsize 
     732             :            << ", cellsize: [" << impars.cellsize[0].getValue() << impars.cellsize[0].getUnit() 
     733             :            << " , " << impars.cellsize[1].getValue() << impars.cellsize[1].getUnit() 
     734             :            << LogIO::POST;
     735             :         */
     736           0 :       }
     737           0 :     catch(AipsError &x)
     738             :       {
     739           0 :         os << "Error in building Coordinate System and Image Shape : " << x.getMesg() << LogIO::EXCEPTION;
     740           0 :       }
     741             : 
     742             :         
     743             :     try
     744             :       {
     745           0 :         os << "Set Gridding options for [" << impars.imageName << "] with ftmachine : " << gridpars.ftmachine << LogIO::POST;
     746             : 
     747           0 :         itsVpTable=gridpars.vpTable;
     748           0 :         itsMakeVP= ( gridpars.ftmachine.contains("mosaicft") ||
     749           0 :                              gridpars.ftmachine.contains("awprojectft") )?False:True;
     750             : 
     751           0 :         createFTMachine(ftm, iftm, gridpars.ftmachine, impars.nTaylorTerms, gridpars.mType, 
     752           0 :                         gridpars.facets, gridpars.wprojplanes,
     753           0 :                         gridpars.padding,gridpars.useAutoCorr,gridpars.useDoublePrec,
     754           0 :                         gridpars.convFunc,
     755           0 :                         gridpars.aTermOn,gridpars.psTermOn, gridpars.mTermOn,
     756           0 :                         gridpars.wbAWP,gridpars.cfCache,gridpars.usePointing,
     757           0 :                         gridpars.doPBCorr,gridpars.conjBeams,
     758           0 :                         gridpars.computePAStep,gridpars.rotatePAStep,
     759           0 :                         gridpars.interpolation, impars.freqFrameValid, 1000000000,  16, impars.stokes,
     760           0 :                         impars.imageName);
     761             : 
     762             :       }
     763           0 :     catch(AipsError &x)
     764             :       {
     765           0 :         os << "Error in setting up FTMachine() : " << x.getMesg() << LogIO::EXCEPTION;
     766           0 :       }
     767             : 
     768             :     try
     769             :       {
     770           0 :         appendToMapperList(impars.imageName,  csys,  impars.shp(),
     771             :                            ftm, iftm,
     772           0 :                            gridpars.distance, gridpars.facets, gridpars.chanchunks,impars.overwrite,
     773           0 :                            gridpars.mType, gridpars.padding, impars.nTaylorTerms, impars.startModel);
     774           0 :         imageDefined_p=true;
     775             :       }
     776           0 :     catch(AipsError &x)
     777             :       {
     778           0 :         os << "Error in adding Mapper : "+x.getMesg() << LogIO::EXCEPTION;
     779           0 :       }
     780             : 
     781           0 :     return true;
     782           0 :   }
     783             : 
     784          17 :   Long SynthesisImager::estimateRAM(){
     785          17 :     Long mem=0;
     786          34 :     LogIO os( LogOrigin("SynthesisImager","estimateRAM",WHERE) );
     787          17 :     if(itsMappers.nMappers()==0)
     788           0 :       os << "SynthesisImage has not been setup to get an estimate of memory usage" << LogIO::WARN << LogIO::POST;
     789          17 :     mem=itsMappers.estimateRAM();
     790          17 :     return mem;
     791          17 :   }
     792             :   
     793           0 :   Bool SynthesisImager::defineImage(CountedPtr<SIImageStore> imstor, 
     794             :                                     const String& ftmachine)
     795             :   {
     796           0 :     CountedPtr<FTMachine> ftm, iftm;
     797             : 
     798             :     // The following call to createFTMachine() uses the
     799             :     // following defaults
     800             :     //
     801             :     // facets=1, wprojplane=1, padding=1.0, useAutocorr=false, 
     802             :     // useDoublePrec=true, gridFunction=String("SF")
     803             :     //
     804           0 :     createFTMachine(ftm, iftm, ftmachine);
     805             :     
     806           0 :     Int id=itsMappers.nMappers();
     807           0 :     CoordinateSystem csys =imstor->residual()->coordinates();
     808           0 :     IPosition imshape=imstor->residual()->shape();
     809           0 :     Int nx=imshape[0], ny=imshape[1];
     810           0 :     if( (id==0) || (nx*ny > itsMaxShape[0]*itsMaxShape[1]))
     811             :       {
     812           0 :         itsMaxShape=imshape;
     813           0 :         itsMaxCoordSys=csys;
     814             :       }
     815             : 
     816           0 :     itsMappers.addMapper(  createSIMapper( "default", imstor, ftm, iftm, id ) );
     817             :     
     818           0 :     return true;
     819           0 :   }
     820             : 
     821             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     822             :   /////////////////////////////////////////////////////////////////////////////////////////////////////
     823             :   // Record SynthesisImage::runGridParamsHeuristics(SynthesisParamsGrid& gridPars)
     824             :   // {
     825             :   //   return gridPars;
     826             :   // }
     827             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     828             :   /////////////////////////////////////////////////////////////////////////////////////////////////////
     829             :   
     830           0 :   Vector<SynthesisParamsSelect> SynthesisImager::tuneSelectData(){
     831           0 :            LogIO os( LogOrigin("SynthesisImager","tuneSelectData",WHERE) );
     832           0 :            if(itsMappers.nMappers() < 1)
     833           0 :                    ThrowCc("defineimage has to be run before tuneSelectData");
     834           0 :            if(impars_p.mode=="cubesource" || impars_p.mode=="cubedata")
     835           0 :              return dataSel_p;
     836           0 :            os << "Tuning frequency data selection to match image spectral coordinates" << LogIO::POST;
     837             : 
     838           0 :            Vector<SynthesisParamsSelect> origDatSel(dataSel_p.nelements());
     839           0 :            origDatSel=dataSel_p;
     840             :            /*Record selpars;
     841             :            for(uInt k=0; k < origDatSel.nelements(); ++k){
     842             :                    Record inSelRec=origDatSel[k].toRecord();
     843             :                    selpars.defineRecord("ms"+String::toString(k), inSelRec);
     844             :            }
     845             :            */
     846           0 :            Int nchannel=itsMaxShape[3];
     847           0 :            CoordinateSystem cs=itsMaxCoordSys;
     848           0 :            MFrequency::Types freqframe=cs.spectralCoordinate(cs.findCoordinate(Coordinate::SPECTRAL)).frequencySystem(False);
     849           0 :            if(freqframe != MFrequency::REST &&  freqframe != MFrequency::Undefined)
     850           0 :              cs.setSpectralConversion("LSRK");
     851           0 :            Vector<Double> pix(4);
     852             :            //increase edge part a bit  vi/vb2 is making lots of grief for selecting properly if the channel are negative
     853             :            // specially...
     854           0 :            pix[0]=0; pix[1]=0; pix[2]=0; pix[3]=-1.5;
     855           0 :            Double freq1=cs.toWorld(pix)[3];
     856           0 :            pix[3]=Double(nchannel)+0.5;
     857           0 :            Double freq2=cs.toWorld(pix)[3];
     858           0 :            String units=cs.worldAxisUnits()[3];
     859           0 :            if(freq2 < freq1){
     860           0 :                    Double tmp=freq1;
     861           0 :                    freq1=freq2;
     862           0 :                    freq2=tmp;
     863             :            }
     864             :            //String freqbeg=String::toString(freq1)+units;
     865             :            //String freqend=String::toString(freq2)+units;
     866             :            // String::toString drops the digits for double precision
     867           0 :            String freqbeg=doubleToString(freq1)+units;
     868           0 :            String freqend=doubleToString(freq2)+units;
     869             :            //Record outRec=SynthesisUtilMethods::cubeDataPartition(selpars, 1, freq1, freq2);
     870             :            //Record partRec=outRec.asRecord("0");
     871             : 
     872           0 :            if(mss_p.nelements() >0){
     873           0 :              for (uInt k=0; k < mss_p.nelements(); ++k){
     874           0 :                if(mss_p[k])
     875           0 :                  delete mss_p[k];
     876             :              }
     877           0 :              mss_p.resize(0, true, false);
     878             :            }
     879             :            ///resetting the block ms
     880           0 :            mss4vi_p.resize(0,true, false);
     881             :            //resetting data selection stored
     882           0 :            dataSel_p.resize();
     883             :            // reset rvi_p
     884           0 :            if(rvi_p) delete rvi_p;
     885           0 :            rvi_p=NULL;
     886             : 
     887           0 :            for(uInt k=0; k< origDatSel.nelements(); ++k){
     888           0 :                    SynthesisParamsSelect outsel=origDatSel[k];
     889           0 :                    outsel.freqbeg=freqbeg;
     890           0 :                    outsel.freqend=freqend;
     891           0 :                    outsel.freqframe=MFrequency::LSRK;
     892           0 :                    selectData(outsel);
     893           0 :            }
     894           0 :            return dataSel_p;
     895             : 
     896           0 :    }
     897             : 
     898             : 
     899             :    ///////////////////////////////////////////////////////////////////////////////////////////
     900             :   ///////////////////////////////////////////////////////////////////////////////////////////
     901           0 :   void SynthesisImager::setComponentList(const ComponentList& cl, Bool sdgrid){
     902           0 :           String cft="SimpleComponentFTMachine";
     903           0 :           if(sdgrid)
     904           0 :                   cft="SimpCompGridFTMachine";
     905           0 :           CountedPtr<SIMapper> sm=new SIMapper(cl, cft);
     906           0 :           itsMappers.addMapper(sm);
     907             :           ////itsMappers.addMapper(  createSIMapper( mappertype, imstor, ftm, iftm, id) );
     908             : 
     909           0 :   }
     910             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     911             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     912             : 
     913             :   //////////////////////Reset the Mapper
     914             :   ////////////////////
     915           0 :   void SynthesisImager::resetMappers(){
     916             :     ////reset code
     917           0 :         itsMappers=SIMapperCollection();
     918           0 :         unFacettedImStore_p=NULL;
     919           0 :         unChanChunkedImStore_p=NULL;
     920           0 :   }
     921             : //////////////////////////////////////////////////////////////////
     922             : /////////////////////////////////////////////
     923           0 :   CountedPtr<SIImageStore> SynthesisImager::imageStore(const Int id)
     924             :   {
     925           0 :     AlwaysAssert( ! ( facetsStore_p>1 && chanChunksStore_p>1 ) , AipsError);
     926             : 
     927           0 :     if(facetsStore_p >1)
     928             :       {
     929           0 :         if(id==0)
     930             :           {
     931           0 :             return unFacettedImStore_p;
     932             :           }
     933             :         else
     934             :           {
     935           0 :             return itsMappers.imageStore(facetsStore_p*facetsStore_p+id-1);
     936             :           }
     937             :       }
     938             : 
     939           0 :     if(chanChunksStore_p >1)
     940             :       {
     941           0 :         if(id==0)
     942             :           {
     943           0 :             return unChanChunkedImStore_p;
     944             :           }
     945             :         else
     946             :           {
     947           0 :             return itsMappers.imageStore(chanChunksStore_p+id-1);
     948             :           }
     949             :       }
     950             : 
     951             : 
     952           0 :     return itsMappers.imageStore(id);
     953             :   }
     954             : 
     955             : 
     956             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     957             :   ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     958             :   
     959          17 :   Record SynthesisImager::executeMajorCycle(const Record& controlRecord)
     960             :   {
     961          34 :     LogIO os( LogOrigin("SynthesisImager","executeMajorCycle",WHERE) );
     962             : 
     963          17 :     nMajorCycles++;
     964          17 :     if(controlRecord.isDefined("nmajorcycles"))
     965           0 :       controlRecord.get("nmajorcycles", nMajorCycles);
     966          17 :     Record outRec=controlRecord;
     967          17 :     Bool lastcycle=false;
     968             : 
     969             :     
     970          17 :     if( controlRecord.isDefined("lastcycle") )
     971             :       {
     972          17 :         controlRecord.get( "lastcycle" , lastcycle );
     973             :         //cout << "lastcycle : " << lastcycle << endl;
     974             :       }
     975             :     //else {cout << "No lastcycle" << endl;}
     976             : 
     977          17 :     os << "----------------------------------------------------------- Run ";
     978             :     //if (lastcycle) os << "(Last) " ;
     979          17 :     os << "Major Cycle " << nMajorCycles << " -------------------------------------" << LogIO::POST;
     980             : 
     981             :     try
     982             :       {
     983          17 :         if( (itsMaxShape[3] > 1 || impars_p.mode.contains("cube"))&& doingCubeGridding_p ){/// and valid ftmachines
     984           0 :                 runMajorCycleCube(false, controlRecord);
     985             :         }
     986             :         else{
     987          17 :          if( itsDataLoopPerMapper == false )
     988          17 :                 {       runMajorCycle(false, lastcycle);}
     989             :          else
     990           0 :                 {       runMajorCycle2(false, lastcycle);}
     991             :         
     992             :         }
     993          17 :         if(lastcycle){
     994          17 :           String mess="In Major Cycle";
     995          17 :           if(controlRecord.isDefined("usemask")  && controlRecord.asString("usemask").contains("auto")){
     996           0 :             mess="\nFor Automasking most  major cycles may appear wrongly as  the last one ";
     997             :           }
     998             : 
     999          17 :           std::vector<String> tmpfiles=itsMappers.cleanupTempFiles(mess);
    1000          17 :           outRec.define("tempfilenames", Vector<String>(tmpfiles));
    1001          17 :         }
    1002          17 :         itsMappers.releaseImageLocks();
    1003             : 
    1004             :       }
    1005           0 :     catch(AipsError &x)
    1006             :       {
    1007           0 :         throw( AipsError("Error in running Major Cycle : "+x.getMesg()) );
    1008           0 :       }    
    1009          34 :     return outRec;
    1010          17 :   }// end of executeMajorCycle
    1011             :   //////////////////////////////////////////////
    1012             :   /////////////////////////////////////////////
    1013          17 :   void SynthesisImager::cleanupTempFiles(){
    1014          34 :     LogIO os( LogOrigin("SynthesisImager","cleanupTempFiles",WHERE) );
    1015          17 :     for (auto it = tempFileNames_p.begin(); it != tempFileNames_p.end(); ++it) {
    1016             :       //cerr <<"Trying to cleanup " << (*it) << endl;
    1017           0 :       if(Table::isReadable(*it)){
    1018             :         try{
    1019           0 :           TableUtil::deleteTable(*it);
    1020             :          }
    1021           0 :          catch(AipsError &x){
    1022           0 :            os << LogIO::WARN<< "YOU may have to delete the temporary file " << *it << " because " << x.getMesg()  << LogIO::POST;
    1023           0 :          }
    1024             :       }
    1025             : 
    1026             :       
    1027             :     }
    1028             : 
    1029             : 
    1030          17 :   }
    1031          17 :   Record SynthesisImager::makePSF()
    1032             :     {
    1033          17 :       Record outRec=Record();
    1034          34 :       LogIO os( LogOrigin("SynthesisImager","makePSF",WHERE) );
    1035             : 
    1036          17 :       os << "----------------------------------------------------------- Make PSF ---------------------------------------------" << LogIO::POST;
    1037             :     
    1038             :       try
    1039             :       {
    1040          17 :         if(  (itsMaxShape[3] >1 || impars_p.mode.contains("cube")) && doingCubeGridding_p){///and valid ftmachines
    1041           0 :                 runMajorCycleCube(true);
    1042             :         }
    1043             :         else{
    1044          17 :          if( itsDataLoopPerMapper == false )
    1045          17 :           {runMajorCycle(true, false);}
    1046             :         else
    1047           0 :           {runMajorCycle2(true, false);}
    1048             :         }
    1049             :         //      makeImage();
    1050             : 
    1051          17 :         String mess("PSF wieghting scheme");
    1052          17 :         std::vector<String> tmpfiles=itsMappers.cleanupTempFiles(mess);
    1053          17 :         outRec.define("tempfilenames", Vector<String>(tmpfiles));
    1054          17 :           itsMappers.releaseImageLocks();
    1055             : 
    1056          17 :       }
    1057           0 :       catch(AipsError &x)
    1058             :       {
    1059           0 :           throw( AipsError("Error in making PSF : "+x.getMesg()) );
    1060           0 :       }
    1061          34 :       return outRec;
    1062          17 :     }
    1063             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1064             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1065             : 
    1066           0 :   Record SynthesisImager::apparentSensitivity() 
    1067             :   {
    1068             : 
    1069           0 :     throw( AipsError("apparentSensitivity calculation not supported in SynthesisImager (VI1)") );
    1070             :     return Record();
    1071             : 
    1072             :   }
    1073             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1074             : 
    1075             : 
    1076             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1077             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1078           0 :   Bool SynthesisImager::weight(const String& type, const String& rmode,
    1079             :                                const Quantity& noise, const Double robust,
    1080             :                                const Quantity& fieldofview,
    1081             :                                const Int npixels, const Bool multiField,
    1082             :                                const Bool /*useCubeBriggs*/,
    1083             :                                const String& filtertype, const Quantity& filterbmaj,
    1084             :                                const Quantity& filterbmin, const Quantity& filterbpa, Double /*fracBW*/   )
    1085             :   {
    1086           0 :     LogIO os(LogOrigin("SynthesisImager", "weight()", WHERE));
    1087             : 
    1088             :        try {
    1089             :         //Int nx=itsMaxShape[0];
    1090             :         //Int ny=itsMaxShape[1];
    1091           0 :          Quantity cellx=Quantity(itsMaxCoordSys.increment()[0], itsMaxCoordSys.worldAxisUnits()[0]);
    1092           0 :          Quantity celly=Quantity(itsMaxCoordSys.increment()[1], itsMaxCoordSys.worldAxisUnits()[1]);
    1093             :          os << LogIO::NORMAL // Loglevel INFO
    1094           0 :             << "Set imaging weights : " ; //<< LogIO::POST;
    1095             :          
    1096           0 :          if (type=="natural") {
    1097             :            os << LogIO::NORMAL // Loglevel INFO
    1098           0 :               << "Natural weighting" << LogIO::POST;
    1099           0 :            imwgt_p=VisImagingWeight("natural");
    1100             :          }
    1101           0 :       else if (type=="radial") {
    1102           0 :         os << "Radial weighting" << LogIO::POST;
    1103           0 :           imwgt_p=VisImagingWeight("radial");
    1104             :       }
    1105             :       else{
    1106           0 :           if(!imageDefined_p)
    1107           0 :                   throw(AipsError("Need to define image"));
    1108           0 :           Int nx=itsMaxShape[0];
    1109           0 :           Int ny=itsMaxShape[1];
    1110           0 :           Quantity cellx=Quantity(itsMaxCoordSys.increment()[0], itsMaxCoordSys.worldAxisUnits()[0]);
    1111           0 :           Quantity celly=Quantity(itsMaxCoordSys.increment()[1], itsMaxCoordSys.worldAxisUnits()[1]);
    1112           0 :           if(type=="superuniform"){
    1113           0 :                   if(!imageDefined_p) throw(AipsError("Please define image first"));
    1114           0 :                   Int actualNpix=npixels;
    1115           0 :                   if(actualNpix <=0)
    1116           0 :                           actualNpix=3;
    1117             :                   os << LogIO::NORMAL // Loglevel INFO
    1118             :                                   << "SuperUniform weighting over a square cell spanning ["
    1119             :                                   << -actualNpix
    1120           0 :                                   << ", " << actualNpix << "] in the uv plane" << LogIO::POST;
    1121           0 :                   imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, nx,
    1122             :                                   ny, cellx, celly, actualNpix,
    1123           0 :                                   actualNpix, multiField);
    1124             :           }
    1125           0 :           else if ((type=="robust")||(type=="uniform")||(type=="briggs")) {
    1126           0 :                   if(!imageDefined_p) throw(AipsError("Please define image first"));
    1127           0 :                   Quantity actualFieldOfView_x(fieldofview), actualFieldOfView_y(fieldofview) ;
    1128           0 :                   Int actualNPixels_x(npixels),actualNPixels_y(npixels) ;
    1129           0 :                   String wtype;
    1130           0 :                   if(type=="briggs") {
    1131           0 :                           wtype = "Briggs";
    1132             :                   }
    1133             :                   else {
    1134           0 :                           wtype = "Uniform";
    1135             :                   }
    1136           0 :                   if(actualFieldOfView_x.get().getValue()==0.0&&actualNPixels_x==0) {
    1137           0 :                           actualNPixels_x=nx;
    1138           0 :                           actualFieldOfView_x=Quantity(actualNPixels_x*cellx.get("rad").getValue(),"rad");
    1139           0 :                           actualNPixels_y=ny;
    1140           0 :                           actualFieldOfView_y=Quantity(actualNPixels_y*celly.get("rad").getValue(),"rad");
    1141             :                           os << LogIO::NORMAL // Loglevel INFO
    1142             :                                           << wtype
    1143             :                                           << " weighting: sidelobes will be suppressed over full image"
    1144           0 :                                           << LogIO::POST;
    1145             :                   }
    1146           0 :                   else if(actualFieldOfView_x.get().getValue()>0.0&&actualNPixels_x==0) {
    1147           0 :                           actualNPixels_x=nx;
    1148           0 :                           actualNPixels_y=ny;
    1149             :                           os << LogIO::NORMAL // Loglevel INFO
    1150             :                                           << wtype
    1151             :                                           << " weighting: sidelobes will be suppressed over specified field of view: "
    1152           0 :                                           << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by " 
    1153           0 :                                           << actualFieldOfView_y.get("arcsec").getValue()  << " arcsec" << LogIO::POST;
    1154             :                   }
    1155           0 :                   else if(actualFieldOfView_x.get().getValue()==0.0&&actualNPixels_x>0) {
    1156           0 :                           actualFieldOfView_x=Quantity(actualNPixels_x*cellx.get("rad").getValue(),"rad");
    1157           0 :                           actualFieldOfView_y=Quantity(actualNPixels_y*celly.get("rad").getValue(),"rad");
    1158             :                           os << LogIO::NORMAL // Loglevel INFO
    1159             :                                           << wtype
    1160             :                                           << " weighting: sidelobes will be suppressed over full image field of view: "
    1161           0 :                                           << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by " 
    1162           0 :                                           << actualFieldOfView_y.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    1163             :                   }
    1164             :                   else {
    1165             :                           os << LogIO::NORMAL // Loglevel INFO
    1166             :                                           << wtype
    1167             :                                           << " weighting: sidelobes will be suppressed over specified field of view: "
    1168           0 :                                           << actualFieldOfView_x.get("arcsec").getValue() << " arcsec by " 
    1169           0 :                                           << actualFieldOfView_y.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    1170             :                   }
    1171             :                   os << LogIO::DEBUG1
    1172             :                      << "Weighting used " << actualNPixels_x << " by " << actualNPixels_y << " uv pixels."
    1173           0 :                      << LogIO::POST;
    1174           0 :                   Quantity actualCellSize_x(actualFieldOfView_x.get("rad").getValue()/actualNPixels_x, "rad");
    1175           0 :                   Quantity actualCellSize_y(actualFieldOfView_y.get("rad").getValue()/actualNPixels_y, "rad");
    1176             : 
    1177             :                   //              cerr << "rmode " << rmode << " noise " << noise << " robust " << robust << " npixels " << actualNPixels << " cellsize " << actualCellSize << " multifield " << multiField << endl;
    1178             :                   //              Timer timer;
    1179             :                   //timer.mark();
    1180             :                   //Construct imwgt_p with old vi for now if old vi is in use as constructing with vi2 is slower 
    1181             : 
    1182             : 
    1183           0 :                   imwgt_p=VisImagingWeight(*rvi_p, wtype=="Uniform" ? "none" : rmode, noise, robust,
    1184             :                                  actualNPixels_x, actualNPixels_y, actualCellSize_x,
    1185           0 :                                  actualCellSize_y, 0, 0, multiField);
    1186             : 
    1187             :                   /*
    1188             :                   if(rvi_p !=NULL){
    1189             :                     imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust,
    1190             :                                  actualNPixels, actualNPixels, actualCellSize,
    1191             :                                  actualCellSize, 0, 0, multiField);
    1192             :                   }
    1193             :                   else{
    1194             :                     ////This is slower by orders of magnitude as of 2014/06/25
    1195             :                     imwgt_p=VisImagingWeight(*vi_p, rmode, noise, robust,
    1196             :                                  actualNPixels, actualNPixels, actualCellSize,
    1197             :                                  actualCellSize, 0, 0, multiField);
    1198             :                   }
    1199             :                   */
    1200             :                     //timer.show("After making visweight ");
    1201             : 
    1202           0 :           }
    1203             :           else {
    1204             :                   //this->unlock();
    1205             :                   os << LogIO::SEVERE << "Unknown weighting " << type
    1206           0 :                                   << LogIO::EXCEPTION;
    1207           0 :                   return false;
    1208             :           }
    1209           0 :       }
    1210             :          
    1211             :          //// UV-Tapering
    1212             :          //cout << "Taper type : " << filtertype << " : " << (filtertype=="gaussian") <<  endl;
    1213           0 :          if( filtertype == "gaussian" ) {
    1214             :            //      os << "Setting uv-taper" << LogIO::POST;
    1215           0 :            imwgt_p.setFilter( filtertype,  filterbmaj, filterbmin, filterbpa );
    1216             :          }
    1217           0 :          rvi_p->useImagingWeight(imwgt_p);
    1218             :       ///////////////////////////////
    1219             :          
    1220           0 :     SynthesisUtilMethods::getResource("Set Weighting");
    1221             :          
    1222             :          ///     return true;
    1223             :          
    1224           0 :        }
    1225           0 :        catch(AipsError &x)
    1226             :          {
    1227           0 :            throw( AipsError("Error in Weighting : "+x.getMesg()) );
    1228           0 :          }
    1229             :        
    1230           0 :        return true;
    1231           0 :   }
    1232             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1233             :   
    1234             :   //// Get/Set Weight Grid.... write to disk and read
    1235             : 
    1236             :   /// todo : do for full mapper list, and taylor terms.
    1237           0 :   String SynthesisImager::getWeightDensity( )
    1238             :   {
    1239           0 :     String outname("");
    1240           0 :     LogIO os(LogOrigin("SynthesisImager", "getWeightDensity()", WHERE));
    1241             :     try
    1242             :       {
    1243             :         //if 
    1244           0 :         if(imwgt_p.getType() != "uniform"){
    1245           0 :           return outname;
    1246             :         }
    1247           0 :         IPosition newshape;
    1248           0 :         Vector<Int> shpOfGrid=imwgt_p.shapeOfdensityGrid();
    1249           0 :         if(shpOfGrid(2) > 1){
    1250           0 :           newshape=IPosition(5,shpOfGrid[0], shpOfGrid[1],1,1,shpOfGrid[2]);
    1251             :         }
    1252             :         else{
    1253           0 :           newshape=IPosition(4,shpOfGrid[0], shpOfGrid[1],1,1);
    1254             :         }
    1255           0 :         IPosition where=        IPosition(Vector<Int>((itsMappers.imageStore(0)->gridwt(newshape))->shape().nelements(),0));
    1256           0 :         if ( shpOfGrid[2] > 0 )
    1257             :           {
    1258           0 :             imwgt_p.toImageInterface(*(itsMappers.imageStore(0)->gridwt(newshape)));           }
    1259           0 :         outname=itsMappers.imageStore(0)->gridwt()->name();
    1260           0 :         itsMappers.releaseImageLocks();
    1261             : 
    1262           0 :       }
    1263           0 :     catch (AipsError &x)
    1264             :       {
    1265           0 :         throw(AipsError("In getWeightDensity : "+x.getMesg()));
    1266           0 :       }
    1267           0 :     return outname;
    1268           0 :   }
    1269             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1270             :   /// todo : do for full mapper list, and taylor terms.
    1271             :   
    1272           0 :   Bool SynthesisImager::setWeightDensity(const String& weightimagename)
    1273             :   {
    1274           0 :     LogIO os(LogOrigin("SynthesisImager", "setWeightDensity()", WHERE));
    1275             :     try
    1276             :       {
    1277             : 
    1278             :         //Array<Float> arr;
    1279             :         ///Use image 0 for weight density shape
    1280             :         //itsMappers.imageStore(0)->gridwt()->get(arr,true);
    1281           0 :         if(weightimagename.size() !=0){
    1282           0 :           Table::isReadable(weightimagename, True);
    1283           0 :           PagedImage<Float> im(weightimagename);
    1284           0 :           imwgt_p=VisImagingWeight(im);
    1285           0 :         }
    1286             :         else{
    1287           0 :           imwgt_p=VisImagingWeight(*(itsMappers.imageStore(0)->gridwt()));
    1288             : 
    1289             :         }
    1290           0 :         rvi_p->useImagingWeight(imwgt_p);
    1291           0 :         itsMappers.releaseImageLocks();
    1292             : 
    1293             :       }
    1294           0 :     catch (AipsError &x)
    1295             :       {
    1296           0 :         throw(AipsError("In setWeightDensity : "+x.getMesg()));
    1297           0 :       }
    1298           0 :     return true;
    1299           0 :   }
    1300             : 
    1301             :   //////////////////////////////////////////////////////////////////////////////
    1302             :   //////////////////////////////////////////////////////////////////////////////
    1303             : 
    1304             : 
    1305             :   //////////////////////////////////////////////////////////////////////////////
    1306             :   ////   Internal Functions start here. These are not visible to the tool layer.
    1307             :   //////////////////////////////////////////////////////////////////////////////
    1308             : 
    1309             :   // This should be called  at each defineimage
    1310          17 :   CountedPtr<SIImageStore> SynthesisImager::createIMStore(
    1311             :     String imageName,
    1312             :     CoordinateSystem& cSys,
    1313             :     IPosition imShape,
    1314             :     const Bool overwrite,
    1315             :     MSColumns& msc,
    1316             :     String mappertype,
    1317             :     uInt ntaylorterms,
    1318             :     Quantity distance,
    1319             :     const TcleanProcessingInfo& procInfo,
    1320             :     uInt facets,
    1321             :     Bool useweightimage,
    1322             :     const Vector<String> &startmodel,
    1323             :     const Bool makeSingleDishStore)
    1324             :   {
    1325          34 :     LogIO os( LogOrigin("SynthesisImager","createIMStore",WHERE) );
    1326             : 
    1327          17 :     CountedPtr<SIImageStore> imstor;
    1328             : 
    1329             :     try {
    1330             :       // Prepare miscellaneous image information
    1331          17 :       auto objectName = msc.field().name()(msc.fieldId()(0));
    1332             :       // Misc info for ImageStore. This will go to the 'miscinfo' table keyword
    1333          17 :       Record miscInfo;
    1334          17 :       auto telescop=msc.observation().telescopeName()(0);
    1335          17 :       miscInfo.define("INSTRUME", telescop);
    1336          17 :       miscInfo.define("distance", distance.get("m").getValue());
    1337          17 :       miscInfo.define("mpiprocs", procInfo.mpiprocs);
    1338          17 :       miscInfo.define("chnchnks", procInfo.chnchnks);
    1339          17 :       miscInfo.define("memreq", procInfo.memreq);
    1340          17 :       miscInfo.define("memavail", procInfo.memavail);
    1341             : 
    1342          17 :       if (mappertype == "default" or mappertype == "imagemosaic") {
    1343          51 :             imstor = std::make_shared<SIImageStore>(
    1344             :               imageName, cSys, imShape, objectName,
    1345             :               miscInfo, overwrite,
    1346          34 :               (useweightimage or mappertype == "imagemosaic"),
    1347             :               makeSingleDishStore
    1348          17 :             );
    1349             :       }
    1350           0 :       else if (mappertype == "multiterm") {
    1351             :             // Upcast with shared_ptr and then ...
    1352             :             std::shared_ptr<SIImageStore>
    1353           0 :             multiTermStore = std::make_shared<SIImageStoreMultiTerm>(
    1354             :               imageName, cSys, imShape,
    1355             :               objectName, miscInfo, facets,
    1356             :               overwrite, ntaylorterms, useweightimage
    1357           0 :             );
    1358             :             // ... assign to CountedPtr<SIImageStore>
    1359           0 :             imstor = multiTermStore;
    1360           0 :       }
    1361             :       else  { // imagemosaic currently not supported
    1362           0 :         throw(
    1363             :           AipsError(
    1364             :             "Internal Error : Invalid mapper type in"
    1365             :             " SynthesisImager::createIMStore"
    1366             :           )
    1367           0 :         );
    1368             :       }
    1369             : 
    1370             :       // Get polRep from 'msc' here, and send to imstore.
    1371          17 :       StokesImageUtil::PolRep polRep(StokesImageUtil::CIRCULAR);
    1372          17 :       Vector<String> polType=msc.feed().polarizationType()(0);
    1373          51 :       if (polType(0) != "X" and polType(0) != "Y" and
    1374          51 :           polType(0) != "R" and polType(0) != "L") {
    1375             :         os << LogIO::WARN << "Unknown stokes types in feed table: ["
    1376           0 :            << polType(0) << ", " << polType(1) << "]" << endl
    1377           0 :            << "Results open to question!" << LogIO::POST;
    1378             :       }
    1379             : 
    1380          17 :       if (polType(0) == "X" or polType(0) == "Y") {
    1381           0 :         polRep=StokesImageUtil::LINEAR;
    1382             :         os << LogIO::DEBUG1
    1383             :            << "Preferred polarization representation is linear"
    1384           0 :            << LogIO::POST;
    1385             :       }
    1386             :       else {
    1387          17 :         polRep=StokesImageUtil::CIRCULAR;
    1388             :         os << LogIO::DEBUG1
    1389             :            << "Preferred polarization representation is circular"
    1390          17 :            << LogIO::POST;
    1391             :       }
    1392             :       // End of reading polRep info
    1393             : 
    1394             :       // Send this info into ImageStore.
    1395          17 :       imstor->setDataPolFrame(polRep);
    1396             : 
    1397             :       // Set Starting model if it exists.
    1398             :       // cout << "In SI, set starting model to : " << startmodel << endl;
    1399          17 :       if (startmodel.nelements() > 0) {
    1400           0 :         imstor->setModelImage(startmodel);
    1401             :       }
    1402             : 
    1403          17 :       imstor->releaseLocks();
    1404             : 
    1405          17 :     }
    1406           0 :     catch (AipsError &x) {
    1407           0 :       throw(
    1408             :         AipsError(
    1409           0 :           "Error in createImStore : " + x.getMesg()
    1410             :         )
    1411           0 :       );
    1412           0 :     }
    1413             : 
    1414          34 :     return imstor;
    1415          17 :   }
    1416             :   
    1417           0 :   CountedPtr<SIMapper> SynthesisImager::createSIMapper(String mappertype,  
    1418             :                                                            CountedPtr<SIImageStore> imagestore,
    1419             :                                                            CountedPtr<FTMachine> ftmachine,
    1420             :                                                            CountedPtr<FTMachine> iftmachine,
    1421             :                                                        uInt /*ntaylorterms*/)
    1422             :   {
    1423           0 :     LogIO os( LogOrigin("SynthesisImager","createSIMapper",WHERE) );
    1424             :     
    1425           0 :     CountedPtr<SIMapper> localMapper;
    1426             : 
    1427             :     try
    1428             :       {
    1429             :         
    1430           0 :         if( mappertype == "default" || mappertype == "multiterm" )
    1431             :           {
    1432           0 :             localMapper = new SIMapper( imagestore, ftmachine, iftmachine );
    1433             :           }
    1434           0 :         else if( mappertype == "imagemosaic") // || mappertype == "mtimagemosaic" )
    1435             :           {
    1436           0 :             localMapper = new SIMapperImageMosaic( imagestore, ftmachine, iftmachine );
    1437             :           }
    1438             :         else
    1439             :           {
    1440           0 :             throw(AipsError("Unknown mapper type : " + mappertype));
    1441             :           }
    1442             : 
    1443             :       }
    1444           0 :     catch(AipsError &x) {
    1445           0 :         throw(AipsError("Error in createSIMapper : " + x.getMesg() ) );
    1446           0 :       }
    1447           0 :     return localMapper;
    1448           0 :   }
    1449             :   
    1450             : 
    1451           0 :   Block<CountedPtr<SIImageStore> > SynthesisImager::createFacetImageStoreList(
    1452             :                                                                               CountedPtr<SIImageStore> imagestore,
    1453             :                                                                               Int facets)
    1454             :   {
    1455           0 :       LogIO os(LogOrigin("SynthesisImager", "createFacetImageStoreList"));
    1456             : 
    1457           0 :       os << "Creating " << facets*facets << " facets in total " << LogIO::POST;
    1458             : 
    1459           0 :     Block<CountedPtr<SIImageStore> > facetList( facets*facets );
    1460             : 
    1461           0 :     if( facets==1 ) { facetList[0] = imagestore;  return facetList; }
    1462             : 
    1463             :     // Remember, only the FIRST field in each run can have facets. So, check for this.
    1464           0 :     if( ! unFacettedImStore_p.null() ) {
    1465           0 :         throw( AipsError("A facetted image has already been set. Facets are supported only for the main (first) field. Please submit a feature-request if you need multiple facets for outlier fields as well. ") );
    1466             :       }
    1467             :     
    1468           0 :     unFacettedImStore_p = imagestore;
    1469           0 :     facetsStore_p = facets;
    1470             :     
    1471             :     // Note : facets : Number of facets on a side.
    1472             :     // Note : facet : index from range(0, facets*facets)
    1473           0 :     for (Int facet=0; facet< facets*facets; ++facet){
    1474           0 :         facetList[facet] = unFacettedImStore_p->getSubImageStore(facet, facets);
    1475             :       }
    1476             :     
    1477           0 :     return facetList;
    1478           0 :   }
    1479             : 
    1480             :   /*
    1481             :   void SynthesisImager::setPsfFromOneFacet()
    1482             :   {
    1483             : 
    1484             :     if( unFacettedImStore_p.null() ){
    1485             :         throw(AipsError("Internal Error in SynthesisImager : Setting PSF on Null unfacettedimage"));
    1486             :       }
    1487             : 
    1488             :     // Copy the PSF from one facet to the center of the full image, to use for the minor cycle
    1489             :     //
    1490             :     // This code segment will work for single and multi-term 
    1491             :     // - for single term, the index will always be 0, and SIImageStore's access functions know this.
    1492             :     // - for multi-term, the index will be the taylor index and SIImageStoreMultiTerm knows this.
    1493             :       {
    1494             :         IPosition shape=(unFacettedImStore_p->psf(0))->shape();
    1495             :         IPosition blc(4, 0, 0, 0, 0);
    1496             :         IPosition trc=shape-1;
    1497             :         for(uInt tix=0; tix<2 * unFacettedImStore_p->getNTaylorTerms() - 1; tix++)
    1498             :           {
    1499             :             TempImage<Float> onepsf((itsMappers.imageStore(0)->psf(tix))->shape(), 
    1500             :                                     (itsMappers.imageStore(0)->psf(tix))->coordinates());
    1501             :             onepsf.copyData(*(itsMappers.imageStore(0)->psf(tix)));
    1502             :             //now set the original to 0 as we have a copy of one facet psf
    1503             :             (unFacettedImStore_p->psf(tix))->set(0.0);
    1504             :             blc[0]=(shape[0]-(onepsf.shape()[0]))/2;
    1505             :             trc[0]=onepsf.shape()[0]+blc[0]-1;
    1506             :             blc[1]=(shape[1]-(onepsf.shape()[1]))/2;
    1507             :             trc[1]=onepsf.shape()[1]+blc[1]-1;
    1508             :             Slicer sl(blc, trc, Slicer::endIsLast);
    1509             :             SubImage<Float> sub(*(unFacettedImStore_p->psf(tix)), sl, true);
    1510             :             sub.copyData(onepsf);
    1511             :           }
    1512             :       }
    1513             : 
    1514             :       //cout << "In setPsfFromOneFacet : sumwt : " << unFacettedImStore_p->sumwt()->get() << endl;
    1515             : 
    1516             :   }
    1517             :   */
    1518             : 
    1519           0 :   Block<CountedPtr<SIImageStore> > SynthesisImager::createChanChunkImageStoreList(
    1520             :                                                                               CountedPtr<SIImageStore> imagestore,
    1521             :                                                                               Int chanchunks)
    1522             :   {
    1523           0 :       LogIO os(LogOrigin("SynthesisImager", "createChanChunkImageStoreList"));
    1524             : 
    1525           0 :       Int extrachunks=0;
    1526           0 :       Int chunksize=imagestore->getShape()[3]/chanchunks;
    1527           0 :       Int rem=imagestore->getShape()[3] % chanchunks;
    1528             :       ///Avoid an extra chunk with 1 channel as it cause bumps in linear interpolation
    1529             :       ///See CAS-12625
    1530           0 :       while((rem==1) && (chunksize >1)){
    1531           0 :           chanchunks +=1;
    1532           0 :           chunksize=imagestore->getShape()[3]/chanchunks;
    1533           0 :           rem=imagestore->getShape()[3] % chanchunks;
    1534             :         }
    1535             :       
    1536             :       
    1537             :       
    1538           0 :       if( rem>0 )
    1539             :         {
    1540             :           // os << LogIO::WARN << "chanchunks ["+String::toString(chanchunks)+"] is not a divisor of nchan ["+String::toString(imagestore->getShape()[3])+"].";
    1541             :           //      os << "Therefore, "+String::toString(imagestore->getShape()[3] % chanchunks)+" channel(s) at the end of the cube will be treated as an extra chunk." << LogIO::POST ;
    1542             : 
    1543           0 :           if( rem < chunksize ) extrachunks=1;
    1544             :           else
    1545             :             {
    1546           0 :               extrachunks=rem/chunksize;
    1547           0 :               if( rem % chunksize > 0 ) extrachunks += 1;
    1548             :             }
    1549             :         }
    1550             :       
    1551             :       
    1552           0 :       os << "Creating " << chanchunks +extrachunks << " reference subCubes (channel chunks) for gridding " << LogIO::POST;
    1553             : 
    1554           0 :       Block<CountedPtr<SIImageStore> > chunkList( chanchunks + extrachunks );
    1555             : 
    1556           0 :     if( chanchunks==1 ) { chunkList[0] = imagestore;  return chunkList; }
    1557             : 
    1558             :     // Remember, only the FIRST field in each run can have chanchunks. So, check for this.
    1559           0 :     if( ! unChanChunkedImStore_p.null() ) {
    1560           0 :         throw( AipsError("A channel chunked image has already been set. Chanchunks are supported only for the main (first) field. Please submit a feature-request if you need multiple chanchunks for outlier fields as well. ") );
    1561             :       }
    1562             :     
    1563           0 :     unChanChunkedImStore_p = imagestore;
    1564           0 :     chanChunksStore_p = chanchunks;
    1565             :     
    1566           0 :     for (Int chunk=0; chunk< chanchunks+extrachunks; ++chunk){
    1567           0 :       chunkList[chunk] = unChanChunkedImStore_p->getSubImageStore(0,1,chunk, chanchunks);
    1568             :       }
    1569             :     
    1570           0 :     return chunkList;
    1571           0 :   }
    1572             : 
    1573             :   
    1574             :   
    1575             :   
    1576           0 :   void SynthesisImager::appendToMapperList(String imagename,  
    1577             :                                            CoordinateSystem& csys, 
    1578             :                                            IPosition imshape,
    1579             :                                            CountedPtr<FTMachine>& ftm,
    1580             :                                            CountedPtr<FTMachine>& iftm,
    1581             :                                            Quantity distance, 
    1582             :                                            Int facets,
    1583             :                                            Int chanchunks,
    1584             :                                            const Bool overwrite,
    1585             :                                            String mappertype,
    1586             :                                            Float padding,
    1587             :                                            uInt ntaylorterms,
    1588             :                                            const Vector<String> &startmodel)
    1589             :     {
    1590           0 :       LogIO log_l(LogOrigin("SynthesisImager", "appendToMapperList(ftm)"));
    1591             :       //---------------------------------------------
    1592             :       // Some checks..
    1593           0 :       if(facets > 1 && itsMappers.nMappers() > 0)
    1594           0 :         log_l << "Facetted image has to be the first of multifields" << LogIO::EXCEPTION;
    1595             : 
    1596           0 :      TcleanProcessingInfo procInfo;
    1597           0 :      if(chanchunks<1)
    1598             :         {
    1599           0 :           log_l << "Automatically calculate chanchunks";
    1600           0 :           log_l << " using imshape : " << imshape << LogIO::POST;
    1601             : 
    1602             :           // Do calculation here.
    1603             :           // This runs once per image field (for multi-field imaging)
    1604             :           // This runs once per cube partition, and will see only its own partition's shape
    1605           0 :           chanchunks=1;
    1606             : 
    1607           0 :           CompositeNumber cn(uInt(imshape[0] * 2));
    1608             :           // heuristic factors multiplied to imshape based on gridder
    1609           0 :           size_t fudge_factor = 15;
    1610           0 :           if (ftm->name()=="MosaicFTNew") {
    1611           0 :               fudge_factor = 20;
    1612             :           }
    1613           0 :           else if (ftm->name()=="GridFT") {
    1614           0 :               fudge_factor = 9;
    1615             :           }
    1616             : 
    1617           0 :           Double required_mem = fudge_factor * sizeof(Float);
    1618           0 :           for (size_t i = 0; i < imshape.nelements(); i++) {
    1619             :               // gridding pads image and increases to composite number
    1620           0 :               if (i < 2) {
    1621           0 :                   required_mem *= cn.nextLargerEven(Int(padding*Float(imshape[i])-0.5));
    1622             :               }
    1623             :               else {
    1624           0 :                   required_mem *= imshape[i];
    1625             :               }
    1626             :           }
    1627             : 
    1628             :           // get number of tclean processes running on the same machine
    1629           0 :           size_t nlocal_procs = 1;
    1630           0 :           if (getenv("OMPI_COMM_WORLD_LOCAL_SIZE")) {
    1631           0 :               std::stringstream ss(getenv("OMPI_COMM_WORLD_LOCAL_SIZE"));
    1632           0 :               ss >> nlocal_procs;
    1633           0 :           }
    1634             :           // assumes all processes need the same amount of memory
    1635           0 :           required_mem *= nlocal_procs;
    1636             :           Double usr_memfrac, usr_mem;
    1637           0 :           AipsrcValue<Double>::find(usr_memfrac, "system.resources.memfrac", 80.);
    1638           0 :           AipsrcValue<Double>::find(usr_mem, "system.resources.memory", -1024.);
    1639             :           Double memory_avail;
    1640           0 :           if (usr_mem > 0.) {
    1641           0 :               memory_avail = usr_mem * 1024. * 1024.;
    1642             :           }
    1643             :           else {
    1644           0 :             memory_avail = Double(HostInfo::memoryFree()) * (usr_memfrac / 100.) * 1024.;
    1645             :           }
    1646             : 
    1647             :           // compute required chanchunks to fit into the available memory
    1648           0 :           chanchunks = (int)std::ceil((Double)required_mem / memory_avail);
    1649           0 :           if (imshape.nelements() == 4 && imshape[3] < chanchunks) {
    1650           0 :               chanchunks = imshape[3];
    1651             :               // TODO make chanchunks a divisor of nchannels?
    1652             :           }
    1653           0 :           chanchunks = chanchunks < 1 ? 1 : chanchunks;
    1654             : 
    1655           0 :           log_l << "Required memory " << required_mem / nlocal_procs / 1024. / 1024. / 1024.
    1656           0 :                  << "\nAvailable memory " << memory_avail / 1024. / 1024 / 1024.
    1657             :                  << " (rc: memory fraction " << usr_memfrac << "% memory " << usr_mem / 1024.
    1658             :                  << ")\n" << nlocal_procs << " other processes on node\n"
    1659           0 :                  << "Setting chanchunks to " << chanchunks << LogIO::POST;
    1660             : 
    1661           0 :           procInfo.mpiprocs = nlocal_procs;
    1662           0 :           procInfo.chnchnks = chanchunks;
    1663           0 :           const float toGB = 1024.0 * 1024.0 * 1024.0;
    1664           0 :           procInfo.memavail = memory_avail / toGB;
    1665           0 :           procInfo.memreq = required_mem / toGB;
    1666           0 :         }
    1667             : 
    1668           0 :       if( imshape.nelements()==4 && imshape[3]<chanchunks )
    1669             :         {
    1670           0 :           log_l << LogIO::WARN << "An image with " << imshape[3] << " channel(s) cannot be divided into " << chanchunks << " chunks. Please set chanchunks=1 or choose chanchunks<nchan." << LogIO::EXCEPTION;
    1671             :         }
    1672             : 
    1673           0 :       if(chanchunks > 1 && itsMappers.nMappers() > 0)
    1674           0 :         log_l << "Channel chunking is currently not supported with multi(outlier)-fields. Please submit a feature request if needed." << LogIO::EXCEPTION;
    1675             : 
    1676           0 :       if(chanchunks > 1) itsDataLoopPerMapper=true;
    1677             :       
    1678           0 :       AlwaysAssert( ( ( ! (ftm->name()=="MosaicFTNew" && mappertype=="imagemosaic") )  && 
    1679             :                       ( ! (ftm->name()=="AWProjectWBFTNew" && mappertype=="imagemosaic") )) ,
    1680             :                     AipsError );
    1681             :       //---------------------------------------------
    1682             : 
    1683             :       // Create the ImageStore object
    1684           0 :       CountedPtr<SIImageStore> imstor;
    1685           0 :       MSColumns msc(mss4vi_p[0]);
    1686           0 :       imstor = createIMStore(imagename, csys, imshape, overwrite, msc, mappertype, ntaylorterms, distance, procInfo, facets, iftm->useWeightImage(), startmodel );
    1687             : 
    1688             :       // Create the Mappers
    1689           0 :       if( facets<2 && chanchunks<2) // One facet. Just add the above imagestore to the mapper list.
    1690             :         {
    1691           0 :           itsMappers.addMapper(  createSIMapper( mappertype, imstor, ftm, iftm, ntaylorterms) );
    1692             :         }
    1693             :       else // This field is facetted. Make a list of reference imstores, and add all to the mapper list.
    1694             :         {
    1695             : 
    1696           0 :           if ( facets>1 && chanchunks==1 )
    1697             :             {
    1698             :               // Make and connect the list.
    1699           0 :               Block<CountedPtr<SIImageStore> > imstorList = createFacetImageStoreList( imstor, facets );
    1700           0 :               for( uInt facet=0; facet<imstorList.nelements(); facet++)
    1701             :                 {
    1702           0 :                   CountedPtr<FTMachine> new_ftm, new_iftm;
    1703           0 :                   if(facet==0){ new_ftm = ftm;  new_iftm = iftm; }
    1704           0 :                   else{ new_ftm=ftm->cloneFTM();  new_iftm=iftm->cloneFTM(); }
    1705           0 :                   itsMappers.addMapper(createSIMapper( mappertype, imstorList[facet], new_ftm, new_iftm, ntaylorterms));
    1706           0 :                 }
    1707           0 :             }// facets
    1708           0 :           else if ( facets==1 && chanchunks>1 )
    1709             :             {
    1710             :               // Make and connect the list.
    1711           0 :               Block<CountedPtr<SIImageStore> > imstorList = createChanChunkImageStoreList( imstor, chanchunks );
    1712           0 :               for( uInt chunk=0; chunk<imstorList.nelements(); chunk++)
    1713             :                 {
    1714           0 :                   CountedPtr<FTMachine> new_ftm, new_iftm;
    1715           0 :                   if(chunk==0){ new_ftm = ftm;  new_iftm = iftm; }
    1716           0 :                   else{ new_ftm=ftm->cloneFTM();  new_iftm=iftm->cloneFTM(); }
    1717           0 :                   itsMappers.addMapper(createSIMapper( mappertype, imstorList[chunk], new_ftm, new_iftm, ntaylorterms));
    1718           0 :                 }
    1719           0 :             }// chanchunks
    1720             :           else
    1721             :             {
    1722           0 :               throw( AipsError("Error in requesting "+String::toString(facets)+" facets on a side with " + String::toString(chanchunks) + " channel chunks.  Support for faceting along with channel chunking is not yet available. Please submit a feature-request if you need multiple facets as well as chanchunks. ") );
    1723             :             }
    1724             : 
    1725             :         }// facets or chunks
    1726             : 
    1727           0 :     }
    1728             : 
    1729             :   /////////////////////////
    1730             :   /*
    1731             :   Bool SynthesisImager::toUseWeightImage(CountedPtr<FTMachine>& ftm, String mappertype)
    1732             :   {
    1733             :     if( (ftm->name() == "GridFT" || ftm->name() == "WProjectFT")&&(mappertype!="imagemosaic") )  
    1734             :       { return false; }
    1735             :     else
    1736             :       { return true; }
    1737             :   }
    1738             :   */
    1739             : 
    1740             :   // Make the FT-Machine and related objects (cfcache, etc.)
    1741           0 :   void SynthesisImager::createFTMachine(CountedPtr<FTMachine>& theFT, 
    1742             :                                         CountedPtr<FTMachine>& theIFT, 
    1743             :                                         const String& ftname,
    1744             :                                         const uInt nTaylorTerms,
    1745             :                                         const String mType,
    1746             :                                         const Int facets,            //=1
    1747             :                                         //------------------------------
    1748             :                                         const Int wprojplane,        //=1,
    1749             :                                         const Float padding,         //=1.0,
    1750             :                                         const Bool useAutocorr,      //=false,
    1751             :                                         const Bool useDoublePrec,    //=true,
    1752             :                                         const String gridFunction,   //=String("SF"),
    1753             :                                         //------------------------------
    1754             :                                         const Bool aTermOn,          //= true,
    1755             :                                         const Bool psTermOn,         //= true,
    1756             :                                         const Bool mTermOn,          //= false,
    1757             :                                         const Bool wbAWP,            //= true,
    1758             :                                         const String cfCache,        //= "",
    1759             :                                         const Bool usePointing,       //= false,
    1760             :                                         const Bool doPBCorr,         //= true,
    1761             :                                         const Bool conjBeams,        //= true,
    1762             :                                         const Float computePAStep,         //=360.0
    1763             :                                         const Float rotatePAStep,          //=5.0
    1764             :                                         const String interpolation,  //="linear"
    1765             :                                         const Bool freqFrameValid, //=true
    1766             :                                         const Int cache,             //=1000000000,
    1767             :                                         const Int tile,               //=16
    1768             :                                         const String stokes, //=I
    1769             :                                         const String imageNamePrefix
    1770             :                                         )
    1771             : 
    1772             :   {
    1773           0 :     LogIO os( LogOrigin("SynthesisImager","createFTMachine",WHERE));
    1774             : 
    1775           0 :     if(ftname=="gridft"){
    1776           0 :       if(facets >1){
    1777           0 :           theFT=new GridFT(cache, tile, gridFunction, mLocation_p, phaseCenter_p, padding, useAutocorr, useDoublePrec);
    1778           0 :           theIFT=new GridFT(cache, tile, gridFunction, mLocation_p, phaseCenter_p, padding, useAutocorr, useDoublePrec);
    1779             : 
    1780             :       }
    1781             :       else{
    1782           0 :           theFT=new GridFT(cache, tile, gridFunction, mLocation_p, padding, useAutocorr, useDoublePrec);
    1783           0 :           theIFT=new GridFT(cache, tile, gridFunction, mLocation_p, padding, useAutocorr, useDoublePrec);
    1784             :       }
    1785             :     }
    1786           0 :     else if(ftname== "wprojectft"){
    1787           0 :      Double maxW=-1.0;
    1788           0 :      Double minW=-1.0;
    1789           0 :      Double rmsW=-1.0;
    1790           0 :      if(wprojplane <1)
    1791           0 :         WProjectFT::wStat(*rvi_p, minW, maxW, rmsW);
    1792           0 :     if(facets >1){
    1793           0 :       theFT=new WProjectFT(wprojplane,  phaseCenter_p, mLocation_p,
    1794           0 :                            cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
    1795           0 :       theIFT=new WProjectFT(wprojplane,  phaseCenter_p, mLocation_p,
    1796           0 :                             cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
    1797             :     }
    1798             :     else{
    1799           0 :       theFT=new WProjectFT(wprojplane,  mLocation_p,
    1800           0 :                            cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
    1801           0 :       theIFT=new WProjectFT(wprojplane,  mLocation_p,
    1802           0 :                             cache/2, tile, useAutocorr, padding, useDoublePrec, minW, maxW, rmsW);
    1803             :     }
    1804           0 :       CountedPtr<WPConvFunc> sharedconvFunc=static_cast<WProjectFT &>(*theFT).getConvFunc();
    1805             :       //static_cast<WProjectFT &>(*theFT).setConvFunc(sharedconvFunc);
    1806           0 :       static_cast<WProjectFT &>(*theIFT).setConvFunc(sharedconvFunc);
    1807           0 :     }
    1808           0 :     else if ((ftname == "awprojectft") || (ftname== "mawprojectft") || (ftname == "protoft")) {
    1809           0 :       createAWPFTMachine(theFT, theIFT, ftname, facets, wprojplane, 
    1810             :                          padding, useAutocorr, useDoublePrec, gridFunction,
    1811             :                          aTermOn, psTermOn, mTermOn, wbAWP, cfCache, 
    1812             :                          usePointing, doPBCorr, conjBeams, computePAStep,
    1813             :                          rotatePAStep, cache,tile,imageNamePrefix);
    1814             :     }
    1815           0 :     else if ( ftname == "mosaic" || ftname== "mosft" || ftname == "mosaicft" || ftname== "MosaicFT"){
    1816             : 
    1817           0 :       createMosFTMachine(theFT, theIFT, padding, useAutocorr, useDoublePrec, rotatePAStep, stokes, conjBeams);
    1818             :     }
    1819             :     else
    1820             :       {
    1821           0 :         throw( AipsError( "Invalid FTMachine name : " + ftname ) );
    1822             :       }
    1823             :     /* else if(ftname== "MosaicFT"){
    1824             : 
    1825             :        }*/
    1826             : 
    1827             : 
    1828             : 
    1829             :     ///////// Now, clone and pack the chosen FT into a MultiTermFT if needed.
    1830           0 :     if( mType=="multiterm" )
    1831             :       {
    1832           0 :         AlwaysAssert( nTaylorTerms>=1 , AipsError );
    1833             : 
    1834           0 :         CountedPtr<FTMachine> theMTFT = new MultiTermFTNew( theFT , nTaylorTerms, true/*forward*/ );
    1835           0 :         CountedPtr<FTMachine> theMTIFT = new MultiTermFTNew( theIFT , nTaylorTerms, false/*forward*/ );
    1836             : 
    1837           0 :         theFT = theMTFT;
    1838           0 :         theIFT = theMTIFT;
    1839           0 :       }
    1840             : 
    1841             : 
    1842             : 
    1843             : 
    1844             :     ////// Now, set the SkyJones if needed, and if not internally generated.
    1845           0 :     if( mType=="imagemosaic" && 
    1846           0 :         (ftname != "awprojectft" && ftname != "mawprojectft" && ftname != "proroft") )
    1847             :       {
    1848           0 :         CountedPtr<SkyJones> vp;
    1849           0 :         MSColumns msc(mss4vi_p[0]);
    1850           0 :         Quantity parang(0.0,"deg");
    1851           0 :         Quantity skyposthreshold(0.0,"deg");
    1852           0 :         vp = new VPSkyJones(msc, true,  parang, BeamSquint::NONE,skyposthreshold);
    1853             : 
    1854           0 :         Vector<CountedPtr<SkyJones> > skyJonesList(1);
    1855           0 :         skyJonesList(0) = vp;
    1856           0 :         theFT->setSkyJones(  skyJonesList );
    1857           0 :         theIFT->setSkyJones(  skyJonesList );
    1858             : 
    1859           0 :       }
    1860             : 
    1861             :     //// For mode=cubedata, set the freq frame to invalid..
    1862             :     // get this info from buildCoordSystem
    1863           0 :     Vector<Int> tspws(0);
    1864             :     //theFT->setSpw( tspws, false );
    1865             :     //theIFT->setSpw( tspws, false );
    1866           0 :     theFT->setSpw( tspws, freqFrameValid );
    1867           0 :     theIFT->setSpw( tspws, freqFrameValid );
    1868             : 
    1869             :     //// Set interpolation mode
    1870           0 :     theFT->setFreqInterpolation( interpolation );
    1871           0 :     theIFT->setFreqInterpolation( interpolation );
    1872             : 
    1873             :     //channel selections from spw param
    1874           0 :     theFT->setSpwChanSelection(chanSel_p);
    1875           0 :     theIFT->setSpwChanSelection(chanSel_p);
    1876           0 :   }
    1877             : 
    1878             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1879             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1880             : 
    1881           0 :   void SynthesisImager::createAWPFTMachine(CountedPtr<FTMachine>& theFT, CountedPtr<FTMachine>& theIFT, 
    1882             :                                            const String&,// ftmName,
    1883             :                                            const Int,// facets,            //=1
    1884             :                                            //------------------------------
    1885             :                                            const Int wprojPlane,        //=1,
    1886             :                                            const Float,// padding,         //=1.0,
    1887             :                                            const Bool,// useAutocorr,      //=false,
    1888             :                                            const Bool useDoublePrec,    //=true,
    1889             :                                            const String,// gridFunction,   //=String("SF"),
    1890             :                                            //------------------------------
    1891             :                                            const Bool aTermOn,          //= true,
    1892             :                                            const Bool psTermOn,         //= true,
    1893             :                                            const Bool mTermOn,          //= false,
    1894             :                                            const Bool wbAWP,            //= true,
    1895             :                                            const String cfCache,        //= "",
    1896             :                                            const Bool usePointing,       //= false,
    1897             :                                            const Bool doPBCorr,         //= true,
    1898             :                                            const Bool conjBeams,        //= true,
    1899             :                                            const Float computePAStep,   //=360.0
    1900             :                                            const Float rotatePAStep,    //=5.0
    1901             :                                            const Int cache,             //=1000000000,
    1902             :                                            const Int tile,               //=16
    1903             :                                            const String imageNamePrefix
    1904             :                                         )
    1905             : 
    1906             :   {
    1907           0 :     LogIO os( LogOrigin("SynthesisImager","createAWPFTMachine",WHERE));
    1908             : 
    1909           0 :     if (wprojPlane<=1)
    1910             :       {
    1911             :         os << LogIO::NORMAL
    1912             :            << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    1913           0 :            << LogIO::POST;
    1914           0 :         os << LogIO::NORMAL << "Performing WBA-Projection" << LogIO::POST; // Loglevel PROGRESS
    1915             :       }
    1916             :     // if((wprojPlane>1)&&(wprojPlane<64)) 
    1917             :     //   {
    1918             :     //  os << LogIO::WARN
    1919             :     //     << "No. of w-planes set too low for W projection - recommend at least 128"
    1920             :     //     << LogIO::POST;
    1921             :     //  os << LogIO::NORMAL << "Performing WBAW-Projection" << LogIO::POST; // Loglevel PROGRESS
    1922             :     //   }
    1923             : 
    1924             :     // CountedPtr<ATerm> apertureFunction = createTelescopeATerm(mss4vi_p[0], aTermOn);
    1925             :     // CountedPtr<PSTerm> psTerm = new PSTerm();
    1926             :     // CountedPtr<WTerm> wTerm = new WTerm();
    1927             :     
    1928             :     // //
    1929             :     // // Selectively switch off CFTerms.
    1930             :     // //
    1931             :     // if (aTermOn == false) {apertureFunction->setOpCode(CFTerms::NOOP);}
    1932             :     // if (psTermOn == false) psTerm->setOpCode(CFTerms::NOOP);
    1933             : 
    1934             :     // //
    1935             :     // // Construct the CF object with appropriate CFTerms.
    1936             :     // //
    1937             :     // CountedPtr<ConvolutionFunction> tt;
    1938             :     // tt = AWProjectFT::makeCFObject(aTermOn, psTermOn, true, mTermOn, wbAWP);
    1939             :     // CountedPtr<ConvolutionFunction> awConvFunc;
    1940             :     // //    awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm, !wbAWP);
    1941             :     // if ((ftmName=="mawprojectft") || (mTermOn))
    1942             :     //   awConvFunc = new AWConvFuncEPJones(apertureFunction,psTerm,wTerm,wbAWP);
    1943             :     // else
    1944             :     //   awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm,wbAWP);
    1945             : 
    1946           0 :     MSObservationColumns msoc(mss4vi_p[0].observation());
    1947           0 :     String telescopeName=msoc.telescopeName()(0);
    1948             :     CountedPtr<ConvolutionFunction> awConvFunc = AWProjectFT::makeCFObject(telescopeName, 
    1949             :                                                                            aTermOn,
    1950             :                                                                            psTermOn, (wprojPlane > 1),
    1951           0 :                                                                            mTermOn, wbAWP, conjBeams);
    1952             :     //
    1953             :     // Construct the appropriate re-sampler.
    1954             :     //
    1955           0 :     CountedPtr<VisibilityResamplerBase> visResampler;
    1956             :     //    if (ftmName=="protoft") visResampler = new ProtoVR();
    1957             :     //elsef
    1958           0 :       visResampler = new AWVisResampler();
    1959             :     //    CountedPtr<VisibilityResamplerBase> visResampler = new VisibilityResampler();
    1960             : 
    1961             :     //
    1962             :     // Construct and initialize the CF cache object.
    1963             :     //
    1964             : 
    1965             : 
    1966             :     // CountedPtr<CFCache> cfCacheObj = new CFCache();
    1967             :     // cfCacheObj->setCacheDir(cfCache.data());
    1968             :     // //    cerr << "Setting wtImagePrefix to " << imageNamePrefix.c_str() << endl;
    1969             :     // cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
    1970             :     // cfCacheObj->initCache2();
    1971             : 
    1972           0 :       CountedPtr<CFCache> cfCacheObj;
    1973             :       
    1974             : 
    1975             :     //
    1976             :     // Finally construct the FTMachine with the CFCache, ConvFunc and
    1977             :     // Re-sampler objects.  
    1978             :     //
    1979           0 :     Float pbLimit_l=1e-2;
    1980           0 :     theFT = new AWProjectWBFTNew(wprojPlane, cache/2, 
    1981             :                               cfCacheObj, awConvFunc, 
    1982             :                               visResampler,
    1983             :                               /*true */usePointing, doPBCorr, 
    1984             :                               tile, computePAStep, pbLimit_l, true,conjBeams,
    1985           0 :                               useDoublePrec);
    1986             : 
    1987           0 :     cfCacheObj = new CFCache();
    1988           0 :     cfCacheObj->setCacheDir(cfCache.data());
    1989             :     // Get the LAZYFILL setting from the user configuration.  If not
    1990             :     // found, default to False.
    1991             :     //
    1992             :     // With lazy fill ON, CFCache loads the required CFs on-demand
    1993             :     // from the disk.  And periodically triggers garbage collection to
    1994             :     // release CFs that aren't required immediately.
    1995           0 :     cfCacheObj->setLazyFill(SynthesisUtils::getenv("CFCache.LAZYFILL",1)==1);
    1996             : 
    1997             :     //    cerr << "Setting wtImagePrefix to " << imageNamePrefix.c_str() << endl;
    1998           0 :     cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
    1999           0 :     cfCacheObj->initCache2();
    2000             : 
    2001           0 :     theFT->setCFCache(cfCacheObj);
    2002             :     
    2003             : 
    2004           0 :     Quantity rotateOTF(rotatePAStep,"deg");
    2005           0 :     static_cast<AWProjectWBFTNew &>(*theFT).setObservatoryLocation(mLocation_p);
    2006           0 :     static_cast<AWProjectWBFTNew &>(*theFT).setPAIncrement(Quantity(computePAStep,"deg"),rotateOTF);
    2007             : 
    2008             :     // theIFT = new AWProjectWBFT(wprojPlane, cache/2, 
    2009             :     //                         cfCacheObj, awConvFunc, 
    2010             :     //                         visResampler,
    2011             :     //                         /*true */usePointing, doPBCorr, 
    2012             :     //                         tile, computePAStep, pbLimit_l, true,conjBeams,
    2013             :     //                         useDoublePrec);
    2014             : 
    2015             :     // static_cast<AWProjectWBFT &>(*theIFT).setObservatoryLocation(mLocation_p);
    2016             :     // static_cast<AWProjectWBFT &>(*theIFT).setPAIncrement(Quantity(computePAStep,"deg"),rotateOTF);
    2017             : 
    2018           0 :     theIFT = new AWProjectWBFTNew(static_cast<AWProjectWBFTNew &>(*theFT));
    2019             : 
    2020             :     //// Send in Freq info.
    2021           0 :     os << "Sending frequency selection information " <<  mssFreqSel_p  <<  " to AWP FTM." << LogIO::POST;
    2022           0 :     theFT->setSpwFreqSelection( mssFreqSel_p );
    2023           0 :     theIFT->setSpwFreqSelection( mssFreqSel_p );
    2024             : 
    2025           0 :   }
    2026             : 
    2027             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2028             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2029             : 
    2030           0 :   ATerm* SynthesisImager::createTelescopeATerm(const MeasurementSet& ms, const Bool& isATermOn)
    2031             :   {
    2032           0 :     LogIO os(LogOrigin("SynthesisImager", "createTelescopeATerm",WHERE));
    2033             :     
    2034           0 :     if (!isATermOn) return new NoOpATerm();
    2035             :     
    2036           0 :     MSObservationColumns msoc(ms.observation());
    2037           0 :     String ObsName=msoc.telescopeName()(0);
    2038           0 :     if ((ObsName == "EVLA") || (ObsName == "VLA"))
    2039           0 :       return new EVLAAperture();
    2040             :     else
    2041             :       {
    2042           0 :         os << "Telescope name ('"+
    2043           0 :           ObsName+"') in the MS not recognized to create the telescope specific ATerm" 
    2044           0 :            << LogIO::WARN;
    2045             :       }
    2046             :     
    2047           0 :     return NULL;
    2048           0 :   }
    2049             : 
    2050             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2051             : 
    2052           0 :   void SynthesisImager::getVPRecord(Record &rec, PBMath::CommonPB &kpb, String telescop)
    2053             :   {
    2054           0 :     LogIO os(LogOrigin("SynthesisImager", "getVPRecord",WHERE));
    2055             : 
    2056           0 :     VPManager *vpman=VPManager::Instance();
    2057           0 :     if( itsVpTable != String("") )  
    2058             :       {
    2059           0 :         os << "Loading Voltage Pattern information from " << itsVpTable << LogIO::POST;
    2060           0 :         vpman->loadfromtable(itsVpTable);
    2061             :       }
    2062             :     else
    2063             :       {
    2064             :         //      os << "Using Voltage Pattern currently set in the VPManager" << LogIO::POST;
    2065           0 :         os << "Using default Voltage Patterns from the VPManager" << LogIO::POST;
    2066           0 :         vpman->reset();
    2067             :       }
    2068             : 
    2069             :     
    2070             :     
    2071             : 
    2072             :     //    PBMath::CommonPB kpb;
    2073           0 :     PBMath::enumerateCommonPB(telescop, kpb);
    2074             :     //    Record rec;
    2075           0 :     vpman->getvp(rec, telescop);
    2076             : 
    2077             :     //ostringstream oss; rec.print(oss);
    2078             :     //os << "Using VP model : " << oss.str() << LogIO::POST;
    2079             : 
    2080           0 :     if(rec.empty()){
    2081           0 :       if((telescop=="EVLA")){
    2082           0 :         os << LogIO::WARN << "vpmanager does not list EVLA. Using VLA beam parameters. To use EVLA beams, please use the vpmanager and set the vptable parameter in tclean (see inline help for vptable)." << LogIO::POST; 
    2083           0 :         telescop="VLA";
    2084           0 :         vpman->getvp(rec, telescop);
    2085           0 :         kpb=PBMath::VLA;
    2086             :       }
    2087             :       else{
    2088             :         //os << LogIO::WARN << "vpmanager does not have a beam for antenna : "+telescop <<".\n Please use the vpanager to define one (and optionally save its state as a table and supply its name via the vptable parameter.)" << LogIO::POST;
    2089           0 :         os << LogIO::WARN << "vpmanager does not have a beam for antenna : "+telescop <<".\n If needed, please use the vpanager to define one (and optionally save its state as a table and supply its name via the vptable parameter.). \n For now, we will proceed by reading dish diameters from the ANTENNA subtable, and form Airy disk beams." << LogIO::POST;
    2090           0 :         kpb=PBMath::UNKNOWN;
    2091           0 :         rec.define("name","COMMONPB");
    2092           0 :         rec.define("commonpb","NONE");
    2093             :       }
    2094             :     }
    2095             :     
    2096           0 :   }// get VPRecord
    2097             : 
    2098             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2099           0 :   void SynthesisImager:: createMosFTMachine(CountedPtr<FTMachine>& theFT,CountedPtr<FTMachine>&  theIFT, const Float /*padding*/, const Bool useAutoCorr, const Bool useDoublePrec, const Float rotatePAStep, const String stokes, const Bool /*doConjBeam*/){
    2100             :     
    2101           0 :     LogIO os(LogOrigin("SynthesisImager", "createMosFTMachine",WHERE));
    2102             :    
    2103           0 :     rvi_p->originChunks();
    2104           0 :     MSColumns msc(rvi_p->ms());
    2105           0 :     String telescop=msc.observation().telescopeName()(0);
    2106             :     ///Multi ms with different telescop
    2107           0 :     Bool multiTel=False;
    2108           0 :     for(rvi_p->originChunks(); rvi_p->moreChunks(); rvi_p->nextChunk()){
    2109           0 :       if(rvi_p->newMS() && telescop !=  MSColumns(rvi_p->ms()).observation().telescopeName()(0))
    2110           0 :         multiTel=True;
    2111             :     }
    2112           0 :     rvi_p->originChunks();
    2113             :   
    2114             :     PBMath::CommonPB kpb;
    2115           0 :     Record rec;
    2116           0 :     getVPRecord( rec, kpb, telescop );
    2117             :     
    2118             :     /*
    2119             :      VPManager *vpman=VPManager::Instance();
    2120             : 
    2121             :     if( itsVpTable != String("") ) vpman->loadfromtable(itsVpTable);
    2122             : 
    2123             :     PBMath::CommonPB kpb;
    2124             :     PBMath::enumerateCommonPB(telescop, kpb);
    2125             :     Record rec;
    2126             :     vpman->getvp(rec, telescop);
    2127             :     if(rec.empty()){
    2128             :         if((telescop=="EVLA")){
    2129             :           os << LogIO::WARN << "vpmanager does not list EVLA. Using VLA beam parameters" << LogIO::POST; 
    2130             :           telescop="VLA";
    2131             :           vpman->getvp(rec, telescop);
    2132             :           kpb=PBMath::VLA;
    2133             :         }
    2134             :         else{
    2135             :           os << LogIO::SEVERE << "vpmanager does not have a beam "+telescop <<"\n You can use VPManager to define one" << LogIO::POST;
    2136             :         }
    2137             :     }
    2138             : 
    2139             :     */
    2140             : 
    2141           0 :     if(rec.empty()){os << LogIO::SEVERE << "Cannot proceed with mosaicft gridder without a valid PB model" << LogIO::POST; }
    2142             : 
    2143             : 
    2144           0 :     VPSkyJones* vps=NULL;
    2145           0 :     if(rec.asString("name")=="COMMONPB" && kpb !=PBMath::UNKNOWN ){
    2146           0 :       vps= new VPSkyJones(msc, true, Quantity(rotatePAStep, "deg"), BeamSquint::GOFIGURE, Quantity(360.0, "deg"));
    2147             :       /////Don't know which parameter has pb threshold cutoff that the user want 
    2148             :       ////leaving at default
    2149             :       ////vps.setThreshold(minPB);
    2150             :       
    2151             :     }
    2152             :     else{
    2153           0 :       PBMath myPB(rec);
    2154           0 :       String whichPBMath;
    2155           0 :       PBMathInterface::namePBClass(myPB.whichPBClass(), whichPBMath);
    2156           0 :       os  << "Using the PB defined by " << whichPBMath << " for beam calculation for telescope " << telescop << LogIO::POST;
    2157           0 :       vps= new VPSkyJones(telescop, myPB, Quantity(rotatePAStep, "deg"), BeamSquint::GOFIGURE, Quantity(360.0, "deg"));
    2158           0 :       kpb=PBMath::DEFAULT;
    2159           0 :     }
    2160             :    
    2161             : 
    2162             :     //cerr << "SImager tel " << ((vps) ? vps->telescope(): "NOTEL " )  << " multiTel " << multiTel << endl;
    2163             :  
    2164           0 :     theFT = new MosaicFTNew(vps, mLocation_p, stokes, 1000000000, 16, useAutoCorr, 
    2165           0 :                       useDoublePrec);
    2166           0 :     PBMathInterface::PBClass pbtype=((kpb==PBMath::EVLA) || multiTel)? PBMathInterface::COMMONPB: PBMathInterface::AIRY;
    2167           0 :     if(rec.asString("name")=="IMAGE")
    2168           0 :        pbtype=PBMathInterface::IMAGE;
    2169             :     ///Use Heterogenous array mode for the following
    2170             :     ///Added EVLA in it to use different beam models for different frequencies
    2171           0 :     if((kpb == PBMath::UNKNOWN) || (kpb==PBMath::OVRO) || (kpb==PBMath::ACA)
    2172           0 :        || (kpb==PBMath::ALMA) || (kpb==PBMath::EVLA) || multiTel){
    2173           0 :       CountedPtr<SimplePBConvFunc> mospb=new HetArrayConvFunc(pbtype, "");
    2174           0 :       static_cast<MosaicFTNew &>(*theFT).setConvFunc(mospb);
    2175           0 :     }
    2176             :     ///////////////////make sure both FTMachine share the same conv functions.
    2177           0 :     theIFT= new MosaicFTNew(static_cast<MosaicFTNew &>(*theFT));
    2178             : 
    2179             :     
    2180           0 :   }
    2181             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2182             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2183             : 
    2184             :   // Do MS-Selection and set up vi/vb. 
    2185             :   // Only this functions needs to know anything about the MS 
    2186           0 :   void SynthesisImager::createVisSet(const Bool writeAccess)
    2187             :   {
    2188           0 :     LogIO os( LogOrigin("SynthesisImager","createVisSet",WHERE) );
    2189             : 
    2190             :     ////////////Temporary revert to vi/vb
    2191           0 :     Block<Int> sort(0);
    2192           0 :     Block<MeasurementSet> msblock(mss4vi_p.nelements());
    2193             :     //for (uInt k=0; k< msblock.nelements(); ++k){
    2194             :     //  msblock[k]=*mss_p[k];
    2195             :     //}
    2196             : 
    2197             :     //vs_p= new VisSet(blockMSSel_p, sort, noChanSel, useModelCol_p);
    2198           0 :     if(!writeAccess){
    2199             : 
    2200           0 :       if(rvi_p) delete rvi_p;
    2201           0 :       rvi_p = NULL;
    2202           0 :       rvi_p=new ROVisibilityIterator(mss4vi_p, sort);
    2203             : 
    2204             :     }
    2205             :     else{
    2206             :       //     if(wvi_p) delete wvi_p;
    2207             :       // wvi_p = NULL;
    2208           0 :       wvi_p=new VisibilityIterator(mss4vi_p, sort);
    2209           0 :       rvi_p=wvi_p;
    2210             :     }
    2211           0 :     Block<Vector<Int> > blockGroup(msblock.nelements());
    2212           0 :     for (uInt k=0; k < msblock.nelements(); ++k){
    2213           0 :         blockGroup[k].resize(blockSpw_p[k].nelements());
    2214           0 :         blockGroup[k].set(1);
    2215             :         //      cerr << "start " << blockStart_p[k] << " nchan " << blockNChan_p[k] << " step " << blockStep_p[k] << " spw "<< blockSpw_p[k] <<endl;
    2216             :     }
    2217             : 
    2218           0 :     rvi_p->selectChannel(blockGroup, blockStart_p, blockNChan_p,
    2219           0 :                           blockStep_p, blockSpw_p);
    2220           0 :     rvi_p->useImagingWeight(VisImagingWeight("natural"));
    2221             :     ////////////////////end of revert vi/vb
    2222           0 :   }// end of createVisSet
    2223             : 
    2224             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2225             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2226             : 
    2227             : 
    2228           0 :   void SynthesisImager::runMajorCycle(const Bool dopsf, 
    2229             :                                       const Bool savemodel)
    2230             :   {
    2231           0 :     LogIO os( LogOrigin("SynthesisImager","runMajorCycle",WHERE) );
    2232             : 
    2233             :     //    cout << "Savemodel : " << savemodel << "   readonly : " << readOnly_p << "   usescratch : " << useScratch_p << endl;
    2234             : 
    2235           0 :     Bool savemodelcolumn = savemodel && !readOnly_p && useScratch_p;
    2236           0 :     Bool savevirtualmodel = savemodel && !readOnly_p && !useScratch_p;
    2237             : 
    2238           0 :     if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
    2239           0 :     if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
    2240             : 
    2241           0 :     SynthesisUtilMethods::getResource("Start Major Cycle");
    2242             : 
    2243           0 :     itsMappers.checkOverlappingModels("blank");
    2244             : 
    2245             :     {
    2246           0 :         VisBufferAutoPtr vb(rvi_p);
    2247           0 :         rvi_p->originChunks();
    2248           0 :         rvi_p->origin();
    2249             : 
    2250           0 :         ProgressMeter pm(1.0, Double(vb->numberCoh()), 
    2251           0 :                          dopsf?"Gridding Weights and PSF":"Major Cycle", "","","",true);
    2252           0 :         Int cohDone=0;
    2253             : 
    2254             : 
    2255           0 :         if(!dopsf)itsMappers.initializeDegrid(*vb);
    2256           0 :         itsMappers.initializeGrid(*vb,dopsf);
    2257             :         //SynthesisUtilMethods::getResource("After initGrid for all mappers");
    2258             : 
    2259           0 :         for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2260             :         {
    2261             : 
    2262           0 :                 for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2263             :                 {
    2264             :                   //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; // No valid rows in this VB
    2265             :                   //              cerr << "nRows "<< vb->nRow() << "   " << max(vb->visCube()) <<  endl;
    2266           0 :                   if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
    2267             :                     {
    2268           0 :                         if(!dopsf) {
    2269           0 :                             { vb->setModelVisCube(Complex(0.0, 0.0)); }
    2270           0 :                                 itsMappers.degrid(*vb, savevirtualmodel );
    2271           0 :                                 if(savemodelcolumn && writeAccess_p )
    2272             :                                   {
    2273             :                                     // cout << "Vi: " << vb->modelVisCube() << endl;
    2274           0 :                                         wvi_p->setVis(vb->modelVisCube(),VisibilityIterator::Model);
    2275             :                                   }
    2276             :                         }
    2277           0 :                         itsMappers.grid(*vb, dopsf, datacol_p);
    2278           0 :                         cohDone += vb->nRow();
    2279           0 :                         pm.update(Double(cohDone));
    2280             :                     }
    2281             :                 }
    2282             :         }
    2283             :         //cerr << "IN SYNTHE_IMA" << endl;
    2284             :         //VisModelData::listModel(rvi_p->getMeasurementSet());
    2285           0 :         SynthesisUtilMethods::getResource("Before finalize for all mappers");
    2286           0 :         if(!dopsf) itsMappers.finalizeDegrid(*vb);
    2287           0 :         itsMappers.finalizeGrid(*vb, dopsf);
    2288             : 
    2289           0 :     }
    2290             : 
    2291           0 :     itsMappers.checkOverlappingModels("restore");
    2292             : 
    2293           0 :     unlockMSs();
    2294             : 
    2295           0 :     SynthesisUtilMethods::getResource("End Major Cycle");
    2296             : 
    2297           0 :   }// end runMajorCycle
    2298             : 
    2299             :  
    2300             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2301             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2302             : 
    2303             :   /// The mapper loop is outside the data iterator loop.
    2304             :   /// This is for cases where the image size is large compared to the RAM and
    2305             :   /// where data I/O is the relatively minor cost.
    2306           0 :   void SynthesisImager::runMajorCycle2(const Bool dopsf, 
    2307             :                                       const Bool savemodel)
    2308             :   {
    2309           0 :     LogIO os( LogOrigin("SynthesisImager","runMajorCycle2",WHERE) );
    2310             : 
    2311             :     //    cout << "Savemodel : " << savemodel << "   readonly : " << readOnly_p << "   usescratch : " << useScratch_p << endl;
    2312             : 
    2313           0 :     Bool savemodelcolumn = savemodel && !readOnly_p && useScratch_p;
    2314           0 :     Bool savevirtualmodel = savemodel && !readOnly_p && !useScratch_p;
    2315             : 
    2316           0 :     if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
    2317           0 :     if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
    2318             : 
    2319           0 :     itsMappers.checkOverlappingModels("blank");
    2320             : 
    2321           0 :     Bool resetModel=False;
    2322           0 :     if( savemodelcolumn && writeAccess_p)
    2323             :       {
    2324           0 :         resetModel=True;
    2325           0 :         os << "Iterating through the model column to reset it to zero" << LogIO::POST;
    2326           0 :         VisBufferAutoPtr vb(rvi_p);
    2327           0 :         rvi_p->originChunks();
    2328           0 :         rvi_p->origin();
    2329             : 
    2330           0 :         ProgressMeter pm(1.0, Double(vb->numberCoh()), 
    2331           0 :                          dopsf?"Seting model column to zero":"pre-Major Cycle", "","","",True);
    2332           0 :         Int cohDone=0;
    2333           0 :         for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2334             :           {
    2335             :             
    2336           0 :             for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2337             :               {
    2338           0 :                 if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
    2339             :                   {
    2340           0 :                     vb->setModelVisCube(Complex(0.0, 0.0));
    2341           0 :                     wvi_p->setVis(vb->modelVisCube(),VisibilityIterator::Model);
    2342             :                   }
    2343           0 :                 cohDone += vb->nRow();
    2344           0 :                 pm.update(Double(cohDone));
    2345             :               }
    2346             :           }
    2347           0 :       }// setting model to zero
    2348             :     
    2349           0 :     for(Int gmap=0;gmap<itsMappers.nMappers();gmap++)
    2350             :        {
    2351           0 :          os << "Running major cycle for chunk : " << gmap << LogIO::POST;
    2352             : 
    2353           0 :          SynthesisUtilMethods::getResource("Start Major Cycle for mapper"+String::toString(gmap));
    2354           0 :         VisBufferAutoPtr vb(rvi_p);
    2355           0 :         rvi_p->originChunks();
    2356           0 :         rvi_p->origin();
    2357             : 
    2358           0 :         ProgressMeter pm(1.0, Double(vb->numberCoh()), 
    2359           0 :                          dopsf?"Gridding Weights and PSF":"Major Cycle", "","","",true);
    2360           0 :         Int cohDone=0;
    2361             : 
    2362           0 :         if(!dopsf){
    2363           0 :           itsMappers.initializeDegrid(*vb, gmap);
    2364             :                   //itsMappers.getMapper(gmap)->initializeDegrid(*vb);
    2365             :         }
    2366           0 :         itsMappers.initializeGrid(*vb,dopsf, gmap);
    2367             :                 //itsMappers.getMapper(gmap)->initializeGrid(*vb,dopsf);
    2368             : 
    2369           0 :         SynthesisUtilMethods::getResource("After initialize for mapper"+String::toString(gmap));
    2370             : 
    2371           0 :         for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2372             :         {
    2373             : 
    2374           0 :                 for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2375             :                 {
    2376             :                   //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; // No valid rows in this VB
    2377             :                   //              cerr << "nRows "<< vb->nRow() << "   " << max(vb->visCube()) <<  endl;
    2378           0 :                   if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS)
    2379             :                     {
    2380           0 :                         if(!dopsf) {
    2381           0 :                           if(resetModel==False) {   vb->setModelVisCube(Complex(0.0, 0.0)); }
    2382           0 :                           itsMappers.degrid(*vb, savevirtualmodel, gmap );
    2383             :                           //itsMappers.getMapper(gmap)->degrid(*vb); //, savevirtualmodel );
    2384           0 :                                 if(savemodelcolumn && writeAccess_p )
    2385           0 :                                         wvi_p->setVis(vb->modelVisCube(),VisibilityIterator::Model);
    2386             :                         }
    2387           0 :                         itsMappers.grid(*vb, dopsf, datacol_p, gmap);
    2388             :                         //itsMappers.getMapper(gmap)->grid(*vb, dopsf, datacol_p);
    2389           0 :                         cohDone += vb->nRow();
    2390           0 :                         pm.update(Double(cohDone));
    2391             :                     }
    2392             :                 }
    2393             :         }
    2394             :         //cerr << "IN SYNTHE_IMA" << endl;
    2395             :         //VisModelData::listModel(rvi_p->getMeasurementSet());
    2396             : 
    2397           0 :         SynthesisUtilMethods::getResource("Before finalize for mapper"+String::toString(gmap));
    2398             : 
    2399           0 :         if(!dopsf) 
    2400             :           {
    2401           0 :             itsMappers.finalizeDegrid(*vb,gmap);
    2402             :             //              auto back = itsMappers.getMapper(gmap)->imageStore()->forwardGrid();        
    2403             :             //              back->tempClose();
    2404             :           }
    2405           0 :         itsMappers.finalizeGrid(*vb, dopsf,gmap);
    2406             : 
    2407             :         //itsMappers.getMapper(gmap)->imageStore()->releaseLocks();        
    2408           0 :         itsMappers.getMapper(gmap)->imageStore()->releaseComplexGrids();        
    2409             : 
    2410             : 
    2411             :         //        auto back = itsMappers.getMapper(gmap)->imageStore()->backwardGrid();        
    2412             :         //      back->tempClose();
    2413             : 
    2414           0 :         SynthesisUtilMethods::getResource("End Major Cycle for mapper"+String::toString(gmap));
    2415           0 :        }// end of mapper loop
    2416             : 
    2417           0 :     itsMappers.checkOverlappingModels("restore");
    2418             : 
    2419           0 :     unlockMSs();
    2420             : 
    2421           0 :     SynthesisUtilMethods::getResource("End Major Cycle");
    2422             : 
    2423           0 :   }// end runMajorCycle2
    2424             : 
    2425             : 
    2426             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2427           0 :   void SynthesisImager::predictModel(){
    2428           0 :     LogIO os( LogOrigin("SynthesisImager","predictModel ",WHERE) );
    2429             : 
    2430           0 :     os << "---------------------------------------------------- Predict Model ---------------------------------------------" << LogIO::POST;
    2431             :     
    2432           0 :     Bool savemodelcolumn = !readOnly_p && useScratch_p;
    2433           0 :     Bool savevirtualmodel = !readOnly_p && !useScratch_p;
    2434             : 
    2435           0 :     if( savemodelcolumn ) os << "Saving model column" << LogIO::POST;
    2436           0 :     if( savevirtualmodel ) os << "Saving virtual model" << LogIO::POST;
    2437             : 
    2438           0 :     itsMappers.checkOverlappingModels("blank");
    2439             : 
    2440             : 
    2441             :     {
    2442           0 :       VisBufferAutoPtr vb(rvi_p);
    2443           0 :       rvi_p->originChunks();
    2444           0 :       rvi_p->origin();
    2445             : 
    2446           0 :       ProgressMeter pm(1.0, Double(vb->numberCoh()), 
    2447           0 :                        "Predict Model", "","","",true);
    2448           0 :       Int cohDone=0;
    2449             : 
    2450           0 :       itsMappers.initializeDegrid(*vb);
    2451           0 :       for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2452             :         {
    2453             :           
    2454           0 :           for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2455             :             {
    2456             :               //if (SynthesisUtilMethods::validate(*vb)==SynthesisUtilMethods::NOVALIDROWS) break; //No valid rows in this MS
    2457             :               //if !usescratch ...just save
    2458           0 :               vb->setModelVisCube(Complex(0.0, 0.0));
    2459           0 :               itsMappers.degrid(*vb, savevirtualmodel);
    2460           0 :               if(savemodelcolumn && writeAccess_p )
    2461           0 :                 wvi_p->setVis(vb->modelVisCube(),VisibilityIterator::Model);
    2462             : 
    2463             :               //              cout << "nRows "<< vb->nRow() << "   " << max(vb->modelVisCube()) <<  endl;
    2464           0 :               cohDone += vb->nRow();
    2465           0 :               pm.update(Double(cohDone));
    2466             : 
    2467             :             }
    2468             :         }
    2469           0 :       itsMappers.finalizeDegrid(*vb);
    2470           0 :     }
    2471             : 
    2472           0 :     itsMappers.checkOverlappingModels("restore");
    2473           0 :     unlockMSs();
    2474             :    
    2475           0 :   }// end of predictModel
    2476             : 
    2477             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2478           0 :   void SynthesisImager::makeSdImage(Bool dopsf)
    2479             :   {
    2480           0 :     LogIO os( LogOrigin("SynthesisImager","makeSdImage",WHERE) );
    2481             : 
    2482             : //    Bool dopsf=false;
    2483           0 :     if(datacol_p==FTMachine::PSF) dopsf=true;
    2484             : 
    2485             :     {
    2486           0 :         VisBufferAutoPtr vb(rvi_p);
    2487           0 :         rvi_p->originChunks();
    2488           0 :         rvi_p->origin();
    2489             : 
    2490           0 :         ProgressMeter pm(1.0, Double(vb->numberCoh()), 
    2491           0 :                          String(datacol_p), "","","",true);
    2492           0 :         Int cohDone=0;
    2493             : 
    2494           0 :         itsMappers.initializeGrid(*vb,dopsf);
    2495           0 :         for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2496             :         {
    2497             : 
    2498           0 :                 for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2499             :                 {
    2500           0 :                         itsMappers.grid(*vb, dopsf, datacol_p);
    2501           0 :                         cohDone += vb->nRow();
    2502           0 :                         pm.update(Double(cohDone));
    2503             :                 }
    2504             :         }
    2505           0 :         itsMappers.finalizeGrid(*vb, dopsf);
    2506             : 
    2507           0 :     }
    2508             : 
    2509           0 :     unlockMSs();
    2510             : 
    2511           0 :   }// end makeSdImage
    2512             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2513             : 
    2514           0 :   void SynthesisImager::makeImage(String type, const String& imagename, const String& complexImage, const Int whichModel)
    2515             :   {
    2516           0 :     LogIO os( LogOrigin("SynthesisImager","makeImage",WHERE) );
    2517             : 
    2518             :     
    2519           0 :     FTMachine::Type seType(FTMachine::OBSERVED);
    2520           0 :     if(type=="observed") {
    2521           0 :       seType=FTMachine::OBSERVED;
    2522             :       os << LogIO::NORMAL // Loglevel INFO
    2523             :          << "Making dirty image from " << type << " data "
    2524           0 :          << LogIO::POST;
    2525             :     }
    2526           0 :     else if (type=="model") {
    2527           0 :       seType=FTMachine::MODEL;
    2528             :       os << LogIO::NORMAL // Loglevel INFO
    2529             :          << "Making dirty image from " << type << " data "
    2530           0 :          << LogIO::POST;
    2531             :     }
    2532           0 :     else if (type=="corrected") {
    2533           0 :       seType=FTMachine::CORRECTED;
    2534             :       os << LogIO::NORMAL // Loglevel INFO
    2535             :          << "Making dirty image from " << type << " data "
    2536           0 :          << LogIO::POST;
    2537             :     }
    2538           0 :     else if (type=="psf") {
    2539           0 :       seType=FTMachine::PSF;
    2540             :       os << "Making point spread function "
    2541           0 :          << LogIO::POST;
    2542             :     }
    2543           0 :     else if (type=="residual") {
    2544           0 :       seType=FTMachine::RESIDUAL;
    2545             :       os << LogIO::NORMAL // Loglevel INFO
    2546             :          << "Making dirty image from " << type << " data "
    2547           0 :          << LogIO::POST;
    2548             :     }
    2549           0 :     else if (type=="singledish-observed") {
    2550           0 :       seType=FTMachine::OBSERVED;
    2551             :       os << LogIO::NORMAL 
    2552           0 :          << "Making single dish image from observed data" << LogIO::POST;
    2553             :     }
    2554           0 :     else if (type=="singledish") {
    2555           0 :       seType=FTMachine::CORRECTED;
    2556             :       os << LogIO::NORMAL 
    2557           0 :          << "Making single dish image from corrected data" << LogIO::POST;
    2558             :     }
    2559           0 :     else if (type=="coverage") {
    2560           0 :       seType=FTMachine::COVERAGE;
    2561             :       os << LogIO::NORMAL 
    2562             :          << "Making single dish coverage function "
    2563           0 :          << LogIO::POST;
    2564             :     }
    2565           0 :     else if (type=="holography") {
    2566           0 :       seType=FTMachine::CORRECTED;
    2567             :       os << LogIO::NORMAL
    2568             :          << "Making complex holographic image from corrected data "
    2569           0 :          << LogIO::POST;
    2570             :     }
    2571           0 :     else if (type=="holography-observed") {
    2572           0 :       seType=FTMachine::OBSERVED;
    2573             :       os << LogIO::NORMAL 
    2574             :          << "Making complex holographic image from observed data "
    2575           0 :          << LogIO::POST;
    2576             :     }
    2577             : 
    2578             : 
    2579           0 :     String imageName=(itsMappers.imageStore(whichModel))->getName();
    2580           0 :     String cImageName(complexImage);
    2581           0 :     Bool keepComplexImage=(complexImage!="")||(type.contains("holography"));
    2582           0 :     if(complexImage=="") {
    2583           0 :       cImageName=imageName+".compleximage";
    2584             :     }
    2585           0 :     PagedImage<Float> theImage((itsMappers.imageStore(whichModel))->getShape(), (itsMappers.imageStore(whichModel))->getCSys(), imagename);
    2586           0 :     PagedImage<Complex> cImageImage(theImage.shape(),
    2587             :                                     theImage.coordinates(),
    2588           0 :                                     cImageName);
    2589           0 :     if(!keepComplexImage)
    2590           0 :       cImageImage.table().markForDelete();
    2591             : 
    2592             : 
    2593           0 :     Matrix<Float> weight;
    2594           0 :     (itsMappers.getFTM(whichModel))->makeImage(seType, *rvi_p, cImageImage, weight);
    2595             :    
    2596           0 :  if(seType==FTMachine::PSF){
    2597           0 :        StokesImageUtil::ToStokesPSF(theImage, cImageImage);
    2598           0 :        StokesImageUtil::normalizePSF(theImage);
    2599             :     }
    2600             :     else{
    2601           0 :       StokesImageUtil::To(theImage, cImageImage);
    2602             :     }
    2603             :     
    2604             : 
    2605           0 :     unlockMSs();
    2606             : 
    2607           0 :   }// end makeImage
    2608             : 
    2609             : 
    2610             : 
    2611             : 
    2612             :  
    2613             : 
    2614             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2615             :   // Method to run the AWProjectFT machine to seperate the CFCache
    2616             :   // construction from imaging.  This is done by splitting the
    2617             :   // operation in two steps: (1) run the FTM in "dry" mode to create a
    2618             :   // "blank" CFCache, and (2) re-load the "blank" CFCache and "fill"
    2619             :   // it.
    2620             :   //
    2621             :   // If someone can get me (SB) out of the horrible statc_casts in the
    2622             :   // code below, I will be most grateful (we are out of it! :-)).
    2623             :   //
    2624           0 :   void SynthesisImager::dryGridding(const Vector<String>& cfList)
    2625             :   {
    2626           0 :     LogIO os( LogOrigin("SynthesisImager","dryGridding",WHERE) );
    2627           0 :     Int cohDone=0, whichFTM=0;
    2628             :     (void)cfList;
    2629             :     // If not an AWProject-class FTM, make this call a NoOp.  Might be
    2630             :     // useful to extend it to other projection FTMs -- but later.
    2631           0 :     String ftmName = ((*(itsMappers.getFTM(whichFTM)))).name();
    2632             : 
    2633           0 :     if (!((itsMappers.getFTM(whichFTM,true))->isUsingCFCache())) return;
    2634             : 
    2635           0 :     os << "---------------------------------------------------- Dry Gridding ---------------------------------------------" << LogIO::POST;
    2636             : 
    2637             :     //
    2638             :     // Go through the entire MS in "dry" mode to set up a "blank"
    2639             :     // CFCache.  This is done by setting the AWPWBFT in dryrun mode
    2640             :     // and gridding.  The process of gridding emits CFCache, which
    2641             :     // will be "blank" in a dry run.
    2642             :     {
    2643           0 :       VisBufferAutoPtr vb(rvi_p);
    2644           0 :       rvi_p->originChunks();
    2645           0 :       rvi_p->origin();
    2646             : 
    2647           0 :       ProgressMeter pm(1.0, Double(vb->numberCoh()), "dryGridding", "","","",true);
    2648             : 
    2649           0 :       itsMappers.initializeGrid(*vb);
    2650             :     
    2651             :       // Set the gridder (iFTM) to run in dry-gridding mode
    2652           0 :       (itsMappers.getFTM(whichFTM,true))->setDryRun(true);
    2653             : 
    2654           0 :       Bool aTermIsOff=False;
    2655             :       {
    2656           0 :         CountedPtr<FTMachine> ftm=itsMappers.getFTM(whichFTM,True);
    2657           0 :         CountedPtr<ConvolutionFunction> cf=ftm->getAWConvFunc();
    2658             :         //      Bool aTermIsOff =         (((static_cast<AWConvFunc &> (*cf)).getTerm("ATerm")))->isNoOp();
    2659           0 :         aTermIsOff = cf->getTerm("ATerm")->isNoOp();
    2660           0 :       }
    2661             : 
    2662             :       os << "Making a \"blank\" CFCache"
    2663             :          << (aTermIsOff?" (without the A-Term)":"")
    2664           0 :          << LogIO::WARN << LogIO::POST;
    2665             :       
    2666             :       // Step through the MS.  This triggers the logic in the Gridder
    2667             :       // to determine all the CFs that will be required.  These empty
    2668             :       // CFs are written to the CFCache which can then be filled via
    2669             :       // a call to fillCFCache().
    2670           0 :       for (rvi_p->originChunks(); rvi_p->moreChunks();rvi_p->nextChunk())
    2671             :         {
    2672           0 :           for (rvi_p->origin(); rvi_p->more(); (*rvi_p)++)
    2673             :             {
    2674           0 :               if (SynthesisUtilMethods::validate(*vb)!=SynthesisUtilMethods::NOVALIDROWS) 
    2675             :                 {
    2676           0 :                   itsMappers.grid(*vb, true, FTMachine::OBSERVED, whichFTM);
    2677           0 :                   cohDone += vb->nRow();
    2678           0 :                   pm.update(Double(cohDone));
    2679             :                   // If there is no term that depends on time, don't iterate over the entire data base
    2680           0 :                   if (aTermIsOff) break;
    2681             :                 }
    2682             :             }
    2683             :         }
    2684           0 :     }
    2685           0 :     if (cohDone == 0) os << "No valid rows found in dryGridding." << LogIO::EXCEPTION << LogIO::POST;
    2686             :     // Unset the dry-gridding mode.
    2687           0 :     (itsMappers.getFTM(whichFTM,true))->setDryRun(false);
    2688             : 
    2689             :     //itsMappers.checkOverlappingModels("restore");
    2690           0 :     unlockMSs();
    2691             :     //fillCFCache(cfList);
    2692           0 :   }
    2693             :   //
    2694             :   // Re-load the CFCache from the disk using the supplied list of CFs
    2695             :   // (as cfList).  Then extract the ConvFunc object (which was setup
    2696             :   // in the FTM) and call it's makeConvFunction2() to fill the CF.
    2697             :   // Finally, unset the dry-run mode of the FTM.
    2698             :   //
    2699           0 :   void SynthesisImager::fillCFCache(const Vector<String>& cfList,
    2700             :                                     const String& ftmName,
    2701             :                                     const String& cfcPath,
    2702             :                                     const Bool& psTermOn,
    2703             :                                     const Bool& aTermOn,
    2704             :                                     const Bool& conjBeams)
    2705             :     {
    2706           0 :       LogIO os( LogOrigin("SynthesisImager","fillCFCache",WHERE) );
    2707             :       // If not an AWProject-class FTM, make this call a NoOp.  Might be
    2708             :       // useful to extend it to other projection FTMs -- but later.
    2709             :       // String ftmName = ((*(itsMappers.getFTM(whichFTM)))).name();
    2710             : 
    2711           0 :       if (!ftmName.contains("awproject") and
    2712           0 :           !ftmName.contains("multitermftnew"))  return;
    2713             :       
    2714           0 :       os << "---------------------------------------------------- fillCFCache ---------------------------------------------" << LogIO::POST;
    2715             : 
    2716             :       //String cfcPath = itsMappers.getFTM(whichFTM)->getCacheDir();
    2717             :       //String imageNamePrefix=itsMappers.getFTM(whichFTM)->getCFCache()->getWtImagePrefix();
    2718             : 
    2719             :       //cerr << "Path = " << path << endl;
    2720             : 
    2721             :       // CountedPtr<AWProjectWBFTNew> tmpFT = new AWProjectWBFTNew(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM))));
    2722             : 
    2723             : 
    2724           0 :       Float dPA=360.0,selectedPA=2*360.0;
    2725           0 :       if (cfList.nelements() > 0)
    2726             :       {
    2727           0 :           CountedPtr<CFCache> cfCacheObj = new CFCache();
    2728             :           //Vector<String> wtCFList; wtCFList.resize(cfList.nelements());
    2729             :           //for (Int i=0; i<wtCFList.nelements(); i++) wtCFList[i] = "WT"+cfList[i];
    2730             :           //Directory dir(path);
    2731           0 :           Vector<String> cfList_p=cfList;//dir.find(Regex(Regex::fromPattern("CFS*")));
    2732           0 :           Vector<String> wtCFList_p;
    2733           0 :           wtCFList_p.resize(cfList_p.nelements());
    2734           0 :           for (Int i=0; i<(Int)wtCFList_p.nelements(); i++) wtCFList_p[i]="WT"+cfList_p[i];
    2735             : 
    2736             :           //cerr << cfList_p << endl;
    2737           0 :           cfCacheObj->setCacheDir(cfcPath.data());
    2738             : 
    2739           0 :           os << "Re-loading the \"blank\" CFCache for filling" << LogIO::WARN << LogIO::POST;
    2740             : 
    2741           0 :           cfCacheObj->initCacheFromList2(cfcPath, cfList_p, wtCFList_p,
    2742             :                                          selectedPA, dPA,1);
    2743             :           // tmpFT->setCFCache(cfCacheObj);
    2744           0 :           Vector<Double> uvScale, uvOffset;
    2745           0 :           Matrix<Double> vbFreqSelection;
    2746           0 :           CountedPtr<CFStore2> cfs2 = CountedPtr<CFStore2>(&cfCacheObj->memCache2_p[0],false);//new CFStore2;
    2747           0 :           CountedPtr<CFStore2> cfwts2 =  CountedPtr<CFStore2>(&cfCacheObj->memCacheWt2_p[0],false);//new CFStore2;
    2748             : 
    2749             :           //
    2750             :           // Get whichFTM from itsMappers (SIMapperCollection) and
    2751             :           // cast it as AWProjectWBFTNew.  Then get the ConvFunc from
    2752             :           // the FTM and cast it as AWConvFunc.  Finally call
    2753             :           // AWConvFunc::makeConvFunction2().
    2754             :           //
    2755             :           // (static_cast<AWConvFunc &> 
    2756             :           //  (*(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM)))).getAWConvFunc())
    2757             :           //  ).makeConvFunction2(String(path), uvScale, uvOffset, vbFreqSelection,
    2758             :           //                   *cfs2, *cfwts2);
    2759             : 
    2760             :           // This is a global methond in AWConvFunc.  Does not require
    2761             :           // FTM to be constructed (which can be expensive in terms of
    2762             :           // memory footprint).
    2763           0 :           AWConvFunc::makeConvFunction2(String(cfcPath), uvScale, uvOffset, vbFreqSelection,
    2764           0 :                                         *cfs2, *cfwts2, psTermOn, aTermOn, conjBeams);
    2765           0 :         }
    2766             :       //cerr << "Mem used = " << itsMappers.getFTM(whichFTM)->getCFCache()->memCache2_p[0].memUsage() << endl;
    2767             :       //(static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM)))).getCFCache()->initCache2();
    2768           0 :     }
    2769             : 
    2770             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2771           0 :   void SynthesisImager::reloadCFCache()
    2772             :   {
    2773           0 :       LogIO os( LogOrigin("SynthesisImager","reloadCFCache",WHERE) );
    2774           0 :       Int whichFTM=0;
    2775           0 :       String ftmName = ((*(itsMappers.getFTM(whichFTM)))).name();
    2776           0 :       if (!ftmName.contains("AWProject")) return;
    2777             : 
    2778           0 :       os << "-------------------------------------------- reloadCFCache ---------------------------------------------" << LogIO::POST;
    2779           0 :       String path = itsMappers.getFTM(whichFTM)->getCacheDir();
    2780           0 :       String imageNamePrefix=itsMappers.getFTM(whichFTM)->getCFCache()->getWtImagePrefix();
    2781             : 
    2782           0 :       CountedPtr<CFCache> cfCacheObj = new CFCache();
    2783           0 :       cfCacheObj->setCacheDir(path.data());
    2784           0 :       cfCacheObj->setWtImagePrefix(imageNamePrefix.c_str());
    2785           0 :       cfCacheObj->initCache2();
    2786             :       
    2787             :       // This assumes the itsMappers is always SIMapperCollection.
    2788           0 :       for (whichFTM = 0; whichFTM < itsMappers.nMappers(); whichFTM++)
    2789             :         {
    2790           0 :           (static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM)))).setCFCache(cfCacheObj,true); // Setup iFTM
    2791           0 :           (static_cast<AWProjectWBFTNew &> (*(itsMappers.getFTM(whichFTM,false)))).setCFCache(cfCacheObj,true); // Set FTM
    2792             :         }
    2793           0 :   }
    2794             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2795             : 
    2796             :   //Utility function to properly convert Double to String.
    2797             :   //With C++11 we can probably use STL to_string() function instead...
    2798           0 :   String SynthesisImager::doubleToString(const Double& df) {
    2799           0 :     std::ostringstream ss;
    2800           0 :     ss.precision(std::numeric_limits<double>::digits10+2);
    2801           0 :     ss << df;
    2802             :     //return ss.str();
    2803           0 :     return to_string(df);
    2804           0 :   }
    2805             : 
    2806             : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2807             : 
    2808           0 :   Bool SynthesisImager::makePB()
    2809             :   {
    2810           0 :       LogIO os( LogOrigin("SynthesisImager","makePB",WHERE) );
    2811             : 
    2812           0 :       if( itsMakeVP==False )
    2813             :         {
    2814           0 :           os << LogIO::NORMAL1 << "Not making .pb by direct evaluation. The gridder will make a .weight and a .pb will be computed from it." << LogIO::POST;
    2815             :           // Check that the .weight exists.. ?
    2816             : 
    2817           0 :           return False;
    2818             :         }
    2819             :       else
    2820             :         {
    2821           0 :           Bool doDefaultVP = itsVpTable.length()>0 ? False : True;
    2822             : 
    2823           0 :           CoordinateSystem coordsys=itsMappers.imageStore(0)->getCSys();
    2824           0 :           String telescope=coordsys.obsInfo().telescope();
    2825             :           
    2826           0 :           if (doDefaultVP) {
    2827             :             
    2828           0 :             MSAntennaColumns ac(mss4vi_p[0].antenna());
    2829           0 :             Double dishDiam=ac.dishDiameter()(0);
    2830           0 :             if(!allEQ(ac.dishDiameter().getColumn(), dishDiam))
    2831             :               os << LogIO::WARN
    2832             :                  << "The MS has multiple antenna diameters ..PB could be wrong "
    2833           0 :                  << LogIO::POST;
    2834           0 :             return makePBImage( telescope, False, dishDiam);
    2835           0 :           }
    2836             :           else{
    2837           0 :             return makePBImage(telescope );     
    2838             :           }
    2839             :           
    2840           0 :         }
    2841             :       return False;
    2842           0 :   }
    2843             :   
    2844          17 :   bool SynthesisImager::makePBImage(const String& telescopeName,
    2845             :                                     Bool useSymmetricBeam, Double diam){
    2846             :     
    2847          34 :     LogIO os(LogOrigin("SynthesisImager", "makePBImage()", WHERE));
    2848             :     
    2849             :     // Check if this metadata info should come from each Mapper or if it's OK to be just the first one.
    2850             :     // Right now it assumes all mappers have the same FREQUENCY settings.
    2851             :     
    2852          17 :   CoordinateSystem imageCoord=itsMappers.imageStore(0)->getCSys();
    2853             : 
    2854          17 :   Int spectralIndex=imageCoord.findCoordinate(Coordinate::SPECTRAL);
    2855             :   SpectralCoordinate
    2856          17 :     spectralCoord=imageCoord.spectralCoordinate(spectralIndex);
    2857          17 :   Vector<String> units(1); units = "Hz";
    2858          17 :   spectralCoord.setWorldAxisUnits(units);       
    2859          17 :   Vector<Double> spectralWorld(1);
    2860          17 :   Vector<Double> spectralPixel(1);
    2861          17 :   spectralPixel(0) = 0;
    2862          17 :   spectralCoord.toWorld(spectralWorld, spectralPixel);  
    2863          17 :   Double freq  = spectralWorld(0);
    2864          17 :   Quantity qFreq( freq, "Hz" );
    2865          17 :   String telName=telescopeName;
    2866          17 :   if(telName=="ALMA" &&  diam < 12.0)
    2867           0 :     telName="ACA";
    2868             :   //cerr << "Telescope Name is " << telName<< endl;
    2869             :   PBMath::CommonPB whichPB;
    2870          17 :   PBMath::enumerateCommonPB(telName, whichPB);  
    2871          17 :   PBMath myPB;
    2872          17 :   if(whichPB!=PBMath::UNKNOWN && whichPB!=PBMath::NONE){
    2873             :     
    2874          17 :     myPB=PBMath(telName, useSymmetricBeam, qFreq);
    2875             :   }
    2876           0 :   else if(diam > 0.0){
    2877           0 :     myPB=PBMath(diam,useSymmetricBeam, qFreq);
    2878             :   }
    2879             :   else{
    2880             :     os << LogIO::WARN << "Telescope " << telName << " is not known\n "
    2881             :        << "Not making the PB  image" 
    2882           0 :        << LogIO::POST;
    2883           0 :     return false; 
    2884             :   }
    2885          17 :   return makePrimaryBeam(myPB );
    2886          17 : }
    2887             : 
    2888           0 :   Bool SynthesisImager::makePBImage(const String telescop){
    2889             : 
    2890             :   /*
    2891             :   ScalarColumn<TableRecord> recCol(vpTable, (String)"pbdescription");
    2892             :   PBMath myPB(recCol(0));
    2893             :   */
    2894           0 :   LogIO os( LogOrigin("SynthesisImager","makePBImage",WHERE) );
    2895             :   
    2896             :   PBMath::CommonPB kpb;
    2897           0 :   Record rec;
    2898           0 :   getVPRecord( rec, kpb, telescop );
    2899             : 
    2900           0 :   Bool ret=False;
    2901           0 :   if(rec.empty())
    2902           0 :     {os << LogIO::WARN << "Not making PB. Cannot use pbcor option later." << LogIO::POST; }
    2903             :   else
    2904             :     {
    2905           0 :       PBMath myPB( rec );
    2906           0 :       ret = makePrimaryBeam(myPB);
    2907           0 :     }
    2908           0 :   return ret;
    2909           0 :   }
    2910             :   
    2911             : 
    2912           0 :   Bool SynthesisImager::makePrimaryBeam(PBMath& pbMath)
    2913             :   {
    2914           0 :     LogIO os( LogOrigin("SynthesisImager","makePrimaryBeam",WHERE) );
    2915             : 
    2916           0 :     os << "Evaluating Primary Beam model onto image grid(s)" << LogIO::POST;
    2917             : 
    2918           0 :     itsMappers.initPB();
    2919             : 
    2920           0 :     VisBuffer vb(*rvi_p);
    2921           0 :     Int fieldCounter=0;
    2922           0 :     Vector<Int> fieldsDone;
    2923             :   
    2924           0 :     for(rvi_p->originChunks(); rvi_p->moreChunks(); rvi_p->nextChunk()){
    2925           0 :       Bool fieldDone=false;
    2926           0 :       for (uInt k=0;  k < fieldsDone.nelements(); ++k){
    2927           0 :         fieldDone=fieldDone || (vb.fieldId()==fieldsDone(k));
    2928             :       }
    2929           0 :       if(!fieldDone){
    2930           0 :         ++fieldCounter;
    2931           0 :         fieldsDone.resize(fieldCounter, true);
    2932           0 :         fieldsDone(fieldCounter-1)=vb.fieldId();
    2933             : 
    2934           0 :         itsMappers.addPB(vb,pbMath);
    2935             : 
    2936             :       }
    2937             :     }
    2938             :  
    2939           0 :     itsMappers.releaseImageLocks();
    2940           0 :     unlockMSs();
    2941             : 
    2942           0 :       return True;
    2943           0 :   }// end makePB
    2944             : 
    2945             :   /////===========
    2946           0 :   void SynthesisImager::setMovingSource(const String& movingSource){
    2947           0 :     movingSource_p=movingSource;
    2948           0 :   }
    2949             :   
    2950           0 :   bool SynthesisImager::isSpectralCube(){
    2951           0 :     bool retval=False;
    2952           0 :     for (Int k=0; k < itsMappers.nMappers(); ++k){
    2953             :       //For some reason imstore sometime returns 0 shape
    2954             :       //trying to test with with psf size breaks parallel = true in some cases...go figure
    2955             :       //if((((itsMappers.imageStore(k))->psf())->shape()[3]) != ((itsMappers.imageStore(k))->getShape()[3])){
    2956             :       //cerr << "shapes " << ((itsMappers.imageStore(k))->psf())->shape() << "   " <<  ((itsMappers.imageStore(k))->getShape()) << endl;
    2957             :       //throw(AipsError("images shape seem insistent "));
    2958           0 :       if((itsMappers.imageStore(k))->getShape()(3) ==0)
    2959           0 :         return True;
    2960             :       //}
    2961           0 :     if((itsMappers.imageStore(k))->getShape()(3) > 1)
    2962           0 :       retval=True;
    2963             :     }
    2964           0 :     return retval;
    2965             : 
    2966             :   }
    2967          17 :   void SynthesisImager::normalizerinfo(const Record& normpars){
    2968          17 :     normpars_p=normpars;
    2969          17 :   }
    2970             : } //# NAMESPACE CASA - END
    2971             : 

Generated by: LCOV version 1.16