LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SynthesisUtilMethods.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1783 2485 71.8 %
Date: 2025-12-19 19:56:21 Functions: 66 83 79.5 %

          Line data    Source code
       1             : //# SynthesisUtilMethods.cc: 
       2             : //# Copyright (C) 2013-2018
       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             : #include <casacore/casa/Logging.h>
      37             : #include <casacore/casa/Logging/LogIO.h>
      38             : #include <casacore/casa/Logging/LogMessage.h>
      39             : #include <casacore/casa/Logging/LogSink.h>
      40             : #include <casacore/casa/Logging/LogMessage.h>
      41             : 
      42             : #include <casacore/casa/OS/DirectoryIterator.h>
      43             : #include <casacore/casa/OS/File.h>
      44             : #include <casacore/casa/OS/Path.h>
      45             : 
      46             : #include <casacore/casa/OS/HostInfo.h>
      47             : 
      48             : #include <casacore/images/Images/TempImage.h>
      49             : #include <casacore/images/Images/SubImage.h>
      50             : #include <casacore/images/Regions/ImageRegion.h>
      51             : #include <imageanalysis/Utilities/SpectralImageUtil.h>
      52             : #include <casacore/measures/Measures/MeasTable.h>
      53             : #include <casacore/measures/Measures/MRadialVelocity.h>
      54             : #include <casacore/ms/MSSel/MSSelection.h>
      55             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      56             : #include <casacore/ms/MeasurementSets/MSDopplerUtil.h>
      57             : #include <casacore/tables/Tables/Table.h>
      58             : #include <synthesis/ImagerObjects/SynthesisUtilMethods.h>
      59             : #include <synthesis/TransformMachines2/Utils.h>
      60             : 
      61             : #include <mstransform/MSTransform/MSTransformRegridder.h>
      62             : #include <msvis/MSVis/MSUtil.h>
      63             : #include <msvis/MSVis/VisibilityIteratorImpl2.h>
      64             : #include <msvis/MSVis/VisBufferUtil.h>
      65             : #include <sys/types.h>
      66             : #include <unistd.h>
      67             : #include <limits>
      68             : #include <tuple>
      69             : #include <sys/time.h>
      70             : #include<sys/resource.h>
      71             : 
      72             : #include <synthesis/ImagerObjects/SIImageStore.h>
      73             : #include <synthesis/ImagerObjects/SIImageStoreMultiTerm.h>
      74             : 
      75             : using namespace std;
      76             : 
      77             : using namespace casacore;
      78             : namespace casa { //# NAMESPACE CASA - BEGIN
      79             : 
      80             :   casacore::String SynthesisUtilMethods::g_hostname;
      81             :   casacore::String SynthesisUtilMethods::g_startTimestamp;
      82             :   const casacore::String SynthesisUtilMethods::g_enableOptMemProfile =
      83             :       "synthesis.imager.memprofile.enable";
      84             : 
      85        1446 :   SynthesisUtilMethods::SynthesisUtilMethods()
      86             :   {
      87             :     
      88        1446 :   }
      89             :   
      90        1446 :   SynthesisUtilMethods::~SynthesisUtilMethods() 
      91             :   {
      92        1446 :   }
      93             :   
      94           0 :   Int SynthesisUtilMethods::validate(const VisBuffer& vb)
      95             :   {
      96           0 :     Int N=vb.nRow(),M=-1;
      97           0 :     for(Int i=0;i<N;i++)
      98             :       {
      99           0 :         if ((!vb.flagRow()(i)) && (vb.antenna1()(i) != vb.antenna2()(i)))
     100           0 :           {M++;break;}
     101             :       }
     102           0 :     return M;
     103             :   }
     104             : 
     105      514533 :   Int SynthesisUtilMethods::validate(const vi::VisBuffer2& vb)
     106             :   {
     107      514533 :     Int N=vb.nRows(),M=-1;
     108     2269669 :     for(Int i=0;i<N;i++)
     109             :       {
     110     2269669 :         if ((!vb.flagRow()(i)) && (vb.antenna1()(i) != vb.antenna2()(i)))
     111      514533 :           {M++;break;}
     112             :       }
     113      514533 :     return M;
     114             :   }
     115             :   // Get the next largest even composite of 2,3,5.
     116             :   // This is to ensure a 'good' image size for FFTW.
     117             :   // Translated from gcwrap/scripts/cleanhelper.py : getOptimumSize
     118        3698 :   Int SynthesisUtilMethods::getOptimumSize(const Int npix)
     119             :   {
     120        3698 :     Int n=npix;
     121             : 
     122        3698 :     if( n%2 !=0 ){ n+= 1; }
     123             : 
     124        3698 :     Vector<uInt> fac = primeFactors(n, false);
     125             :     Int val, newlarge;
     126       24001 :     for( uInt k=0; k< fac.nelements(); k++ )
     127             :       {
     128       20303 :         if( fac[k]>5 )
     129             :           {
     130         147 :             val = fac[k];
     131         301 :             while( max( primeFactors(val) ) > 5 ){ val+=1;}
     132         147 :             fac[k] = val;
     133             :           }
     134             :       }
     135        3698 :     newlarge=product(fac);
     136        3955 :     for( Int k=n; k<newlarge; k+=2 )
     137             :       {
     138         272 :         if( max( primeFactors(k) ) < 6 ) {return k;}
     139             :       }
     140        3683 :     return newlarge;
     141        3698 :   }
     142             : 
     143             :   // Return the prime factors of the given number
     144        4271 :   Vector<uInt> SynthesisUtilMethods::primeFactors(uInt n, Bool /*douniq*/)
     145             :   {
     146        4271 :     Vector<uInt> factors;
     147             :     
     148        4271 :     Int lastresult = n;
     149        4271 :     Int sqlast = int(sqrt(n))+1;
     150             :    
     151        4271 :     if(n==1){ factors.resize(1);factors[0]=1;return factors;}
     152        4271 :     Int c=2;
     153             :     while(1)
     154             :       {
     155       25980 :         if( lastresult == 1 || c > sqlast ) { break; }
     156       21709 :         sqlast = (Int)(sqrt(lastresult))+1;
     157             :         while(1)
     158             :           {
     159       31351 :             if( c>sqlast){ c=lastresult; break; }
     160       28082 :             if( lastresult % c == 0 ) { break; }
     161        9642 :             c += 1;
     162             :           }
     163       21709 :         factors.resize( factors.nelements()+1, true );
     164       21709 :         factors[ factors.nelements()-1 ] = c;
     165       21709 :         lastresult /= c;
     166             :       }
     167        4271 :     if( factors.nelements()==0 ) { factors.resize(1);factors[0]=n; }
     168             : 
     169             :     //if( douniq ) { factors = unique(factors); }
     170             : 
     171             :     /*    
     172             :           /// The Sort::unique isn't working as called below. Results appear to be the
     173             :           /// same as with the cleanhelper python code, so leaving as is for not. CAS-7889
     174             :     if( douniq )
     175             :       {
     176             :         cout << "Test unique fn on : " << factors << endl;
     177             :         Sort srt;
     178             :         Vector<uInt> unvec=factors; uInt nrec;
     179             :         srt.unique(unvec,nrec);
     180             :         cout << " Unique : " << unvec << " nr : " << nrec << endl;
     181             :       }
     182             :     */
     183             : 
     184        4271 :     return factors;
     185           0 :   }
     186             : 
     187             : 
     188          35 :   Bool SynthesisUtilMethods::fitPsfBeam(const String& imagename, const Int nterms, const Float psfcutoff)
     189             :   {
     190          70 :     LogIO os(LogOrigin("SynthesisUtilMethods", "fitPsfBeam"));
     191             : 
     192          35 :     if (psfcutoff >=1.0 || psfcutoff<=0.0)
     193             :       {
     194           0 :         os << "psfcutoff must be >0 and <1" << LogIO::WARN;
     195           0 :         return false;
     196             :       }
     197             : 
     198          35 :     std::shared_ptr<SIImageStore> imstore;
     199          35 :     if( nterms>1 )
     200          10 :       { imstore = std::shared_ptr<SIImageStore>(new SIImageStoreMultiTerm( imagename, nterms, true, true ));   }
     201             :     else
     202          25 :       { imstore = std::shared_ptr<SIImageStore>(new SIImageStore( imagename, true, true ));   }
     203             :   
     204             : 
     205          35 :     os << "Fitting PSF beam for Imagestore : " << imstore->getName() << LogIO::POST;
     206             : 
     207          35 :     imstore->makeImageBeamSet(psfcutoff, true);
     208             : 
     209          35 :     imstore->printBeamSet();
     210             : 
     211          35 :     imstore->releaseLocks();
     212             :     
     213          35 :     return true;
     214          35 :   }
     215             : 
     216             : 
     217             : 
     218             :   // Evaluate a polynomial from Taylor coefficients and expand to a Cube.
     219             :   // Since this funcion is primarily for use with mtmfs_via_cube, this step applies only to 
     220             :   // the multiterm.model.ttx images and the cube.model image cube.  
     221          18 :   Bool SynthesisUtilMethods::taylorCoeffsToCube(const String& cubename,const String& mtname,  const Int nterms, const String& reffreq)
     222             :   {
     223          36 :     LogIO os(LogOrigin("SynthesisUtilMethods", "taylorCoeffsToCube"));
     224             : 
     225             :     // Set up imstores
     226          18 :     CountedPtr<SIImageStore> cube_imstore;
     227          18 :     cube_imstore = CountedPtr<SIImageStore>(new SIImageStore( cubename, true, true ));  
     228             : 
     229          18 :     CountedPtr<SIImageStoreMultiTerm> mt_imstore;
     230          18 :     mt_imstore = CountedPtr<SIImageStoreMultiTerm>(new SIImageStoreMultiTerm( mtname, nterms, true, true )); 
     231             : 
     232             :     // Check that .model exists. 
     233             :     try{
     234          18 :       cube_imstore->model();
     235          54 :       for(Int i=0;i<nterms;i++)
     236          36 :         mt_imstore->model(i);
     237             :         }
     238           0 :     catch(AipsError &x)
     239             :       {
     240           0 :         throw( AipsError("Error in reading image : " + x.getMesg() + "\nModel images must exist on disk." ));
     241           0 :       }
     242             :     
     243             :     // Get/check shapes
     244          18 :     IPosition cube_shp( cube_imstore->model()->shape() );
     245          18 :     IPosition mt_shp( mt_imstore->model(0)->shape() );
     246          18 :     if( cube_shp[0] != mt_shp[0] || cube_shp[1] != mt_shp[1] ||cube_shp[2] != mt_shp[2] ){
     247           0 :       throw( AipsError("The Cube and Multi-Term images should have the same nx, ny and npol"));
     248             :     }
     249             : 
     250             :     // Read reference frequency
     251          18 :     Quantity reffreq_qa;
     252          18 :     Quantity::read( reffreq_qa, reffreq );
     253          18 :     Double refval = reffreq_qa.getValue("Hz");
     254             :     
     255             :     //cout << "ref freq : " << refval << endl;
     256             : 
     257             :     //Get the frequency list for the cube
     258          18 :     CoordinateSystem csys ( cube_imstore->getCSys() );
     259          18 :     Vector<Double> freqlist( cube_shp[3] );
     260             : 
     261          72 :     for(uInt i=0; i<csys.nCoordinates(); i++)
     262             :     {
     263          54 :       if( csys.type(i) == Coordinate::SPECTRAL )
     264             :         {
     265          18 :           SpectralCoordinate speccoord(csys.spectralCoordinate(i));
     266             : 
     267         108 :           for(Int ch=0;ch<cube_shp[3];ch++)
     268             :             {
     269             :               Double freq;
     270          90 :               Bool ret = speccoord.toWorld( freq, ch );
     271          90 :               if(ret==False) throw(AipsError("Cannot read channel frequency"));
     272          90 :               freqlist[ch] = freq;
     273             :               
     274             :               //cout << "freq " << ch << "  is " << freq << endl;
     275             :             }
     276             : 
     277          18 :         }
     278             :     }
     279             : 
     280             : 
     281             :     // Reset the Cube values to zero. 
     282             :     //cube_imstore->model()->set(0.0);
     283             : 
     284             :     //For each pol, do the Taylor-to-Cube calculation.    
     285          36 :     for(Int pol=0; pol<cube_shp[2]; pol++)
     286             :       {
     287          18 :         Vector< CountedPtr <ImageInterface<Float> > > mt_subims(nterms);
     288          54 :         for(Int i=0;i<nterms;i++)
     289             :           {
     290          72 :             mt_subims[i] = mt_imstore->makeSubImage(0,1, 
     291          36 :                                                                        0, cube_shp[3],
     292          36 :                                                                        pol, cube_shp[2], 
     293         108 :                                                                        *mt_imstore->model(i) );
     294             :           }
     295             : 
     296         108 :         for(Int chan=0; chan<cube_shp[3]; chan++)
     297             :           {
     298         180 :             CountedPtr<ImageInterface<Float> > cube_subim=cube_imstore->makeSubImage(0,1, 
     299          90 :                                                                        chan, cube_shp[3],
     300          90 :                                                                        pol, cube_shp[2], 
     301         180 :                                                                        *cube_imstore->model() );
     302             :         
     303          90 :             Double wt = (freqlist[chan] - refval) / refval;
     304             : 
     305          90 :             cube_subim->set(0.0);
     306         270 :             for(Int tt=0;tt<nterms;tt++)
     307             :               {
     308         180 :                 Double fac = pow(wt,tt);
     309         360 :                 LatticeExpr<Float> oneterm = LatticeExpr<Float>( *cube_subim + (fac) * (*mt_subims[tt])) ;
     310         180 :                 cube_subim->copyData(oneterm);
     311         180 :               }
     312             :             
     313             : 
     314          90 :           }//for chan
     315          18 :       }// for pol
     316             : 
     317          18 :     return True;
     318             : 
     319          18 :   }//end of func
     320             : 
     321             : 
     322             :   // Calculate the RHS of the Normal equations for a linear least squares fit of a Taylor polynomial (per pixel). 
     323             :   // This function is primarily for use with mtmfs_via_cube, and may be used for the PSF (2nterms-1), the residual (nterms) 
     324             :   // and the primary beam (nterms=1).  
     325             :   // imtype=0 : PSF with 2nterms-1 terms
     326             :   // imtype=1 : residual with nterms terms
     327             :   // imtype=2 : pb with 1 term
     328             :   // imtype=3 : sumwt with 2nterms-1 terms
     329          53 :   Bool SynthesisUtilMethods::cubeToTaylorSum(const String& cubename,const String& mtname,  const Int nterms, const String& reffreq, const Int imtype, const Float pblimit)
     330             :   {
     331         106 :     LogIO os(LogOrigin("SynthesisUtilMethods", "cubeToTaylorSum"));
     332             : 
     333             :     //cout << "imtype : " << imtype << endl;
     334          53 :     if(imtype <0 || imtype >3)
     335             :       {
     336           0 :         throw( AipsError("cubeToTaylorSum currently only supports 'psf','residual','pb', 'sumwt' options"));
     337             :       }
     338             :     
     339             :     // Set up imstores
     340          53 :     CountedPtr<SIImageStore> cube_imstore;
     341          53 :     cube_imstore = CountedPtr<SIImageStore>(new SIImageStore( cubename, true, true ));  
     342             : 
     343          53 :     CountedPtr<SIImageStoreMultiTerm> mt_imstore;
     344          53 :     mt_imstore = CountedPtr<SIImageStoreMultiTerm>(new SIImageStoreMultiTerm( mtname, nterms, true, true )); 
     345             :     //For psf   avg pb has to be done already
     346             :     // doing residual too for sensitivity  this is independent of beam spectral index removal
     347          53 :     Float maxPB=1.0;
     348          53 :     if(imtype < 2){
     349          70 :       LatticeExprNode elnod( max( *(mt_imstore->pb(0)) ) );
     350          35 :       maxPB=elnod.getFloat();
     351          35 :       if(maxPB == 0.0){
     352           0 :        throw(AipsError("Programmers error: should do tt psf images after making average PB")); 
     353             :         
     354             :       }
     355             :      
     356          35 :     }
     357             :     //    cerr << "imtype " << imtype << " MAX PB " << maxPB << endl;
     358             :     // If dopsf=True, calculate 2n-1 terms.
     359          53 :     Int out_nterms=nterms; // for residual
     360          53 :     if(imtype==0 || imtype==3){out_nterms=2 * nterms - 1;} // the psfs fill the upper triangle of the Hessian with 2 nterms-1 elements. Also sumwt.
     361          53 :     if(imtype==2){out_nterms=1;} // For the PB, for mtmfs_via_cube, we need only tt0.  Later, if we need all terms to calculate PB alpha, then change this to nterms, and add the invHesian math (elsewhere) to later convert the RHS vector into the coefficients. 
     362             : 
     363          53 :     CountedPtr <ImageInterface<Float> > use_cube, use_mt;
     364             :     // If dopsf=True, check that .psf cube and mt's exist.  If dopsf=False, check residual images. 
     365             :     try{
     366          53 :       switch(imtype)
     367             :         {
     368           9 :         case 0: use_cube=cube_imstore->psf();break; 
     369          26 :         case 1: use_cube=cube_imstore->residual();break;
     370           9 :         case 2: use_cube=cube_imstore->pb();break;
     371           9 :         case 3: use_cube=cube_imstore->sumwt();break;
     372             :         }
     373          53 :       cube_imstore->sumwt();
     374         168 :       for(Int i=0;i<out_nterms;i++)
     375             :         {
     376         115 :           switch(imtype)
     377             :             {
     378          27 :             case 0:mt_imstore->psf(i);break; 
     379          52 :             case 1:mt_imstore->residual(i);break;
     380           9 :             case 2:mt_imstore->pb(i);break;
     381          27 :             case 3:mt_imstore->sumwt(i);break;
     382             :             }
     383             :         }
     384             :     }
     385           0 :     catch(AipsError &x)
     386             :       {
     387           0 :         throw( AipsError("Error in reading image : " + x.getMesg() + "\n " + imtype + " images must exist on disk." ));
     388           0 :       }
     389             : 
     390             :     // Get/check shapes ( Assume that the PSF always exists in the imstore... A valid assumption in the context of mtmfs_via_cube )
     391         106 :     IPosition cube_shp( cube_imstore->psf()->shape() );
     392         106 :     IPosition mt_shp( mt_imstore->psf(0)->shape() );
     393          53 :     if( cube_shp[0] != mt_shp[0] || cube_shp[1] != mt_shp[1] ||cube_shp[2] != mt_shp[2] ){
     394           0 :       throw( AipsError("The Cube and Multi-Term images should have the same nx, ny and npol"));
     395             :     }
     396             : 
     397             :     // Read reference frequency
     398         106 :     Quantity reffreq_qa;
     399          53 :     Quantity::read( reffreq_qa, reffreq );
     400          53 :     Double refval = reffreq_qa.getValue("Hz");
     401             :     
     402             :     //cout << "ref freq : " << refval << endl;
     403             : 
     404             :     //Get the frequency list for the cube
     405         106 :     CoordinateSystem csys ( cube_imstore->getCSys() );
     406         106 :     Vector<Double> freqlist( cube_shp[3] );
     407             : 
     408         212 :     for(uInt i=0; i<csys.nCoordinates(); i++)
     409             :     {
     410         159 :       if( csys.type(i) == Coordinate::SPECTRAL )
     411             :         {
     412          53 :           SpectralCoordinate speccoord(csys.spectralCoordinate(i));
     413             : 
     414         324 :           for(Int ch=0;ch<cube_shp[3];ch++)
     415             :             {
     416             :               Double freq;
     417         271 :               Bool ret = speccoord.toWorld( freq, ch );
     418         271 :               if(ret==False) throw(AipsError("Cannot read channel frequency"));
     419         271 :               freqlist[ch] = freq;
     420             :               // cout << "freq " << ch << "  is " << freq << endl;
     421             :             }
     422             : 
     423          53 :         }
     424             :     }
     425             : 
     426             : 
     427             :     // Reset the Taylor Sum values to zero. 
     428         168 :     for(Int i=0;i<out_nterms;i++)
     429             :       {
     430         115 :         switch(imtype)
     431             :           {
     432          27 :           case 0:mt_imstore->psf(i)->set(0.0);break;
     433          52 :           case 1:mt_imstore->residual(i)->set(0.0);break;
     434           9 :           case 2:mt_imstore->pb(i)->set(0.0);break;
     435          27 :           case 3:mt_imstore->sumwt(i)->set(0.0);break;
     436             :           }
     437             :       }
     438             : 
     439             :     // Get the sumwt spectrum.
     440         106 :     Array<Float> lsumwt;
     441          53 :     cube_imstore->sumwt()->get(lsumwt, False);
     442             : 
     443             :     // Sum the weights ( or just use accumulate...) 
     444         106 :     LatticeExprNode msum( sum( *cube_imstore->sumwt() ) );
     445          53 :     Float wtsum = msum.getFloat();
     446             : 
     447             :     //cerr << "perchansumwt : shape "<< lsumwt.shape() << "  "  << lsumwt << " sumwt "<< wtsum << endl;
     448             : 
     449             :     //Float wtsum = cube_shp[3]; // This is sum of weights, if all weights are 1.0 
     450             : 
     451             :     //For each pol, do the Cube-To-Taylor calculation.    
     452         106 :     for(Int pol=0; pol<cube_shp[2]; pol++)
     453             :       {
     454          53 :         Vector< CountedPtr <ImageInterface<Float> > > mt_subims(out_nterms);
     455         168 :         for(Int i=0;i<out_nterms;i++)
     456             :           {
     457         115 :           switch(imtype)
     458             :             {
     459          27 :             case 0:use_mt=mt_imstore->psf(i);break; 
     460          52 :             case 1:use_mt=mt_imstore->residual(i);break;
     461           9 :             case 2:use_mt=mt_imstore->pb(i);break;
     462          27 :             case 3:use_mt=mt_imstore->sumwt(i);break;
     463             :             }
     464         345 :                     mt_subims[i] = mt_imstore->makeSubImage(0,1, 
     465         115 :                                                     0, cube_shp[3],
     466         115 :                                                     pol, cube_shp[2], 
     467         230 :                                                     *use_mt );
     468             :           }
     469             : 
     470         324 :         for(Int chan=0; chan<cube_shp[3]; chan++)
     471             :           {
     472         271 :             CountedPtr<ImageInterface<Float> > cube_subim=cube_imstore->makeSubImage(0,1, 
     473         271 :                                                                                      chan, cube_shp[3],
     474         271 :                                                                                      pol, cube_shp[2], 
     475         271 :                                                                                      *use_cube);
     476         271 :         if(imtype < 2){
     477         358 :           CountedPtr<ImageInterface<Float> > pb_subim=cube_imstore->makeSubImage(0,1, 
     478         179 :                                                                                      chan, cube_shp[3],
     479         179 :                                                                                      pol, cube_shp[2], 
     480         358 :                                                                                      *(cube_imstore->pb()));
     481         358 :           CountedPtr<ImageInterface<Float> > tmplat = new TempImage<Float>(cube_subim->shape(), cube_subim->coordinates());
     482         179 :           tmplat->copyData(LatticeExpr<Float>((*pb_subim) *(*cube_subim)));
     483         179 :           cube_subim = tmplat;
     484             :           
     485         179 :         }
     486             : 
     487         271 :             IPosition pos(4,0,0,pol,chan);
     488             :             
     489         271 :             Double wt = (freqlist[chan] - refval) / refval;
     490             : 
     491         859 :             for(Int tt=0;tt<out_nterms;tt++)
     492             :               {
     493         588 :                 Double fac = pow(wt,tt);
     494             :                 //cerr <<  "BEF accum " <<  max(mt_subims[tt]->get()) << " for imtype " << imtype <<  endl;
     495        1176 :                 LatticeExpr<Float> eachterm = LatticeExpr<Float>( (*mt_subims[tt])  + ((fac) * (*cube_subim) * lsumwt(pos)))  ;
     496         588 :                 mt_subims[tt]->copyData(eachterm);
     497             :                 //cerr <<" AFT accum :  chan " <<  chan  <<  " tt " <<  tt <<  " fac " << fac <<  " lsumwt " <<  lsumwt(pos) <<  " pos " << pos << " max " <<  max(mt_subims[tt]->get()) <<  endl;
     498         588 :               }
     499             :             
     500             : 
     501         271 :           }//for chan
     502             : 
     503             :                 
     504             :         // Divide by sum of weights.
     505         168 :         for(Int tt=0;tt<out_nterms;tt++)
     506             :           {
     507             :             //cerr << "bef div : tt " <<  tt << " : " <<   max(mt_subims[tt]->get()) << " for imtype " << imtype << endl; 
     508             :             
     509         115 :             LatticeExpr<Float> eachterm;
     510         115 :             if (imtype < 2) {
     511          79 :               eachterm = LatticeExpr<Float>( iif( (*(mt_imstore->pb(0))) > pblimit , (*mt_subims[tt]) / wtsum/(*(mt_imstore->pb(0))),  0.0));
     512             :             }
     513             :             else{
     514          36 :               eachterm  = LatticeExpr<Float>( (*mt_subims[tt]) / wtsum ) ;
     515             :             }
     516         115 :             mt_subims[tt]->copyData(eachterm);
     517             : 
     518         115 :             mt_subims[tt]->flush();
     519             :             // cerr << "aft div : " <<  max(mt_subims[tt]->get()) <<  endl;
     520         115 :           }
     521             :         
     522          53 :       }// for pol
     523             : 
     524             : 
     525             :     // Set the T/F mask, for PB images. Without this, the PB is fully masked, for aproj /mosaic gridders.
     526          53 :     if( imtype==2 )
     527             :       {
     528           9 :         mt_imstore->removeMask( mt_imstore->pb(0) );
     529             :         {
     530             :           //MSK//       
     531          18 :           LatticeExpr<Bool> pbmask( iif( *mt_imstore->pb(0) > fabs(pblimit) , True , False ) );
     532             :           //MSK// 
     533           9 :           mt_imstore->createMask( pbmask, mt_imstore->pb(0) );
     534           9 :           mt_imstore->pb(0)->pixelMask().unlock();
     535           9 :         }
     536             :         
     537             :       }
     538             :     
     539         106 :     return True;
     540             : 
     541          53 :   }//end of func
     542             : 
     543             : 
     544          26 :   Bool SynthesisUtilMethods::removeFreqDepPB(const String& cubename, const String& mtname, const Float pblimit)
     545             :   {
     546          52 :     LogIO os(LogOrigin("SynthesisUtilMethods", "removeFreqDepPB"));
     547             : 
     548             :     // Set up imstores
     549          26 :     CountedPtr<SIImageStore> cube_imstore;
     550          26 :     cube_imstore = CountedPtr<SIImageStore>(new SIImageStore( cubename, true, true ));  
     551             : 
     552          26 :     CountedPtr<SIImageStoreMultiTerm> mt_imstore;
     553          26 :     mt_imstore = CountedPtr<SIImageStoreMultiTerm>(new SIImageStoreMultiTerm( mtname, 1, true, true )); 
     554             : 
     555             :     try{
     556          26 :       cube_imstore->residual();  // Residual Cube
     557          26 :       cube_imstore->pb(); // PB cube
     558          26 :       mt_imstore->pb(0); // avgPB in the tt0 pb. 
     559             :     }
     560           0 :     catch(AipsError &x)
     561             :       {
     562           0 :         throw( AipsError("Error in reading image : " + x.getMesg() + "\n Residual cube, PB cube, and multiterm PB.tt0 must exist on disk." ));
     563           0 :       }
     564             :     
     565             :     // Get/check shapes
     566          26 :     IPosition cube_shp( cube_imstore->residual()->shape() );
     567          26 :     IPosition mt_shp( mt_imstore->pb(0)->shape() );
     568          26 :     if( cube_shp[0] != mt_shp[0] || cube_shp[1] != mt_shp[1] ||cube_shp[2] != mt_shp[2] ){
     569           0 :       throw( AipsError("The Cube and Multi-Term images should have the same nx, ny and npol"));
     570             :     }
     571             : 
     572             :     //For each pol, do the freq-dep PB math.//////////////////////////
     573          52 :     for(Int pol=0; pol<cube_shp[2]; pol++)
     574             :       {
     575             : 
     576          52 :         CountedPtr<ImageInterface<Float> >  mt_subim = mt_imstore->makeSubImage(0,1, 
     577          26 :                                                                                 0, cube_shp[3],
     578          26 :                                                                                 pol, cube_shp[2], 
     579          52 :                                                                                 (*mt_imstore->pb(0)) );
     580             : 
     581          26 :         LatticeExprNode mtpbmax( max( *mt_subim ) );
     582          26 :         Float mtpbmaxval = mtpbmax.getFloat();
     583          26 :         if(mtpbmaxval <=0.0){os << LogIO::WARN << "pb.tt0 max is < or = zero" << LogIO::POST;}
     584             : 
     585             : 
     586         159 :         for(Int chan=0; chan<cube_shp[3]; chan++)
     587             :           {
     588         266 :             CountedPtr<ImageInterface<Float> > cube_subim=cube_imstore->makeSubImage(0,1, 
     589         133 :                                                                                      chan, cube_shp[3],
     590         133 :                                                                                      pol, cube_shp[2], 
     591         266 :                                                                                      *cube_imstore->residual() );
     592         266 :             CountedPtr<ImageInterface<Float> > pb_subim=cube_imstore->makeSubImage(0,1, 
     593         133 :                                                                                      chan, cube_shp[3],
     594         133 :                                                                                      pol, cube_shp[2], 
     595         266 :                                                                                      *cube_imstore->pb() );
     596             : 
     597         133 :             LatticeExprNode pbmax( max( *pb_subim ) );
     598         133 :             Float pbmaxval = pbmax.getFloat();
     599         133 :             if( pbmaxval<=0.0 )
     600             :               {
     601           0 :                 os << LogIO::WARN << "pb max is zero for chan" << chan << LogIO::POST;
     602             :               }
     603             :             else
     604             :               {
     605         266 :                 LatticeExpr<Float> thepbcor( iif( *(pb_subim) > pblimit , (*mt_subim)*(*(cube_subim))/(*(pb_subim)) , 0.0 ) );
     606         133 :                 cube_subim->copyData( thepbcor );
     607         133 :               }// if not zero
     608             :             
     609         133 :           }//for chan
     610          26 :       }// for pol
     611             : 
     612          26 :     return True;
     613             : 
     614          26 :   }//end of func
     615             : 
     616             : 
     617             : 
     618          18 :   Bool SynthesisUtilMethods::applyFreqDepPB(const String& cubename, const String& mtname, const Float pblimit)
     619             :   {
     620          36 :     LogIO os(LogOrigin("SynthesisUtilMethods", "applyFreqDepPB"));
     621             : 
     622             :     // Set up imstores
     623          18 :     CountedPtr<SIImageStore> cube_imstore;
     624          18 :     cube_imstore = CountedPtr<SIImageStore>(new SIImageStore( cubename, true, true ));  
     625             : 
     626          18 :     CountedPtr<SIImageStoreMultiTerm> mt_imstore;
     627          18 :     mt_imstore = CountedPtr<SIImageStoreMultiTerm>(new SIImageStoreMultiTerm( mtname, 1, true, true )); 
     628             : 
     629             :     try{
     630          18 :       cube_imstore->model();  // Model Cube
     631          18 :       cube_imstore->pb(); // PB cube
     632          18 :       mt_imstore->pb(0); // avgPB in the tt0 pb. 
     633             :     }
     634           0 :     catch(AipsError &x)
     635             :       {
     636           0 :         throw( AipsError("Error in reading image : " + x.getMesg() + "\n Model cube, PB cube, and multiterm PB.tt0 must exist on disk." ));
     637           0 :       }
     638             :     
     639             :     // Get/check shapes
     640          18 :     IPosition cube_shp( cube_imstore->model()->shape() );
     641          18 :     IPosition mt_shp( mt_imstore->pb(0)->shape() );
     642          18 :     if( cube_shp[0] != mt_shp[0] || cube_shp[1] != mt_shp[1] ||cube_shp[2] != mt_shp[2] ){
     643           0 :       throw( AipsError("The Cube and Multi-Term images should have the same nx, ny and npol"));
     644             :     }
     645             : 
     646             :     //For each pol, do the freq-dep PB math.//////////////////////////
     647          36 :     for(Int pol=0; pol<cube_shp[2]; pol++)
     648             :       {
     649          36 :         CountedPtr<ImageInterface<Float> >  mt_subim = mt_imstore->makeSubImage(0,1, 
     650          18 :                                                                                 0, cube_shp[3],
     651          18 :                                                                                 pol, cube_shp[2], 
     652          36 :                                                                                 (*mt_imstore->pb(0)) );
     653             : 
     654          18 :         LatticeExprNode mtpbmax( max( *mt_subim ) );
     655          18 :         Float mtpbmaxval = mtpbmax.getFloat();
     656          18 :         if(mtpbmaxval <=0.0)
     657           0 :           {os << LogIO::SEVERE << "pb.tt0 max is < or = zero. Cannot divide model image ! ERROR" << LogIO::POST;}
     658             :         else
     659             :           {
     660             :             
     661         108 :             for(Int chan=0; chan<cube_shp[3]; chan++)
     662             :               {
     663         180 :                 CountedPtr<ImageInterface<Float> > cube_subim=cube_imstore->makeSubImage(0,1, 
     664          90 :                                                                                          chan, cube_shp[3],
     665          90 :                                                                                          pol, cube_shp[2], 
     666         180 :                                                                                          *cube_imstore->model() );
     667         180 :                 CountedPtr<ImageInterface<Float> > pb_subim=cube_imstore->makeSubImage(0,1, 
     668          90 :                                                                                        chan, cube_shp[3],
     669          90 :                                                                                        pol, cube_shp[2], 
     670         180 :                                                                                        *cube_imstore->pb() );
     671             :                 
     672             :                 
     673          90 :                 LatticeExprNode pbmax( max( *pb_subim ) );
     674          90 :                 Float pbmaxval = pbmax.getFloat();
     675          90 :                 if( pbmaxval<=0.0 )
     676             :                   {
     677           0 :                     os << LogIO::WARN << "pb max is zero for chan" << chan << LogIO::POST;
     678             :                   }
     679             :                 else
     680             :                   {
     681         180 :                     LatticeExpr<Float> thepbcor( iif( *(pb_subim) > pblimit , (*(cube_subim)) *(*(pb_subim)) / (*mt_subim) , 0.0 ) );
     682          90 :                     cube_subim->copyData( thepbcor );
     683          90 :                   }// if not zero
     684             :                 
     685          90 :               }//for chan
     686             :           }// if mtpb >0
     687          18 :       }// for pol
     688             : 
     689          18 :     return True;
     690             : 
     691          18 :   }//end of func
     692             : 
     693             : 
     694             : 
     695             : 
     696             :   /***make a record of synthesisimager::weight parameters***/
     697        1630 :   Record SynthesisUtilMethods::fillWeightRecord(const String& type, const String& rmode,
     698             :                                const Quantity& noise, const Double robust,
     699             :                                const Quantity& fieldofview,
     700             :                                  const Int npixels, const Bool multiField, const Bool useCubeBriggs,
     701             :                                const String& filtertype, const Quantity& filterbmaj,
     702             :                                                 const Quantity& filterbmin, const Quantity& filterbpa, const Double& fracBW){
     703             : 
     704        1630 :     Record outRec;
     705        1630 :     outRec.define("type", type);
     706        1630 :     outRec.define("rmode", rmode);
     707        1630 :     Record quantRec;
     708        1630 :     QuantumHolder(noise).toRecord(quantRec);
     709        1630 :     outRec.defineRecord("noise", quantRec);
     710        1630 :     outRec.define("robust", robust);
     711        1630 :     QuantumHolder(fieldofview).toRecord(quantRec);
     712        1630 :     outRec.defineRecord("fieldofview", quantRec);
     713        1630 :     outRec.define("npixels", npixels);
     714        1630 :     outRec.define("multifield", multiField);
     715        1630 :     outRec.define("usecubebriggs", useCubeBriggs);
     716        1630 :     outRec.define("filtertype", filtertype);
     717        1630 :     QuantumHolder(filterbmaj).toRecord(quantRec);
     718        1630 :     outRec.defineRecord("filterbmaj", quantRec);
     719        1630 :     QuantumHolder(filterbmin).toRecord(quantRec);
     720        1630 :     outRec.defineRecord("filterbmin", quantRec);
     721        1630 :     QuantumHolder(filterbpa).toRecord(quantRec);
     722        1630 :     outRec.defineRecord("filterbpa", quantRec);
     723        1630 :     outRec.define("fracBW", fracBW);
     724             : 
     725        3260 :     return outRec;
     726        1630 :   }
     727         869 :   void SynthesisUtilMethods::getFromWeightRecord(String& type, String& rmode,
     728             :                                Quantity& noise, Double& robust,
     729             :                                Quantity& fieldofview,
     730             :                                 Int& npixels, Bool& multiField, Bool& useCubeBriggs,
     731             :                                String& filtertype, Quantity& filterbmaj,
     732             :                                                  Quantity& filterbmin, Quantity& filterbpa, Double& fracBW, const Record& inRec){
     733         869 :     QuantumHolder qh;
     734         869 :     String err;
     735         869 :     if(!inRec.isDefined("type"))
     736           0 :       throw(AipsError("Record is not filled with SynthesisUtilMethods::fillWeightRecord"));
     737         869 :     inRec.get("type", type);
     738         869 :     inRec.get("rmode", rmode);
     739         869 :     if(!qh.fromRecord(err, inRec.asRecord("noise")))
     740           0 :       throw(AipsError("Error in reading noise param"));
     741         869 :     noise=qh.asQuantity();
     742         869 :     inRec.get("robust", robust);
     743         869 :     if(!qh.fromRecord(err, inRec.asRecord("fieldofview")))
     744           0 :       throw(AipsError("Error in reading fieldofview param"));
     745         869 :     fieldofview=qh.asQuantity();
     746         869 :     inRec.get("npixels", npixels);
     747         869 :     inRec.get("multifield", multiField);
     748         869 :     inRec.get("usecubebriggs", useCubeBriggs);
     749         869 :     inRec.get("filtertype", filtertype);
     750         869 :     if(!qh.fromRecord(err, inRec.asRecord("filterbmaj")))
     751           0 :       throw(AipsError("Error in reading filterbmaj param"));
     752         869 :     filterbmaj=qh.asQuantity();
     753         869 :     if(!qh.fromRecord(err, inRec.asRecord("filterbmin")))
     754           0 :       throw(AipsError("Error in reading filterbmin param"));
     755         869 :     filterbmin=qh.asQuantity();
     756         869 :     if(!qh.fromRecord(err, inRec.asRecord("filterbpa")))
     757           0 :       throw(AipsError("Error in reading filterbpa param"));
     758         869 :     filterbpa=qh.asQuantity();
     759         869 :     inRec.get("fracBW", fracBW);
     760             : 
     761             : 
     762             : 
     763         869 :   }
     764             :   
     765             :   
     766             :   /**
     767             :    * Get values from lines of a /proc/self/status file. For example:
     768             :    * 'VmRSS:     600 kB'
     769             :    * @param str line from status file
     770             :    * @return integer value (memory amount, etc.)
     771             :    */
     772           0 :   Int SynthesisUtilMethods::parseProcStatusLine(const std::string &str) {
     773           0 :     istringstream is(str);
     774           0 :     std::string token;
     775           0 :     is >> token;
     776           0 :     is >> token;
     777           0 :     Int value = stoi(token);
     778           0 :     return value;
     779           0 :   }
     780             : 
     781             :   /**
     782             :    * Produces a name for a 'memprofile' output file. For example:
     783             :    * casa.synthesis.imager.memprofile.23514.pc22555.hq.eso.org.20171209_120446.txt
     784             :    * (where 23514 is the PID passed as input parameter).
     785             :    *
     786             :    * @param pid PID of the process running the imager
     787             :    *
     788             :    * @return a longish 'memprofile' filename including PID, machine, timestamp, etc.
     789             :    **/
     790           0 :   String SynthesisUtilMethods::makeResourceFilename(int pid)
     791             :   {
     792           0 :     if (g_hostname.empty() or g_startTimestamp.empty()) {
     793             :       // TODO: not using HOST_NAME_MAX because of issues with __APPLE__
     794             :       // somehow tests tAWPFTM, tSynthesisImager, and tSynthesisImagerVi2 fail.
     795           0 :       const int strMax = 255;
     796             :       char hostname[strMax];
     797           0 :       gethostname(hostname, strMax);
     798           0 :       g_hostname = hostname;
     799             : 
     800           0 :       auto time = std::time(nullptr);
     801           0 :       auto gmt = std::gmtime(&time);
     802           0 :       const char* format = "%Y%m%d_%H%M%S";
     803             :       char timestr[strMax];
     804           0 :       std::strftime(timestr, strMax, format, gmt);
     805           0 :       g_startTimestamp = timestr;
     806             :     }
     807             : 
     808           0 :     return String("casa.synthesis.imager.memprofile." + String::toString(pid) +
     809           0 :                   "." + g_hostname + "." + g_startTimestamp + ".txt");
     810             :   }
     811             : 
     812          13 :     Bool SynthesisUtilMethods::adviseChanSel(Double& freqStart, Double& freqEnd, 
     813             :                        const Double& freqStep,  const MFrequency::Types& freqframe,
     814             :                        Vector<Int>& spw, Vector<Int>& start,
     815             :                                              Vector<Int>& nchan, const String& ms, const String& ephemtab, const Int field_id, const Bool getFreqRange, const String spwselection){
     816             : 
     817          26 :   LogIO os(LogOrigin("SynthesisUtilMethods", "adviseChanSel"));
     818          13 :   if(ms==String("")){
     819           0 :     throw(AipsError("Need a valid MS"));
     820             :   }
     821          13 :   spw.resize();
     822          13 :   start.resize();
     823          13 :   nchan.resize();
     824             :   try {
     825          13 :     if(!getFreqRange){
     826           0 :       Vector<Int> bnchan;
     827           0 :       Vector<Int>  bstart;
     828           0 :       Vector<Int>  bspw;
     829             :       Double fS, fE;
     830           0 :       fS=freqStart;
     831           0 :       fE=freqEnd;
     832           0 :       if(freqEnd < freqStart){
     833           0 :         fS=freqEnd;
     834           0 :         fE=freqStart;
     835             :       }
     836             :     
     837             :       
     838             :       {
     839             :         
     840           0 :         MeasurementSet elms(String(ms), TableLock(TableLock::AutoNoReadLocking), Table::Old);
     841           0 :         if(ephemtab != "" && freqframe == MFrequency::REST ){
     842           0 :            MSUtil::getSpwInSourceFreqRange(bspw, bstart, bnchan, elms, fS, fE, fabs(freqStep), ephemtab, field_id);
     843             :         }
     844             :         else
     845           0 :           MSUtil::getSpwInFreqRange(bspw, bstart, bnchan, elms, fS, fE, fabs(freqStep), freqframe, field_id);
     846           0 :         elms.relinquishAutoLocks(true);
     847             : 
     848           0 :       }
     849           0 :       spw=Vector<Int> (bspw);
     850           0 :       start=Vector<Int> (bstart);
     851           0 :       nchan=Vector<Int> (bnchan);
     852           0 :     }
     853             :     else{
     854             :     
     855             :       {
     856          13 :         MeasurementSet elms(ms, TableLock(TableLock::AutoNoReadLocking), Table::Old);
     857          13 :         MSSelection thisSelection;
     858          13 :         String spsel=spwselection;
     859          13 :         if(spsel=="")spsel="*";
     860          13 :         thisSelection.setSpwExpr(spsel);
     861          13 :         TableExprNode exprNode=thisSelection.toTableExprNode(&elms);
     862          13 :         Matrix<Int> chanlist=thisSelection.getChanList();
     863          13 :         if(chanlist.ncolumn() <3){
     864           0 :           freqStart=-1.0;
     865           0 :           freqEnd=-1.0;
     866           0 :           return false;
     867             :         }
     868          13 :         Vector<Int> elspw=chanlist.column(0);
     869          13 :         Vector<Int> elstart=chanlist.column(1);
     870          26 :         Vector<Int> elnchan=Vector<Int> (chanlist.column(2)-elstart)+1;
     871          13 :         if(ephemtab != "" ){
     872           0 :           const MSColumns mscol(ms);
     873           0 :           MEpoch ep=mscol.timeMeas()(0);
     874           0 :           Quantity sysvel;
     875           0 :           String ephemTable("");
     876           0 :           MDirection::Types mtype=MDirection::APP;
     877           0 :           MDirection mdir(mtype);
     878           0 :           if(Table::isReadable(ephemtab)){
     879           0 :             ephemTable=ephemtab;
     880             :           }
     881           0 :           else if(ephemtab=="TRACKFIELD"){
     882           0 :            ephemTable=(mscol.field()).ephemPath(field_id); 
     883             :           }
     884           0 :           else if(MDirection::getType(mtype, ephemtab)){
     885           0 :             mdir=MDirection(mtype);
     886             :           }
     887             :           
     888           0 :           MSUtil::getFreqRangeAndRefFreqShift(freqStart, freqEnd, sysvel, ep, elspw, elstart, elnchan, elms, ephemTable , mdir, True);
     889             : 
     890           0 :         }
     891             :         else
     892          13 :           MSUtil::getFreqRangeInSpw(freqStart, freqEnd, elspw, elstart, elnchan, elms, freqframe, field_id);
     893          13 :       }
     894             : 
     895             :     }
     896             : 
     897             : 
     898             : 
     899             :         
     900           0 :   } catch (AipsError x) {
     901             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     902           0 :        << LogIO::POST;
     903           0 :     return false;
     904           0 :   } 
     905           0 :   catch (...){
     906             :     os << LogIO::SEVERE << "Unknown  exception handled" 
     907           0 :        << LogIO::POST;
     908           0 :     return false;
     909             :     
     910           0 :   }
     911             :   
     912          13 :   return true;
     913             :   
     914          13 :   }
     915             : 
     916       26901 :   void SynthesisUtilMethods::getResource(String label, String fname)
     917             :   {
     918             :      // TODO: not tested on anything else than LINUX (MACOS for the future)
     919             : #if !defined(AIPS_LINUX)
     920             :       return;
     921             : #endif
     922             : 
     923       26901 :      Bool isOn = false;
     924       26901 :      AipsrcValue<Bool>::find(isOn, g_enableOptMemProfile);
     925       26901 :      if (!isOn)
     926       26901 :          return;
     927             : 
     928             :      // TODO: reorganize, use struct or something to hold and pass info over. ifdef lnx
     929           0 :      LogIO casalog( LogOrigin("SynthesisUtilMethods", "getResource", WHERE) );
     930             : 
     931             :      // To hold memory stats, in MB
     932           0 :      int vmRSS = -1, vmHWM = -1, vmSize = -1, vmPeak = -1, vmSwap = -1;
     933           0 :      pid_t pid = -1;
     934           0 :      int fdSize = -1;
     935             : 
     936             :      // TODO: this won't probably work on anything but linux
     937           0 :      ifstream procFile("/proc/self/status");
     938           0 :      if (procFile.is_open()) {
     939           0 :        std::string line;
     940           0 :        while (not procFile.eof()) {
     941           0 :          getline(procFile, line);
     942           0 :          const std::string startVmRSS = "VmRSS:";
     943           0 :          const std::string startVmWHM = "VmHWM:";
     944           0 :          const std::string startVmSize = "VmSize:";
     945           0 :          const std::string startVmPeak = "VmPeak:";
     946           0 :          const std::string startVmSwap = "VmSwap:";
     947           0 :          const std::string startFDSize = "FDSize:";
     948           0 :          const double KB_TO_MB = 1024.0;
     949           0 :          if (startVmRSS == line.substr(0, startVmRSS.size())) {
     950           0 :            vmRSS = parseProcStatusLine(line.c_str()) / KB_TO_MB;
     951           0 :          } else if (startVmWHM == line.substr(0, startVmWHM.size())) {
     952           0 :            vmHWM = parseProcStatusLine(line.c_str()) / KB_TO_MB;
     953           0 :          } else if (startVmSize == line.substr(0, startVmSize.size())) {
     954           0 :            vmSize = parseProcStatusLine(line.c_str()) / KB_TO_MB;
     955           0 :          } else if (startVmPeak == line.substr(0, startVmPeak.size())) {
     956           0 :            vmPeak = parseProcStatusLine(line.c_str()) / KB_TO_MB;
     957           0 :          } else if (startVmSwap == line.substr(0, startVmSwap.size())) {
     958           0 :            vmSwap = parseProcStatusLine(line.c_str()) / KB_TO_MB;
     959           0 :          } else if (startFDSize == line.substr(0, startFDSize.size())) {
     960           0 :            fdSize = parseProcStatusLine(line.c_str());
     961             :          }
     962           0 :        }
     963           0 :        procFile.close();
     964           0 :      }
     965             : 
     966           0 :      pid = getpid();
     967             : 
     968             :      struct rusage usage;
     969             :      struct timeval now;
     970           0 :      getrusage(RUSAGE_SELF, &usage);
     971           0 :      now = usage.ru_utime;
     972             : 
     973             :      // TODO: check if this works as expected when /proc/self/status is not there
     974             :      // Not clear at all if VmHWM and .ru_maxrss measure the same thing
     975             :      // Some alternative is needed for the other fields as well: VmSize, VMHWM, FDSize.
     976           0 :      if (vmHWM < 0) {
     977           0 :        vmHWM = usage.ru_maxrss;
     978             :      }
     979             : 
     980           0 :      ostringstream oss;
     981           0 :      oss << "PID: " << pid ;
     982           0 :      oss << " MemRSS (VmRSS): " << vmRSS << " MB.";
     983           0 :      oss << " VmWHM: " << vmHWM << " MB.";
     984           0 :      oss << " VirtMem (VmSize): " << vmSize << " MB.";
     985           0 :      oss << " VmPeak: " << vmPeak << " MB.";
     986           0 :      oss << " VmSwap: " << vmSwap << " MB.";
     987           0 :      oss << " ProcTime: " << now.tv_sec << '.' << now.tv_usec;
     988           0 :      oss << " FDSize: " << fdSize;
     989           0 :      oss <<  " [" << label << "] ";
     990           0 :      casalog << oss.str() << LogIO::NORMAL3 <<  LogIO::POST;
     991             : 
     992             :      // Write this to a file too...
     993             :      try {
     994           0 :        if (fname.empty()) {
     995           0 :          fname = makeResourceFilename(pid);
     996             :        }
     997           0 :        ofstream ofile(fname, ios::app);
     998           0 :        if (ofile.is_open()) {
     999           0 :          if (0 == ofile.tellp()) {
    1000             :              casalog << g_enableOptMemProfile << " is enabled, initializing output file for "
    1001             :                  "imager profiling information (memory and run time): " << fname <<
    1002           0 :                  LogIO::NORMAL <<  LogIO::POST;
    1003           0 :              ostringstream header;
    1004             :              header << "# PID, MemRSS_(VmRSS)_MB, VmWHM_MB, VirtMem_(VmSize)_MB, VmPeak_MB, "
    1005           0 :                  "VmSwap_MB, ProcTime_sec, FDSize, label_checkpoint";
    1006           0 :              ofile << header.str() << '\n';
    1007           0 :          }
    1008           0 :          ostringstream line;
    1009           0 :          line << pid << ',' << vmRSS << ',' << vmHWM << ',' << vmSize << ','
    1010           0 :               << vmPeak << ','<< vmSwap << ',' << now.tv_sec << '.' << now.tv_usec << ','
    1011           0 :               << fdSize << ',' << '[' << label << ']';
    1012           0 :          ofile << line.str() << '\n';
    1013           0 :          ofile.close();
    1014           0 :        }
    1015           0 :      } catch(std::runtime_error &exc) {
    1016             :          casalog << "Could not write imager memory+runtime information into output file: "
    1017           0 :                  << fname << LogIO::WARN <<  LogIO::POST;
    1018           0 :      }
    1019           0 :   }
    1020             : 
    1021             : 
    1022             :   // Data partitioning rules for CONTINUUM imaging
    1023             :   //
    1024             :   //  ALL members of the selection parameters in selpars are strings
    1025             :   //  ONLY.  This methods reads the selection parameters from selpars
    1026             :   //  and returns a partitioned Record with npart data selection
    1027             :   //  entries.
    1028             :   //
    1029             :   //  The algorithm used to do the partitioning along the TIME axis is
    1030             :   //  as follows:
    1031             :   //    
    1032             :   //    for each MS in selpars
    1033             :   //      - get the selection parameters
    1034             :   //      - generate a selected MS
    1035             :   //      - get number of rows in the selected MS
    1036             :   //      - divide the rows in nparts
    1037             :   //      - for each part
    1038             :   //          - get compute rowBeg and rowEnd
    1039             :   //          - modify rowEnd such that rowEnd points to the end of
    1040             :   //            full integration data.  This is done as follows:
    1041             :   //               tRef = TIME(rowEnd);
    1042             :   //               reduce rowEnd till TIME(rowEnd) != tRef
    1043             :   //          - Construct a T0~T1 string
    1044             :   //          - Fill it in the timeSelPerPart[msID][PartNo] array
    1045             :   //
    1046           0 :   Record SynthesisUtilMethods::continuumDataPartition(Record &selpars, const Int npart)
    1047             :   {
    1048           0 :     LogIO os( LogOrigin("SynthesisUtilMethods","continuumDataPartition",WHERE) );
    1049             : 
    1050           0 :     Record onepart, allparts;
    1051           0 :     Vector<Vector<String> > timeSelPerPart;
    1052           0 :     timeSelPerPart.resize(selpars.nfields());
    1053             : 
    1054             :     // Duplicate the entire input record npart times, with a specific partition id.
    1055             :     // Modify each sub-record according to partition id.
    1056           0 :     for (uInt msID=0;msID<selpars.nfields();msID++)
    1057             :       {
    1058           0 :         Record thisMS= selpars.subRecord(RecordFieldId("ms"+String::toString(msID)));
    1059           0 :         String msName = thisMS.asString("msname");
    1060           0 :         timeSelPerPart[msID].resize(npart,true);
    1061             :         //
    1062             :         // Make a selected MS and extract the time-column information
    1063             :         //
    1064           0 :         MeasurementSet ms(msName,TableLock(TableLock::AutoNoReadLocking), Table::Old),
    1065           0 :           selectedMS(ms);
    1066           0 :         MSInterface msI(ms);    MSSelection msSelObj; 
    1067           0 :         msSelObj.reset(msI,MSSelection::PARSE_NOW,
    1068             :                        thisMS.asString("timestr"),
    1069             :                        thisMS.asString("antenna"),
    1070             :                        thisMS.asString("field"),
    1071             :                        thisMS.asString("spw"),
    1072             :                        thisMS.asString("uvdist"),
    1073             :                        thisMS.asString("taql"),
    1074             :                        "",//thisMS.asString("poln"),
    1075             :                        thisMS.asString("scan"),
    1076             :                        "",//thisMS.asString("array"),
    1077             :                        thisMS.asString("state"),
    1078             :                        thisMS.asString("obs")//observation
    1079             :                        );
    1080           0 :         msSelObj.getSelectedMS(selectedMS);
    1081             : 
    1082             :         //--------------------------------------------------------------------
    1083             :         // Use the selectedMS to generate time selection strings per part
    1084             :         //
    1085             :         //      Double Tint;
    1086           0 :         MSMainColumns mainCols(selectedMS);
    1087           0 :         Vector<rownr_t> rowNumbers = selectedMS.rowNumbers();
    1088           0 :         Int nRows=selectedMS.nrow(), 
    1089           0 :           dRows=nRows/npart;
    1090           0 :         Int rowBegID=0, rowEndID=nRows-1;
    1091           0 :         Int rowBeg=rowNumbers[rowBegID], rowEnd=rowNumbers[rowEndID];
    1092             :         //cerr << "NRows, dRows, npart = " << nRows << " " << dRows << " " << npart << " " << rowBeg << " " << rowEnd << endl;
    1093             : 
    1094           0 :         rowEndID = rowBegID + dRows;
    1095             :         
    1096             : 
    1097           0 :         MVTime mvInt=mainCols.intervalQuant()(0);
    1098             :         //Time intT(mvInt.getTime());
    1099             :         //      Tint = intT.modifiedJulianDay();
    1100             : 
    1101           0 :         Int partNo=0;
    1102             :         // The +1 in rowBeg and rowEnd below is because it appears
    1103             :         // that TaQL by default counts from 1, not 0.
    1104           0 :         while(rowEndID < nRows)
    1105             :           {
    1106             :             //      rowBeg=rowNumbers[rowBegID]; rowEnd = rowNumbers[rowEndID];
    1107           0 :             rowBeg=rowBegID+1; rowEnd = rowEndID+1;
    1108           0 :             stringstream taql;
    1109           0 :             taql << "ROWNUMBER() >= " << rowBeg << " && ROWNUMBER() <= " << rowEnd;
    1110           0 :             timeSelPerPart[msID][partNo] = taql.str();
    1111             : 
    1112           0 :             if (partNo == npart - 1) break;
    1113           0 :             partNo++;
    1114           0 :             rowBegID = rowEndID+1;
    1115           0 :             rowEndID = min(rowBegID + dRows, nRows-1);
    1116           0 :             if (rowEndID == nRows-1) break;
    1117           0 :           }
    1118             : 
    1119             :         //rowBeg=rowNumbers[rowBegID]; rowEnd = rowNumbers[nRows-1];
    1120           0 :         stringstream taql;
    1121           0 :         rowBeg=rowBegID+1; rowEnd = nRows-1+1;
    1122           0 :         taql << "ROWNUMBER() >= " << rowBeg << " && ROWNUMBER() <= " << rowEnd;
    1123           0 :         timeSelPerPart[msID][partNo] = taql.str();
    1124             :         os << endl << "Rows = " << rowBeg << " " << rowEnd << " "
    1125           0 :            << "[P][M]: " << msID << ":" << partNo << " " << timeSelPerPart[msID][partNo]
    1126           0 :            << LogIO::POST;            
    1127           0 :       }
    1128             :     //
    1129             :     // The time selection strings for all parts of the current
    1130             :     // msID are in timeSelPerPart.  
    1131             :     //--------------------------------------------------------------------
    1132             :     //
    1133             :     // Now reverse the order of parts and ME loops. Create a Record
    1134             :     // per part, get the MS for thisPart.  Put the associated time
    1135             :     // selection string in it.  Add the thisMS to thisPart Record.
    1136             :     // Finally add thisPart Record to the allparts Record.
    1137             :     //
    1138           0 :     for(Int iPart=0; iPart<npart; iPart++)
    1139             :       {
    1140           0 :         Record thisPart;
    1141           0 :         thisPart.assign(selpars);
    1142           0 :         for (uInt msID=0; msID<selpars.nfields(); msID++)      
    1143             :           {
    1144           0 :             Record thisMS = thisPart.subRecord(RecordFieldId("ms"+String::toString(msID)));
    1145             : 
    1146           0 :             thisMS.define("taql",timeSelPerPart[msID][iPart]);
    1147           0 :             thisPart.defineRecord(RecordFieldId("ms"+String::toString(msID)) , thisMS);
    1148           0 :           }
    1149           0 :         allparts.defineRecord(RecordFieldId(String::toString(iPart)), thisPart);
    1150           0 :       }
    1151             :     //    cerr << allparts << endl;
    1152           0 :     return allparts;
    1153             : 
    1154             :     // for( Int part=0; part < npart; part++)
    1155             :     //   {
    1156             : 
    1157             :     //  onepart.assign(selpars);
    1158             : 
    1159             : 
    1160             :     //  //-------------------------------------------------
    1161             :     //  // WARNING : This is special-case code for two specific datasets
    1162             :     //  for ( uInt msid=0; msid<selpars.nfields(); msid++)
    1163             :     //    {
    1164             :     //      Record onems = onepart.subRecord( RecordFieldId("ms"+String::toString(msid)) );
    1165             :     //      String msname = onems.asString("msname");
    1166             :     //      String spw = onems.asString("spw");
    1167             :     //      if(msname.matches("DataTest/twopoints_twochan.ms"))
    1168             :     //        {
    1169             :     //          onems.define("spw", spw+":"+String::toString(part));
    1170             :     //        }
    1171             :     //      if(msname.matches("DataTest/point_twospws.ms"))
    1172             :     //        {
    1173             :     //          onems.define("spw", spw+":"+ (((Bool)part)?("10~19"):("0~9"))  );
    1174             :     //        }
    1175             :     //      if(msname.matches("DataTest/reg_mawproject.ms"))
    1176             :     //        {
    1177             :     //          onems.define("scan", (((Bool)part)?("1~17"):("18~35"))  );
    1178             :     //        }
    1179             :     //      onepart.defineRecord( RecordFieldId("ms"+String::toString(msid)) , onems );
    1180             :     //    }// end ms loop
    1181             :     //  //-------------------------------------------------
    1182             : 
    1183             :     //  allparts.defineRecord( RecordFieldId(String::toString(part)), onepart );
    1184             : 
    1185             :     //   }// end partition loop
    1186             : 
    1187             :     // return allparts;
    1188           0 :   }
    1189             : 
    1190             : 
    1191             :   // Data partitioning rules for CUBE imaging
    1192           0 :   Record SynthesisUtilMethods::cubeDataPartition(const Record &selpars, const Int npart,
    1193             :                   const Double freqBeg, const Double freqEnd, const MFrequency::Types eltype)
    1194             :   {
    1195           0 :     LogIO os( LogOrigin("SynthesisUtilMethods","cubeDataPartition",WHERE) );
    1196             :     // Temporary special-case code. Please replace with actual rules.
    1197           0 :     Vector<Double> fstart(npart);
    1198           0 :     Vector<Double> fend(npart);
    1199           0 :     Double step=(freqEnd-freqBeg)/Double(npart);
    1200           0 :     fstart(0)=freqBeg;
    1201           0 :     fend(0)=freqBeg+step;
    1202           0 :     for (Int k=1; k < npart; ++k){
    1203           0 :         fstart(k)=fstart(k-1)+step;
    1204           0 :         fend(k)=fend(k-1)+step;
    1205             :     }
    1206           0 :     return cubeDataPartition( selpars, fstart, fend, eltype );
    1207             : 
    1208           0 :   }
    1209             : 
    1210             : 
    1211           0 :   Record SynthesisUtilMethods::cubeDataImagePartition(const Record & selpars, const CoordinateSystem&
    1212             :                                     incsys, const Int npart, const Int nchannel, 
    1213             :                                     Vector<CoordinateSystem>& outCsys,
    1214             :                                                  Vector<Int>& outnChan){
    1215             : 
    1216           0 :     LogIO os( LogOrigin("SynthesisUtilMethods","cubeDataImagePartition",WHERE) );
    1217           0 :     outnChan.resize(npart);
    1218           0 :     outCsys.resize(npart);
    1219           0 :     Int nomnchan=nchannel/npart;
    1220           0 :     outnChan.set(nomnchan);
    1221           0 :     nomnchan=nchannel%npart;
    1222           0 :     for (Int k=0; k < nomnchan; ++k)
    1223           0 :       outnChan[k]+=1;
    1224           0 :     Vector<Int> shp(0);
    1225             :     //shp(0)=20; shp(1)=20; shp(2)=1; shp(3)=outnChan[0];
    1226           0 :     Vector<Float> shift(4, 0.0);
    1227           0 :     Vector<Float> fac(4, 1.0);
    1228           0 :     Vector<Double> freqEnd(npart);
    1229           0 :     Vector<Double> freqStart(npart);
    1230           0 :     Float chanshift=0.0;
    1231           0 :     for (Int k =0; k <npart; ++k){
    1232           0 :       shift(3)=chanshift;
    1233             :       //cerr << k << " shift " << shift << endl;
    1234           0 :       outCsys[k]=incsys.subImage(shift, fac, shp);
    1235           0 :       freqStart[k]=SpectralImageUtil::worldFreq(outCsys[k], 0.0);
    1236           0 :       freqEnd[k]=SpectralImageUtil::worldFreq(outCsys[k], Double(outnChan[k]-1));
    1237           0 :       if(freqStart[k] > freqEnd[k]){
    1238           0 :         Double tmp=freqEnd[k];
    1239           0 :         freqEnd[k]=freqStart[k];
    1240           0 :         freqStart[k]=tmp;
    1241             :       }
    1242           0 :       chanshift+=Float(outnChan[k]);      
    1243             :     }
    1244           0 :      MFrequency::Types eltype=incsys.spectralCoordinate(incsys.findCoordinate(Coordinate::SPECTRAL)).frequencySystem(true);
    1245             : 
    1246             :      //os << "freqStart="<<freqStart<<" freqend="<<freqEnd<< "eltype="<<eltype<<LogIO::POST;
    1247           0 :      Record rec=cubeDataPartition(selpars, freqStart, freqEnd, eltype);
    1248           0 :      for (Int k=0; k < npart ; ++k){
    1249           0 :        outCsys[k].save(rec.asrwRecord(String::toString(k)), "coordsys");
    1250           0 :        rec.asrwRecord(String::toString(k)).define("nchan", outnChan[k]);
    1251             :      }
    1252           0 :      return rec;
    1253           0 :   }
    1254             : 
    1255           0 :   Record SynthesisUtilMethods::cubeDataPartition(const Record &selpars, const Vector<Double>& freqBeg, const Vector<Double>&freqEnd, const MFrequency::Types eltype){
    1256           0 :     LogIO os( LogOrigin("SynthesisUtilMethods","cubeDataPartition",WHERE) );
    1257           0 :     Record retRec;
    1258           0 :     Int npart=freqBeg.shape()(0);
    1259           0 :     for (Int k=0; k < npart; ++k){
    1260           0 :       Int nms=selpars.nfields();
    1261           0 :       Record partRec;
    1262           0 :       for(Int j=0; j < nms; ++j){
    1263           0 :           if(selpars.isDefined(String("ms"+String::toString(j)))){
    1264           0 :                   Record msRec=selpars.asRecord(String("ms"+String::toString(j)));
    1265           0 :                   if(!msRec.isDefined("msname"))
    1266           0 :                           throw(AipsError("No msname key in ms record"));
    1267           0 :                   String msname=msRec.asString("msname");
    1268           0 :                   String userspw=msRec.isDefined("spw")? msRec.asString("spw") : "*";
    1269           0 :                   String userfield=msRec.isDefined("field") ? msRec.asString("field") : "*";
    1270           0 :                   String userstate=msRec.isDefined("state") ? msRec.asString("state") : "*";
    1271             :                   
    1272           0 :                   MeasurementSet elms(msname);
    1273           0 :                   Record laSelection=elms.msseltoindex(userspw, userfield);
    1274           0 :                   if (userfield=="")  userfield="*";
    1275           0 :                   MSSelection mssel;
    1276           0 :                   mssel.setSpwExpr(userspw);
    1277           0 :                   mssel.setFieldExpr(userfield);
    1278           0 :                   mssel.setStateExpr(userstate);
    1279           0 :                   TableExprNode exprNode = mssel.toTableExprNode(&elms);
    1280           0 :                   Matrix<Int> spwsel=mssel.getChanList();
    1281           0 :                   Vector<Int> fieldsel=mssel.getFieldList();
    1282             :                   // case for scan intent specified 
    1283           0 :                   if (userstate!="*") {
    1284           0 :                     MeasurementSet elselms((elms)(exprNode), &elms);
    1285           0 :                     MSColumns tmpmsc(elselms);
    1286           0 :                     Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
    1287           0 :                     if (fldidv.nelements()==0)
    1288           0 :                       throw(AipsError("No field ids were selected, please check input parameters"));
    1289           0 :                     std::set<Int> ufldids(fldidv.begin(),fldidv.end());
    1290           0 :                     std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
    1291           0 :                     fieldsel.resize(tmpv.size());
    1292           0 :                     uInt count=0;
    1293           0 :                     for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
    1294             :                     {
    1295           0 :                       fieldsel(count) = *it;
    1296           0 :                       count++;
    1297             :                     }
    1298           0 :                   }
    1299             :                   //Matrix<Int> spwsel=laSelection.asArrayInt("channel");
    1300             :                   //Vector<Int> fieldsel=laSelection.asArrayInt("field");
    1301           0 :                   Vector<Int> freqSpw;
    1302           0 :                   Vector<Int> freqStart;
    1303           0 :                   Vector<Int> freqNchan;
    1304           0 :                   String newspw;
    1305             :                   try{
    1306           0 :                     MSUtil::getSpwInFreqRange(freqSpw, freqStart, freqNchan, elms, freqBeg(k), freqEnd(k),0.0, eltype, fieldsel[0]);
    1307           0 :                     newspw=mergeSpwSel(freqSpw, freqStart, freqNchan, spwsel);
    1308             :                     //cerr << "try " << freqSpw <<  "  " << freqStart << "  " << freqNchan << endl;
    1309             :                   }
    1310           0 :                   catch(...){
    1311             :                     //cerr << "In catch " << endl;
    1312           0 :                     newspw="";
    1313           0 :                   }
    1314             :                   //String newspw=mergeSpwSel(freqSpw, freqStart, freqNchan, spwsel);
    1315           0 :                   if(newspw=="") newspw="-1";
    1316           0 :                   msRec.define("spw", newspw);
    1317           0 :                   partRec.defineRecord(String("ms"+String::toString(j)),msRec);
    1318           0 :           }
    1319             : 
    1320             :       }
    1321           0 :       retRec.defineRecord(String::toString(k), partRec);
    1322           0 :     }
    1323             : 
    1324             : 
    1325             : 
    1326             : 
    1327           0 :     return retRec;
    1328           0 :   }
    1329             : 
    1330             : 
    1331           0 :  String  SynthesisUtilMethods::mergeSpwSel(const Vector<Int>& fspw, const Vector<Int>& fstart, const Vector<Int>& fnchan, const Matrix<Int>& spwsel)
    1332             :   {
    1333           0 :          String retval="";
    1334             :          Int cstart, cend;
    1335           0 :           for(Int k=0; k < fspw.shape()(0); ++k){
    1336           0 :                   cstart=fstart(k);
    1337           0 :                   cend=fstart(k)+fnchan(k)-1;
    1338           0 :                   for (Int j=0; j < spwsel.shape()(0); ++j){
    1339             :                         //need to put this here as multiple rows can have the same spw
    1340           0 :                         cstart=fstart(k);
    1341           0 :                         cend=fstart(k)+fnchan(k)-1;
    1342           0 :                         if(spwsel(j,0)==fspw[k]){
    1343           0 :                           if(cstart < spwsel(j,1)) cstart=spwsel(j,1);
    1344           0 :                           if(cend > spwsel(j,2)) cend= spwsel(j,2);
    1345           0 :                                 if(!retval.empty()) retval=retval+(",");
    1346           0 :                                 retval=retval+String::toString(fspw[k])+":"+String::toString(cstart)+"~"+String::toString(cend);
    1347             :                         }
    1348             :                   }
    1349             :           }
    1350             : 
    1351             : 
    1352             : 
    1353           0 :           return retval;
    1354           0 :   }
    1355             : 
    1356             :   // Image cube partitioning rules for CUBE imaging
    1357           0 :   Record SynthesisUtilMethods::cubeImagePartition(Record &impars, Int npart)
    1358             :   {
    1359           0 :     LogIO os( LogOrigin("SynthesisUtilMethods","cubeImagePartition",WHERE) );
    1360             : 
    1361           0 :     Record onepart, allparts;
    1362             : 
    1363             :     // Duplicate the entire input record npart times, with a specific partition id.
    1364             :     // Modify each sub-record according to partition id.
    1365           0 :     for( Int part=0; part < npart; part++)
    1366             :       {
    1367             : 
    1368           0 :         onepart.assign(impars);
    1369             : 
    1370             :         //-------------------------------------------------
    1371             :         // WARNING : This is special-case code for two specific datasets
    1372           0 :         for ( uInt imfld=0; imfld<impars.nfields(); imfld++)
    1373             :           {
    1374           0 :             Record onefld = onepart.subRecord( RecordFieldId(String::toString(imfld)) );
    1375           0 :             Int nchan = onefld.asInt("nchan");
    1376             :             //String freqstart = onems.asString("freqstart");
    1377             : 
    1378           0 :             onefld.define("nchan", nchan/npart);
    1379           0 :             onefld.define("freqstart", (((Bool)part)?("1.2GHz"):("1.0GHz"))  );
    1380             : 
    1381           0 :             String imname = onefld.asString("imagename");
    1382           0 :             onefld.define("imagename", imname+".n"+String::toString(part));
    1383             : 
    1384           0 :             onepart.defineRecord( RecordFieldId( String::toString(imfld) ), onefld );
    1385           0 :           }// end ms loop
    1386             :         //-------------------------------------------------
    1387             : 
    1388           0 :         allparts.defineRecord( RecordFieldId(String::toString(part)), onepart );
    1389             : 
    1390             :       }// end partition loop
    1391             : 
    1392           0 :     return allparts;
    1393             :     
    1394             : 
    1395           0 :   }
    1396             : 
    1397         155 :   String SynthesisUtilMethods::asComprehensibleDirectionString(MDirection const &direction)
    1398             :   {
    1399         155 :     MVAngle mvRa=direction.getAngle().getValue()(0);
    1400         155 :     MVAngle mvDec=direction.getAngle().getValue()(1);
    1401         155 :     ostringstream oos;
    1402         155 :     oos << "     ";
    1403         155 :     Int widthRA=20;
    1404         155 :     Int widthDec=20;
    1405         155 :     oos.setf(ios::left, ios::adjustfield);
    1406         155 :     oos.width(widthRA);  oos << mvRa(0.0).string(MVAngle::TIME,8);
    1407         155 :     oos.width(widthDec); oos << mvDec.string(MVAngle::DIG2,8);
    1408         155 :     oos << "     "
    1409         155 :         << MDirection::showType(direction.getRefPtr()->getType());
    1410         310 :     return String(oos);
    1411         155 :   }
    1412             : 
    1413             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1414             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1415             :   /////////////////    Parameter Containers     ///////////////////////////////////////////////////////
    1416             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1417             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1418             : 
    1419             :   // Read String from Record
    1420       99791 :   String SynthesisParams::readVal(const Record &rec, String id, String& val) const
    1421             :   {
    1422       99791 :     if( rec.isDefined( id ) )
    1423             :       {
    1424       92290 :         String inval("");
    1425       92290 :         if( rec.dataType( id )==TpString ) 
    1426       92290 :           { rec.get( id , inval );  // Read into temp string
    1427             :             //      val = inval;
    1428             :             //      return String("");
    1429             :             // Set value only if it is not a null string. Otherwise, leave it unchanged as it will
    1430             :             // retain the default value that was set before this function was called.
    1431       92290 :             if(inval.length()>0){val=inval;}
    1432       92290 :             return String(""); 
    1433             :           }
    1434           0 :         else { return String(id + " must be a string\n"); }
    1435       92290 :       }
    1436        7501 :     else { return String("");}
    1437             :   }
    1438             : 
    1439             :   // Read Integer from Record
    1440       25412 :   String SynthesisParams::readVal(const Record &rec, String id, Int& val) const
    1441             :   {
    1442       25412 :     if( rec.isDefined( id ) )
    1443             :       {
    1444       25062 :         if( rec.dataType( id )==TpInt ) { rec.get( id , val ); return String(""); }
    1445           0 :         else  { return String(id + " must be an integer\n"); }
    1446             :       }
    1447         350 :     else { return String(""); }
    1448             :   }
    1449             : 
    1450             :   // Read Float from Record
    1451       39499 :   String SynthesisParams::readVal(const Record &rec, String id, Float& val) const
    1452             :   {
    1453       39499 :     if( rec.isDefined( id ) )
    1454             :       {
    1455       36704 :       if ( rec.dataType( id )==TpFloat || rec.dataType( id )==TpDouble )  
    1456       36704 :         { rec.get( id , val ); return String(""); }
    1457           0 :       else { return String(id + " must be a float\n"); }
    1458             :       }
    1459        2795 :     else { return String(""); }
    1460             :   }
    1461             : 
    1462             :   // Read Bool from Record
    1463       49415 :   String SynthesisParams::readVal(const Record &rec, String id, Bool& val) const
    1464             :   {
    1465       49415 :     if( rec.isDefined( id ) )
    1466             :       {
    1467       42104 :         if( rec.dataType( id )==TpBool ) { rec.get( id , val ); return String(""); }
    1468           0 :         else { return String(id + " must be a bool\n"); }
    1469             :       }
    1470        7311 :     else{ return String(""); }
    1471             :   }
    1472             : 
    1473             :   // Read Vector<Int> from Record
    1474         899 :   String SynthesisParams::readVal(const Record &rec, String id, Vector<Int>& val) const
    1475             :   {
    1476         899 :     if( rec.isDefined( id ) )
    1477             :       {
    1478         899 :         if( rec.dataType( id )==TpArrayInt || rec.dataType( id )==TpArrayUInt ) 
    1479         899 :           { rec.get( id , val ); return String(""); }
    1480           0 :         else if ( rec.dataType( id ) == TpArrayBool ) // An empty python vector [] comes in as this.
    1481             :           {
    1482           0 :             Vector<Bool> vec; rec.get( id, vec );
    1483           0 :             if( vec.nelements()==0 ){val.resize(0); return String("");}
    1484           0 :             else{ return String(id + " must be a vector of strings.\n"); }
    1485           0 :           }
    1486           0 :         else { return String(id + " must be a vector of integers\n"); }
    1487             :       }
    1488           0 :     else{ return String(""); }
    1489             :   }
    1490             : 
    1491             :   // Read Vector<Float> from Record
    1492        4369 :   String SynthesisParams::readVal(const Record &rec, String id, Vector<Float>& val) const
    1493             :   {
    1494        4369 :     if( rec.isDefined( id ) )
    1495             :       {
    1496        4369 :         if( rec.dataType( id )==TpArrayFloat )
    1497             :           { 
    1498        2574 :             rec.get( id , val ); return String(""); 
    1499             :             /*
    1500             :             Array<Float> vec; rec.get(id, vec );
    1501             :             cout << " vec : " << vec << endl;
    1502             :             if( vec.shape().nelements()==1 )
    1503             :               {
    1504             :                 val.resize( vec.shape()[0] );
    1505             :                 for(uInt i=0;i<val.nelements();i++){val[i]=(Float)vec(IPosition(1,i));}
    1506             :                 return String("");
    1507             :               }
    1508             :             else { return String(id + " must be a 1D vector of floats"); }
    1509             :             */
    1510             :           }
    1511        1795 :         else if ( rec.dataType( id ) ==TpArrayDouble ) 
    1512             :           {
    1513         170 :             Vector<Double> vec; rec.get( id, vec );
    1514         170 :             val.resize(vec.nelements());
    1515         510 :             for(uInt i=0;i<val.nelements();i++){val[i]=(Float)vec[i];}
    1516         170 :             return String("");
    1517         170 :           }
    1518        1625 :         else if ( rec.dataType( id ) ==TpArrayInt ) 
    1519             :           {
    1520          49 :             Vector<Int> vec; rec.get( id, vec );
    1521          49 :             val.resize(vec.nelements());
    1522         255 :             for(uInt i=0;i<val.nelements();i++){val[i]=(Float)vec[i];}
    1523          49 :             return String("");
    1524          49 :           }
    1525        1576 :         else if ( rec.dataType( id ) == TpArrayBool ) // An empty python vector [] comes in as this.
    1526             :           {
    1527        1576 :             Vector<Bool> vec; rec.get( id, vec );
    1528        1576 :             if( vec.shape().product()==0 ){val.resize(0); return String("");}
    1529           0 :             else{ return String(id + " must be a vector of strings.\n"); }
    1530             :             // val.resize(0); return String("");
    1531        1576 :           }
    1532           0 :         else { return String(id + " must be a vector of floats\n"); }
    1533             :       }
    1534           0 :     else{ return String(""); }
    1535             :   }
    1536             : 
    1537             :   // Read Vector<String> from Record
    1538        4109 :   String SynthesisParams::readVal(const Record &rec, String id, Vector<String>& val) const
    1539             :   {
    1540        4109 :     if( rec.isDefined( id ) )
    1541             :       {
    1542        4109 :         if( rec.dataType( id )==TpArrayString || rec.dataType( id )==TpArrayChar ) 
    1543        4106 :           { rec.get( id , val ); return String(""); }
    1544           3 :         else if ( rec.dataType( id ) == TpArrayBool ) // An empty python vector [] comes in as this.
    1545             :           {
    1546           3 :             Vector<Bool> vec; rec.get( id, vec );
    1547           3 :             if( vec.nelements()==0 ){val.resize(0); return String("");}
    1548           0 :             else{ return String(id + " must be a vector of strings.\n"); }
    1549           3 :           }
    1550           0 :         else { return String(id + " must be a vector of strings.\n"); 
    1551             :         }
    1552             :       }
    1553           0 :     else{ return String(""); }
    1554             :   }
    1555             : 
    1556             :   // Convert String to Quantity
    1557       11818 :   String SynthesisParams::stringToQuantity(String instr, Quantity& qa) const
    1558             :   {
    1559             :     //QuantumHolder qh;
    1560             :     //String error;
    1561             :     //    if( qh.fromString( error, instr ) ) { qa = qh.asQuantity(); return String(""); }
    1562             :     //else { return String("Error in converting " + instr + " to a Quantity : " + error + " \n"); }
    1563       11818 :     if ( casacore::Quantity::read( qa, instr ) ) { return String(""); }
    1564           0 :     else  { return String("Error in converting " + instr + " to a Quantity \n"); }
    1565             :   }
    1566             : 
    1567             :   // Convert String to MDirection
    1568             :   // UR : TODO :    If J2000 not specified, make it still work.
    1569        2148 :   String SynthesisParams::stringToMDirection(String instr, MDirection& md) const
    1570             :   {
    1571             :     try
    1572             :       {
    1573        2148 :         String tmpRF, tmpRA, tmpDEC;
    1574        2148 :         std::istringstream iss(instr);
    1575        2148 :         iss >> tmpRF >> tmpRA >> tmpDEC;
    1576        2148 :         if( tmpDEC.length() == 0 )// J2000 may not be specified.
    1577             :           {
    1578           0 :             tmpDEC = tmpRA;
    1579           0 :             tmpRA = tmpRF;
    1580           0 :             tmpRF = String("J2000");
    1581             :           }
    1582        2148 :         casacore::Quantity tmpQRA;
    1583        2148 :         casacore::Quantity tmpQDEC;
    1584        2148 :         casacore::Quantity::read(tmpQRA, tmpRA);
    1585        2148 :         casacore::Quantity::read(tmpQDEC, tmpDEC);
    1586             : 
    1587        2148 :         if(tmpQDEC.getFullUnit()==Unit("deg") && tmpDEC.contains(":")){
    1588           0 :           LogIO os( LogOrigin("SynthesisParams","stringToMDirection",WHERE) );
    1589             :           os << LogIO::WARN 
    1590             :              << "You provided the Declination/Latitude value \""<< tmpDEC
    1591             :              << "\" which is understood to be in units of hours.\n"
    1592             :              << "If you meant degrees, please replace \":\" by \".\"."
    1593           0 :              << LogIO::POST;
    1594           0 :         }
    1595             : 
    1596             :         MDirection::Types theRF;
    1597        2148 :         Bool status = MDirection::getType(theRF, tmpRF);
    1598        2148 :         if (!status) {
    1599           2 :           throw AipsError();
    1600             :         }
    1601        2146 :         md = MDirection (tmpQRA, tmpQDEC, theRF);
    1602        2146 :         return String("");
    1603        2158 :       }
    1604           2 :     catch(AipsError &x)
    1605             :       {
    1606           4 :         return String("Error in converting '" + instr + "' to MDirection. Need format : 'J2000 19:59:28.500 +40.44.01.50'\n");
    1607           2 :       }
    1608             :   }
    1609             : 
    1610             :   // Read Quantity from a Record string
    1611        9239 :   String SynthesisParams::readVal(const Record &rec, String id, Quantity& val) const
    1612             :   {
    1613        9239 :     if( rec.isDefined( id ) )
    1614             :       {
    1615        8291 :         if( rec.dataType( id )==TpString ) 
    1616        8291 :           { String valstr;  rec.get( id , valstr ); return stringToQuantity(valstr, val); }
    1617           0 :         else { return String(id + " must be a string in the format : '1.5GHz' or '0.2arcsec'...'\n"); }
    1618             :       }
    1619         948 :     else{ return String(""); }
    1620             :   }
    1621             : 
    1622             :   // Read MDirection from a Record string
    1623        3096 :   String SynthesisParams::readVal(const Record &rec, String id, MDirection& val) const
    1624             :   {
    1625        3096 :     if( rec.isDefined( id ) )
    1626             :       {
    1627        2148 :         if( rec.dataType( id )==TpString ) 
    1628        2148 :           { String valstr;  rec.get( id , valstr ); return stringToMDirection(valstr, val); }
    1629           0 :         else { return String(id + " must be a string in the format : 'J2000 19:59:28.500 +40.44.01.50'\n"); }
    1630             :       }
    1631         948 :     else{ return String(""); }
    1632             :   }
    1633             : 
    1634             :   // Convert MDirection to String
    1635        1798 :   String SynthesisParams::MDirectionToString(MDirection val) const
    1636             :   {
    1637        1798 :     MVDirection mvpc( val.getAngle() );
    1638        1798 :     MVAngle ra = mvpc.get()(0);
    1639        1798 :     MVAngle dec = mvpc.get()(1);
    1640             :     // Beware of precision here......( for VLBA / ALMA ). 14 gives 8 digits after the decimal for arcsec.
    1641        5394 :     return  String(val.getRefString() + " " + ra.string(MVAngle::TIME,14) + " " +  dec.string(MVAngle::ANGLE,14));
    1642        1798 :   }
    1643             : 
    1644             :   // Convert Quantity to String
    1645        6058 :   String SynthesisParams::QuantityToString(Quantity val) const
    1646             :   {
    1647        6058 :     std::ostringstream ss;
    1648             :     //use digits10 to ensure the conersions involve use full decimal digits guranteed to be 
    1649             :     //correct plus extra digits to deal with least significant digits (or replace with
    1650             :     // max_digits10 when it is available)
    1651        6058 :     ss.precision(std::numeric_limits<double>::digits10+2);
    1652        6058 :     ss << val;
    1653       18174 :     return ss.str();
    1654             :     // NOTE - 2017.10.04: It was found (CAS-10773) that we cannot use to_string for this as
    1655             :     // the decimal place is fixed to 6 digits. 
    1656             :     //TT: change to C++11 to_string which handles double value to string conversion 
    1657             :     //return String(std::to_string( val.getValue(val.getUnit()) )) + val.getUnit() ;
    1658        6058 :   }
    1659             :   
    1660             :   // Convert Record contains Quantity or Measure quantities to String
    1661          49 :   String SynthesisParams::recordQMToString(const Record &rec) const
    1662             :   { 
    1663             :      Double val;
    1664          49 :      String unit;
    1665          49 :      if ( rec.isDefined("m0") ) 
    1666             :        {
    1667          28 :          Record subrec = rec.subRecord("m0");
    1668          28 :          subrec.get("value",val); 
    1669          28 :          subrec.get("unit",unit);
    1670          28 :        }
    1671          21 :      else if (rec.isDefined("value") )
    1672             :        {
    1673          21 :          rec.get("value",val);
    1674          21 :          rec.get("unit",unit);
    1675             :        }
    1676         147 :      return String::toString(val) + unit;
    1677          49 :   } 
    1678             : 
    1679             : 
    1680             :   /////////////////////// Selection Parameters
    1681             : 
    1682        5112 :   SynthesisParamsSelect::SynthesisParamsSelect():SynthesisParams()
    1683             :   {
    1684        5112 :     setDefaults();
    1685        5112 :   }
    1686             : 
    1687        5122 :   SynthesisParamsSelect::~SynthesisParamsSelect()
    1688             :   {
    1689        5122 :   }
    1690             : 
    1691          11 :   SynthesisParamsSelect::SynthesisParamsSelect(const SynthesisParamsSelect& other){
    1692          11 :           operator=(other);
    1693          11 :   }
    1694             : 
    1695        2037 :   SynthesisParamsSelect& SynthesisParamsSelect::operator=(const SynthesisParamsSelect& other){
    1696        2037 :           if(this!=&other) {
    1697        2037 :                   msname=other.msname;
    1698        2037 :                       spw=other.spw;
    1699        2037 :                       freqbeg=other.freqbeg;
    1700        2037 :                       freqend=other.freqend;
    1701        2037 :                       freqframe=other.freqframe;
    1702        2037 :                       field=other.field;
    1703        2037 :                       antenna=other.antenna;
    1704        2037 :                       timestr=other.timestr;
    1705        2037 :                       scan=other.scan;
    1706        2037 :                       obs=other.obs;
    1707        2037 :                       state=other.state;
    1708        2037 :                       uvdist=other.uvdist;
    1709        2037 :                       taql=other.taql;
    1710        2037 :                       usescratch=other.usescratch;
    1711        2037 :                       readonly=other.readonly;
    1712        2037 :                       incrmodel=other.incrmodel;
    1713        2037 :                       datacolumn=other.datacolumn;
    1714             : 
    1715             :           }
    1716        2037 :           return *this;
    1717             :   }
    1718             : 
    1719        3086 :   void SynthesisParamsSelect::fromRecord(const Record &inrec)
    1720             :   {
    1721        3086 :     setDefaults();
    1722             : 
    1723        3086 :     String err("");
    1724             : 
    1725             :     try
    1726             :       {
    1727             :         
    1728        3086 :         err += readVal( inrec, String("msname"), msname );
    1729             : 
    1730        3086 :         err += readVal( inrec, String("readonly"), readonly );
    1731        3086 :         err += readVal( inrec, String("usescratch"), usescratch );
    1732             : 
    1733             :         // override with entries from savemodel.
    1734        3086 :         String savemodel("");
    1735        3086 :         err += readVal( inrec, String("savemodel"), savemodel );
    1736        3086 :         if( savemodel=="none" ){usescratch=false; readonly=true;}
    1737        1961 :         else if( savemodel=="virtual" ){usescratch=false; readonly=false;}
    1738        1944 :         else if ( savemodel=="modelcolumn" ){ usescratch=true; readonly=false; }
    1739             : 
    1740        3086 :         err += readVal( inrec, String("incrmodel"), incrmodel );
    1741             : 
    1742        3086 :         err += readVal( inrec, String("spw"), spw );
    1743             : 
    1744             :         /// -------------------------------------------------------------------------------------
    1745             :         // Why are these params here ? Repeats of defineimage.
    1746        3086 :         err += readVal( inrec, String("freqbeg"), freqbeg);
    1747        3086 :         err += readVal( inrec, String("freqend"), freqend);
    1748             : 
    1749        3086 :         String freqframestr( MFrequency::showType(freqframe) );
    1750        3086 :         err += readVal( inrec, String("outframe"), freqframestr);
    1751        3086 :         if( ! MFrequency::getType(freqframe, freqframestr) )
    1752           0 :           { err += "Invalid Frequency Frame " + freqframestr ; }
    1753             :         /// -------------------------------------------------------------------------------------
    1754             : 
    1755        3086 :         err += readVal( inrec, String("field"),field);
    1756        3086 :         err += readVal( inrec, String("antenna"),antenna);
    1757        3086 :         err += readVal( inrec, String("timestr"),timestr);
    1758        3086 :         err += readVal( inrec, String("scan"),scan);
    1759        3086 :         err += readVal( inrec, String("obs"),obs);
    1760        3086 :         err += readVal( inrec, String("state"),state);
    1761        3086 :         err += readVal( inrec, String("uvdist"),uvdist);
    1762        3086 :         err += readVal( inrec, String("taql"),taql);
    1763             : 
    1764        3086 :         err += readVal( inrec, String("datacolumn"),datacolumn);
    1765             : 
    1766        3086 :         err += verify();
    1767             : 
    1768        3086 :       }
    1769           0 :     catch(AipsError &x)
    1770             :       {
    1771           0 :         err = err + x.getMesg() + "\n";
    1772           0 :       }
    1773             :       
    1774        3086 :       if( err.length()>0 ) throw(AipsError("Invalid Selection Parameter set : " + err));
    1775             :       
    1776        3086 :   }
    1777             : 
    1778        3086 :   String SynthesisParamsSelect::verify() const
    1779             :   {
    1780        3086 :     String err;
    1781             :     // Does the MS exist on disk.
    1782        3086 :     Directory thems( msname );
    1783        3086 :     if( thems.exists() )
    1784             :       {
    1785             :         // Is it readable ? 
    1786        3086 :         if( ! thems.isReadable() )
    1787           0 :           { err += "MS " + msname + " is not readable.\n"; }
    1788             :         // Depending on 'readonly', is the MS writable ? 
    1789        3086 :         if( readonly==false && ! thems.isWritable() ) 
    1790           0 :           { err += "MS " + msname + " is not writable.\n"; }
    1791             :       }
    1792             :     else 
    1793           0 :       { err += "MS does not exist : " + msname + "\n"; }
    1794             :     
    1795        6172 :     return err;
    1796        3086 :   }
    1797             :   
    1798        8198 :   void SynthesisParamsSelect::setDefaults()
    1799             :   {
    1800        8198 :     msname="";
    1801        8198 :     spw="";
    1802        8198 :     freqbeg="";
    1803        8198 :     freqend="";
    1804        8198 :     MFrequency::getType(freqframe,"LSRK");
    1805        8198 :     field="";
    1806        8198 :     antenna="";
    1807        8198 :     timestr="";
    1808        8198 :     scan="";
    1809        8198 :     obs="";
    1810        8198 :     state="";
    1811        8198 :     uvdist="";
    1812        8198 :     taql="";
    1813        8198 :     usescratch=false;
    1814        8198 :     readonly=true;
    1815        8198 :     incrmodel=false;
    1816        8198 :     datacolumn="corrected";
    1817        8198 :   }
    1818             : 
    1819        2086 :   Record SynthesisParamsSelect::toRecord()const
    1820             :   {
    1821        2086 :     Record selpar;
    1822        2086 :     selpar.define("msname",msname);
    1823        2086 :     selpar.define("spw",spw);
    1824        2086 :     selpar.define("freqbeg",freqbeg);
    1825        2086 :     selpar.define("freqend",freqend);
    1826        2086 :     selpar.define("freqframe", MFrequency::showType(freqframe)); // Convert MFrequency::Types to String
    1827             :     //looks like fromRecord looks for outframe !
    1828        2086 :     selpar.define("outframe", MFrequency::showType(freqframe)); 
    1829        2086 :     selpar.define("field",field);
    1830        2086 :     selpar.define("antenna",antenna);
    1831        2086 :     selpar.define("timestr",timestr);
    1832        2086 :     selpar.define("scan",scan);
    1833        2086 :     selpar.define("obs",obs);
    1834        2086 :     selpar.define("state",state);
    1835        2086 :     selpar.define("uvdist",uvdist);
    1836        2086 :     selpar.define("taql",taql);
    1837        2086 :     selpar.define("usescratch",usescratch);
    1838        2086 :     selpar.define("readonly",readonly);
    1839        2086 :     selpar.define("incrmodel",incrmodel);
    1840        2086 :     selpar.define("datacolumn",datacolumn);
    1841             : 
    1842        2086 :     return selpar;
    1843           0 :   }
    1844             : 
    1845             : 
    1846             :   /////////////////////// Image Parameters
    1847             : 
    1848        5551 :   SynthesisParamsImage::SynthesisParamsImage():SynthesisParams()
    1849             :   {
    1850        5551 :     setDefaults();
    1851        5551 :   }
    1852             : 
    1853        5550 :   SynthesisParamsImage::~SynthesisParamsImage()
    1854             :   {
    1855        5550 :   }
    1856             : 
    1857        3719 :   SynthesisParamsImage& SynthesisParamsImage::operator=(const SynthesisParamsImage& other){
    1858        3719 :     if(this != &other){
    1859        3719 :       imageName=other.imageName;
    1860        3719 :       stokes=other.stokes;
    1861        3719 :       startModel.resize(); startModel=other.startModel;
    1862        3719 :       imsize.resize(); imsize=other.imsize;
    1863        3719 :       cellsize.resize(); cellsize=other.cellsize;
    1864        3719 :       projection=other.projection;
    1865        3719 :       useNCP=other.useNCP;
    1866        3719 :       phaseCenter=other.phaseCenter;
    1867        3719 :       phaseCenterFieldId=other.phaseCenterFieldId;
    1868        3719 :       obslocation=other.obslocation;
    1869        3719 :       pseudoi=other.pseudoi;
    1870        3719 :       nchan=other.nchan;
    1871        3719 :       nTaylorTerms=other.nTaylorTerms;
    1872        3719 :       chanStart=other.chanStart;
    1873        3719 :       chanStep=other.chanStep;
    1874        3719 :       freqStart=other.freqStart;
    1875        3719 :       freqStep=other.freqStep;
    1876        3719 :       refFreq=other.refFreq;
    1877        3719 :       velStart=other.velStart;
    1878        3719 :       velStep=other.velStep;
    1879        3719 :       freqFrame=other.freqFrame;
    1880        3719 :       mFreqStart=other.mFreqStart;
    1881        3719 :       mFreqStep=other.mFreqStep;
    1882        3719 :       mVelStart=other.mVelStart;
    1883        3719 :       mVelStep=other.mVelStep;
    1884        3719 :       restFreq.resize(); restFreq=other.restFreq;
    1885        3719 :       start=other.start;
    1886        3719 :       step=other.step;
    1887        3719 :       frame=other.frame;
    1888        3719 :       veltype=other.veltype;
    1889        3719 :       mode=other.mode;
    1890        3719 :       reffreq=other.reffreq;
    1891        3719 :       sysvel=other.sysvel;
    1892        3719 :       sysvelframe=other.sysvelframe;
    1893        3719 :       sysvelvalue=other.sysvelvalue;
    1894        3719 :       qmframe=other.qmframe;
    1895        3719 :       mveltype=other.mveltype;
    1896        3719 :       tststr=other.tststr;
    1897        3719 :       startRecord=other.startRecord;
    1898        3719 :       stepRecord=other.stepRecord;
    1899        3719 :       reffreqRecord=other.reffreqRecord;
    1900        3719 :       sysvelRecord=other.sysvelRecord;
    1901        3719 :       restfreqRecord=other.restfreqRecord;
    1902        3719 :       csysRecord=other.csysRecord;
    1903        3719 :       csys=other.csys;
    1904        3719 :       imshape.resize(); imshape=other.imshape;
    1905        3719 :       freqFrameValid=other.freqFrameValid;
    1906        3719 :       overwrite=other.overwrite;
    1907        3719 :       deconvolver=other.deconvolver;
    1908        3719 :       distance=other.distance;
    1909        3719 :       trackDir=other.trackDir;
    1910        3719 :       trackSource=other.trackSource;
    1911        3719 :       movingSource=other.movingSource;
    1912             : 
    1913             : 
    1914             : 
    1915             :     }
    1916             : 
    1917        3719 :     return *this;
    1918             : 
    1919             :   }
    1920             : 
    1921        1687 :   void SynthesisParamsImage::fromRecord(const casacore::Record &inrec) {
    1922        1687 :     fromRecord(inrec, False);
    1923        1686 :   }
    1924             : 
    1925        1847 :   void SynthesisParamsImage::fromRecord(const casacore::Record &inrec,
    1926             :                                         const casacore::Bool isSingleDish) {
    1927        1847 :     setDefaults();
    1928        1847 :     String err("");
    1929        3694 :     LogIO os(LogOrigin("SynthesisParamsImage", "fromRecord"));
    1930             : 
    1931             :     try {
    1932        1847 :       err += readVal(inrec, String("imagename"), imageName);
    1933             : 
    1934             :       //// imsize
    1935        1847 :       if (inrec.isDefined("imsize")) {
    1936        1847 :         DataType tp = inrec.dataType("imsize");
    1937        1847 :         if (tp == TpInt) { // A single integer for both dimensions.
    1938             :           Int npix;
    1939         742 :           inrec.get("imsize", npix);
    1940         742 :           imsize.resize(2);
    1941         742 :           imsize.set(npix);
    1942        1105 :         } else if (tp == TpArrayInt) { // An integer array : [ nx ] or [ nx, ny ]
    1943        1105 :           Vector<Int> ims;
    1944        1105 :           inrec.get("imsize", ims);
    1945        1105 :           if (ims.nelements() == 1) { // [ nx ]
    1946          47 :             imsize.set(ims[0]);
    1947        1058 :           } else if (ims.nelements() == 2) { // [ nx, ny ]
    1948        1058 :             imsize[0] = ims[0];
    1949        1058 :             imsize[1] = ims[1];
    1950             :           } else { // [ nx, ny ]
    1951           0 :             err += "imsize must be either a single integer, or a vector of two integers\n";
    1952             :           }
    1953        1105 :         } else { // Wrong data type
    1954           0 :           err += "imsize must be either a single integer, or a vector of two integers\n";
    1955             :         }
    1956             :       } //imsize
    1957             : 
    1958             :         //// cellsize
    1959        1847 :       if (inrec.isDefined("cell")) {
    1960             :         try {
    1961        1847 :           DataType tp = inrec.dataType("cell");
    1962        1847 :           if (tp == TpInt ||
    1963        1847 :               tp == TpFloat ||
    1964             :               tp == TpDouble) {
    1965          11 :             Double cell = inrec.asDouble("cell");
    1966          11 :             cellsize.set(Quantity(cell, "arcsec"));
    1967        1847 :           } else if (tp == TpArrayInt ||
    1968        1836 :                     tp == TpArrayFloat ||
    1969             :                     tp == TpArrayDouble) {
    1970           1 :             Vector<Double> cells;
    1971           1 :             inrec.get("cell", cells);
    1972           1 :             if (cells.nelements() == 1) { // [ cellx ]
    1973           0 :               cellsize.set(Quantity(cells[0], "arcsec"));
    1974           1 :             } else if (cells.nelements() == 2) { // [ cellx, celly ]
    1975           1 :               cellsize[0] = Quantity(cells[0], "arcsec");
    1976           1 :               cellsize[1] = Quantity(cells[1], "arcsec");
    1977             :             } else { // Wrong array length
    1978           0 :               err += "cellsize must be a single integer/string, or a vector of two integers/strings\n";
    1979             :             }
    1980        1836 :           } else if (tp == TpString) {
    1981         835 :             String cell;
    1982         835 :             inrec.get("cell", cell);
    1983         835 :             Quantity qcell;
    1984         835 :             err += stringToQuantity(cell, qcell);
    1985         835 :             cellsize.set(qcell);
    1986        1835 :           } else if (tp == TpArrayString) {
    1987        1000 :             Array<String> cells;
    1988        1000 :             inrec.get("cell", cells);
    1989        1000 :             Vector<String> vcells(cells);
    1990        1000 :             if (cells.nelements() == 1) { // [ cellx ]
    1991          12 :               Quantity qcell;
    1992          12 :               err += stringToQuantity(vcells[0], qcell);
    1993          12 :               cellsize.set(qcell);
    1994        1000 :             } else if (cells.nelements() == 2) { // [ cellx, celly ]
    1995         988 :               err += stringToQuantity(vcells[0], cellsize[0]);
    1996         988 :               err += stringToQuantity(vcells[1], cellsize[1]);
    1997             :             } else { // Wrong array length
    1998           0 :               err += "cellsize must be a single integer/string, or a vector of two integers/strings\n";
    1999             :             }
    2000        1000 :           } else { // Wrong data type
    2001           0 :             err += "cellsize must be a single integer/string, or a vector of two integers/strings\n";
    2002             :           }
    2003           0 :         } catch (AipsError &x) {
    2004           0 :           err += "Error reading cellsize : " + x.getMesg();
    2005           0 :         }
    2006             :       } // cellsize
    2007             : 
    2008             :         //// stokes
    2009        1847 :       err += readVal(inrec, String("stokes"), stokes);
    2010        1847 :       if (stokes.matches("pseudoI")) {
    2011           1 :         stokes = "I";
    2012           1 :         pseudoi = true;
    2013             :       } else {
    2014        1846 :         pseudoi = false;
    2015             :       }
    2016             : 
    2017             :       /// PseudoI
    2018             : 
    2019             :       ////nchan
    2020        1847 :       err += readVal(inrec, String("nchan"), nchan);
    2021             : 
    2022             :       /// phaseCenter (as a string) . // Add INT support later.
    2023             :       //err += readVal( inrec, String("phasecenter"), phaseCenter );
    2024        1847 :       if (inrec.isDefined("phasecenter")) {
    2025        1847 :         String pcent("");
    2026        1847 :         if (inrec.dataType("phasecenter") == TpString) {
    2027        1821 :           inrec.get("phasecenter", pcent);
    2028        1821 :           if (pcent.length() > 0) { // if it's zero length, it means 'figure out from first field in MS'.
    2029        1249 :             err += readVal(inrec, String("phasecenter"), phaseCenter);
    2030        1249 :             phaseCenterFieldId = -1;
    2031             :             //// Phase Center Field ID.... if explicitly specified, and not via phasecenter.
    2032             :             //   Need this, to deal with a null phase center being translated to a string to go back out.
    2033        1249 :             err += readVal(inrec, String("phasecenterfieldid"), phaseCenterFieldId);
    2034             :           } else {
    2035         572 :             phaseCenterFieldId = -2; // deal with this later in buildCoordinateSystem to assign the first selected field 
    2036             :           }
    2037             :         }
    2038        1847 :         if (inrec.dataType("phasecenter") == TpInt   ||
    2039        5515 :             inrec.dataType("phasecenter") == TpFloat ||
    2040        3668 :             inrec.dataType("phasecenter") == TpDouble) {
    2041             :           // This will override the previous setting to 0 if the phaseCenter string is zero length.
    2042          26 :           err += readVal(inrec, String("phasecenter"), phaseCenterFieldId);
    2043             :         }
    2044        1873 :         if ((inrec.dataType("phasecenter") != TpString && inrec.dataType("phasecenter") != TpInt
    2045        1873 :             && inrec.dataType("phasecenter") != TpFloat && inrec.dataType("phasecenter") != TpDouble)) {
    2046           0 :           err += String("Cannot set phasecenter. Please specify a string or int\n");
    2047             :         }
    2048        1847 :       }
    2049             : 
    2050             :       //// Projection
    2051        1847 :       if (inrec.isDefined("projection")) {
    2052        1847 :           if (inrec.dataType("projection") == TpString) {
    2053        1847 :               String pstr;
    2054        1847 :               inrec.get("projection", pstr);
    2055             :               try {
    2056        1847 :                   if (pstr.matches("NCP")) {
    2057           1 :                       pstr = "SIN";
    2058           1 :                       useNCP = true;
    2059             :                   }
    2060        1847 :                   projection = Projection::type(pstr);
    2061           0 :               } catch (AipsError &x) {
    2062           0 :                   err += String("Invalid projection code : " + pstr);
    2063           0 :               }
    2064        1847 :           } else {
    2065           0 :               err += "projection must be a string\n";
    2066             :           }
    2067             :       } //projection
    2068             : 
    2069             :       // Frequency frame stuff. 
    2070        1847 :       err += readVal(inrec, String("specmode"), mode);
    2071             :       // Alias for 'mfs' is 'cont'
    2072        1847 :       if (mode == "cont") mode = "mfs";
    2073             : 
    2074        1847 :       err += readVal(inrec, String("outframe"), frame);
    2075        1847 :       qmframe = "";
    2076             :       // mveltype is only set when start/step is given in mdoppler
    2077        1847 :       mveltype = "";
    2078             :       //start 
    2079        1847 :       String startType("");
    2080        1847 :       String widthType("");
    2081        1847 :       if (inrec.isDefined("start")) {
    2082        1847 :         if (inrec.dataType("start") == TpInt) {
    2083         239 :           err += readVal(inrec, String("start"), chanStart);
    2084         239 :           start = String::toString(chanStart);
    2085         239 :           startType = "chan";
    2086        1608 :         } else if (inrec.dataType("start") == TpString) {
    2087        1573 :             err += readVal(inrec, String("start"), start);
    2088        1573 :             if (start.contains("Hz")) {
    2089         157 :               stringToQuantity(start, freqStart);
    2090         157 :               startType = "freq";
    2091        1416 :             } else if (start.contains("m/s")) {
    2092          46 :               stringToQuantity(start, velStart);
    2093          46 :               startType = "vel";
    2094             :             }
    2095          35 :         } else if (inrec.dataType("start") == TpRecord) {
    2096             :             //record can be freq in Quantity or MFreaquency or vel in Quantity or
    2097             :             //MRadialVelocity or Doppler (by me.todoppler())
    2098             :             // ** doppler => converted to radialvel with frame 
    2099          35 :             startRecord = inrec.subRecord("start");
    2100          35 :             if (startRecord.isDefined("m0")) {
    2101             :               //must be a measure
    2102          21 :               String mtype;
    2103          21 :               startRecord.get("type", mtype);
    2104          21 :               if (mtype == "frequency") {
    2105             :                 //mfrequency
    2106           7 :                 startRecord.get(String("refer"), qmframe);
    2107           7 :                 if (frame != "" && frame != qmframe) {
    2108             :                   // should emit warning to the logger
    2109           0 :                   cerr << "The frame in start:" << qmframe << " Override frame=" << frame << endl;
    2110             :                 }
    2111           7 :                 start = recordQMToString(startRecord);
    2112           7 :                 stringToQuantity(start, freqStart);
    2113           7 :                 startType = "freq";
    2114          14 :               } else if (mtype == "radialvelocity") {
    2115             :                 //mradialvelocity
    2116           7 :                 startRecord.get(String("refer"), qmframe);
    2117           7 :                 if (frame != "" && frame != qmframe) {
    2118             :                   // should emit warning to the logger
    2119           7 :                   cerr << "The frame in start:" << qmframe << " Override frame=" << frame << endl;
    2120             :                 }
    2121           7 :                 start = recordQMToString(startRecord);
    2122           7 :                 stringToQuantity(start, velStart);
    2123           7 :                 startType = "vel";
    2124           7 :               } else if (mtype == "doppler") {
    2125             :                   //use veltype in mdoppler
    2126             :                   //start = MDopToVelString(startRecord);
    2127           7 :                   start = recordQMToString(startRecord);
    2128           7 :                   stringToQuantity(start, velStart);
    2129           7 :                   startRecord.get(String("refer"), mveltype);
    2130           7 :                   mveltype.downcase();
    2131           7 :                   startType = "vel";
    2132             :               }
    2133          21 :             } else {
    2134          14 :                 start = recordQMToString(startRecord);
    2135          14 :                 if (start.contains("Hz")) {
    2136           7 :                     stringToQuantity(start, freqStart);
    2137           7 :                     startType = "freq";
    2138           7 :                 } else if (start.contains("m/s")) {
    2139           7 :                     stringToQuantity(start, velStart);
    2140           7 :                     startType = "vel";
    2141             :                 } else {
    2142           0 :                     err += String("Unrecognized Quantity unit for start, must contain m/s or Hz\n");
    2143             :                 }
    2144             :             }
    2145             :         } else {
    2146           0 :             err += String("start must be an integer, a string, or frequency/velocity in Quantity/Measure\n");
    2147             :         }
    2148             :       }
    2149             : 
    2150             :         //step
    2151        1847 :       if (inrec.isDefined("width")) {
    2152        1847 :         if (inrec.dataType("width") == TpInt) {
    2153         206 :           err += readVal(inrec, String("width"), chanStep);
    2154         206 :           step = String::toString(chanStep);
    2155         206 :           widthType = "chan";
    2156        1641 :         } else if (inrec.dataType("width") == TpString) {
    2157        1627 :           err += readVal(inrec, String("width"), step);
    2158        1627 :           if (step.contains("Hz")) {
    2159         142 :             stringToQuantity(step, freqStep);
    2160         142 :             widthType = "freq";
    2161        1485 :           } else if (step.contains("m/s")) {
    2162          50 :             stringToQuantity(step, velStep);
    2163          50 :             widthType = "vel";
    2164             :           }
    2165          14 :         } else if (inrec.dataType("width") == TpRecord) {
    2166             :           //record can be freq in Quantity or MFreaquency or vel in Quantity or
    2167             :           //MRadialVelocity or Doppler (by me.todoppler())
    2168             :           // ** doppler => converted to radialvel with frame 
    2169          14 :           stepRecord = inrec.subRecord("width");
    2170          14 :           if (stepRecord.isDefined("m0")) {
    2171             :             //must be a measure
    2172           7 :             String mtype;
    2173           7 :             stepRecord.get("type", mtype);
    2174           7 :             if (mtype == "frequency") {
    2175             :               //mfrequency
    2176           0 :               stepRecord.get(String("refer"), qmframe);
    2177           0 :               if (frame != "" && frame != qmframe) {
    2178             :                 // should emit warning to the logger
    2179           0 :                 cerr << "The frame in step:" << qmframe << " Override frame=" << frame << endl;
    2180             :               }
    2181           0 :               step = recordQMToString(stepRecord);
    2182           0 :               stringToQuantity(step, freqStep);
    2183           0 :               widthType = "freq";
    2184           7 :             } else if (mtype == "radialvelocity") {
    2185             :               //mradialvelocity
    2186           7 :               stepRecord.get(String("refer"), qmframe);
    2187           7 :               if (frame != "" && frame != qmframe) {
    2188             :                 // should emit warning to the logger
    2189           0 :                 cerr << "The frame in step:" << qmframe << " Override frame=" << frame << endl;
    2190             :               }
    2191           7 :               step = recordQMToString(stepRecord);
    2192           7 :               stringToQuantity(step, velStep);
    2193           7 :               widthType = "vel";
    2194           0 :             } else if (mtype == "doppler") {
    2195             :               //step = MDopToVelString(stepRecord);
    2196           0 :               step = recordQMToString(stepRecord);
    2197           0 :               stringToQuantity(step, velStep);
    2198           0 :               startRecord.get(String("refer"), mveltype);
    2199           0 :               mveltype.downcase();
    2200           0 :               widthType = "vel";
    2201             :             }
    2202           7 :           } else {
    2203           7 :             step = recordQMToString(stepRecord);
    2204           7 :             if (step.contains("Hz")) {
    2205           0 :               stringToQuantity(step, freqStep);
    2206           0 :               widthType = "freq";
    2207           7 :             } else if (step.contains("m/s")) {
    2208           7 :               stringToQuantity(step, velStep);
    2209           7 :               widthType = "vel";
    2210             :             } else {
    2211           0 :               err += String("Unrecognized Quantity unit for step, must contain m/s or Hz\n");
    2212             :             }
    2213             :           }
    2214             :         } else {
    2215           0 :           err += String("step must be an integer, a string, or frequency/velocity in Quantity/Measure\n");
    2216             :         }
    2217             :       }
    2218             : 
    2219             :       //check for start, width unit consistentcy
    2220        1847 :       if (startType != widthType && startType != "" && widthType != "") {
    2221           0 :         err += String("Cannot mix start and width with different unit types (e.g. km/s vs. Hz)\n");
    2222             :       }
    2223             : 
    2224             :       //reffreq (String, Quantity, or Measure)
    2225        1847 :       if (inrec.isDefined("reffreq")) {
    2226        1847 :         if (inrec.dataType("reffreq") == TpString) {
    2227        1847 :           err += readVal(inrec, String("reffreq"), refFreq);
    2228           0 :         } else if (inrec.dataType("reffreq") == TpRecord) {
    2229           0 :           String reffreqstr;
    2230           0 :           reffreqRecord = inrec.subRecord("reffreq");
    2231           0 :           if (reffreqRecord.isDefined("m0")) {
    2232           0 :             String mtype;
    2233           0 :             reffreqRecord.get("type", mtype);
    2234           0 :             if (mtype == "frequency") {
    2235           0 :               reffreqstr = recordQMToString(reffreqRecord);
    2236           0 :               stringToQuantity(reffreqstr, refFreq);
    2237             :             } else {
    2238           0 :               err += String("Unrecognized Measure for reffreq, must be a frequency measure\n");
    2239             :             }
    2240           0 :           } else {
    2241           0 :             reffreqstr = recordQMToString(reffreqRecord);
    2242           0 :             if (reffreqstr.contains("Hz")) {
    2243           0 :               stringToQuantity(reffreqstr, refFreq);
    2244             :             } else {
    2245           0 :               err += String("Unrecognized Quantity unit for reffreq, must contain Hz\n");
    2246             :             }
    2247             :           }
    2248           0 :         } else {
    2249           0 :           err += String("reffreq must be a string, or frequency in Quantity/Measure\n");
    2250             :         }
    2251             :       }
    2252             : 
    2253        1847 :       err += readVal(inrec, String("veltype"), veltype);
    2254        1847 :       veltype = mveltype != "" ? mveltype : veltype;
    2255             :       // sysvel (String, Quantity)
    2256        1847 :       if (inrec.isDefined("sysvel")) {
    2257        1847 :         if (inrec.dataType("sysvel") == TpString) {
    2258        1847 :           err += readVal(inrec, String("sysvel"), sysvel);
    2259           0 :         } else if (inrec.dataType("sysvel") == TpRecord) {
    2260           0 :           sysvelRecord = inrec.subRecord("sysvel");
    2261           0 :           sysvel = recordQMToString(sysvelRecord);
    2262           0 :           if (sysvel == "" || !sysvel.contains("m/s")) {
    2263           0 :             err += String("Unrecognized Quantity unit for sysvel, must contain m/s\n");
    2264             :           }
    2265             :         } else {
    2266           0 :           err += String("sysvel must be a string, or velocity in Quantity\n");
    2267             :         }
    2268             :       }
    2269        1847 :       err += readVal(inrec, String("sysvelframe"), sysvelframe);
    2270             : 
    2271             :       // rest frequencies (record or vector of Strings)
    2272        1847 :       if (inrec.isDefined("restfreq")) {
    2273        1847 :         Vector<String> rfreqs(0);
    2274        1847 :         Record restfreqSubRecord;
    2275        1847 :         if (inrec.dataType("restfreq") == TpRecord) {
    2276           0 :           restfreqRecord = inrec.subRecord("restfreq");
    2277             :           // assume multiple restfreqs are index as '0','1'..
    2278           0 :           if (restfreqRecord.isDefined("0")) {
    2279           0 :             rfreqs.resize(restfreqRecord.nfields());
    2280           0 :             for (uInt fr = 0; fr < restfreqRecord.nfields(); fr++) {
    2281           0 :               restfreqSubRecord = restfreqRecord.subRecord(String::toString(fr));
    2282           0 :               rfreqs[fr] = recordQMToString(restfreqSubRecord);
    2283             :             }
    2284             :           }
    2285        1847 :         } else if (inrec.dataType("restfreq") == TpArrayString) {
    2286         967 :           err += readVal(inrec, String("restfreq"), rfreqs);
    2287         880 :         } else if (inrec.dataType("restfreq") == TpString) {
    2288           7 :           rfreqs.resize(1);
    2289           7 :           err += readVal(inrec, String("restfreq"), rfreqs[0]);
    2290             :         }
    2291        1847 :         restFreq.resize(rfreqs.nelements());
    2292        2107 :         for (uInt fr = 0; fr < rfreqs.nelements(); fr++) {
    2293         260 :           err += stringToQuantity(rfreqs[fr], restFreq[fr]);
    2294             :         }
    2295        1847 :       } // if def restfreq
    2296             : 
    2297             :       // optional - coordsys, imshape
    2298             :       // if exist use them. May need a consistency check with the rest of impars?
    2299        1847 :       if (inrec.isDefined("csys")) {
    2300             :         //            cout<<"HAS CSYS KEY - got from input record"<<endl;
    2301         899 :         if (inrec.dataType("csys") == TpRecord) {
    2302             :           //csysRecord = inrec.subRecord("csys");
    2303         899 :           csysRecord.defineRecord("coordsys", inrec.subRecord("csys"));
    2304             :         }
    2305         899 :         if (inrec.isDefined("imshape")) {
    2306         899 :           if (inrec.dataType("imshape") == TpArrayInt) {
    2307         899 :             err += readVal(inrec, String("imshape"), imshape);
    2308             :           }
    2309             :         }
    2310             :       }
    2311             : 
    2312             :       //String freqframestr( MFrequency::showType(freqFrame) );
    2313             :       //err += readVal( inrec, String("outframe"), freqframestr);
    2314             :       //if( ! MFrequency::getType(freqFrame, freqframestr) )
    2315             :       //  { err += "Invalid Frequency Frame " + freqframestr ; }
    2316             : 
    2317        1847 :       String freqframestr = (frame != "" && qmframe != "") ? qmframe : frame;
    2318        1847 :       if (frame != "" && !MFrequency::getType(freqFrame, freqframestr)) {
    2319           1 :         err += "Invalid Frequency Frame " + freqframestr;
    2320             :       }
    2321        1847 :       err += readVal(inrec, String("restart"), overwrite);
    2322             : 
    2323        1847 :       err += readVal(inrec, String("freqframevalid"), freqFrameValid);
    2324             :       // startmodel parsing copied in SynthesisParamDeconv. Clean this up !!! 
    2325        1847 :       if (inrec.isDefined("startmodel")) {
    2326        1847 :         if (inrec.dataType("startmodel") == TpString) {
    2327         941 :           String onemodel;
    2328         941 :           err += readVal(inrec, String("startmodel"), onemodel);
    2329         941 :           if (onemodel.length() > 0) {
    2330          16 :             startModel.resize(1);
    2331          16 :             startModel[0] = onemodel;
    2332             :           } else {
    2333         925 :             startModel.resize();
    2334             :           }
    2335        2754 :         } else if (inrec.dataType("startmodel") == TpArrayString ||
    2336         907 :                     inrec.dataType("startmodel") == TpArrayBool) {
    2337         906 :           err += readVal(inrec, String("startmodel"), startModel);
    2338             :         } else {
    2339           0 :           err += String("startmodel must be either a string(singleterm) or a list of strings(multiterm)\n");
    2340             :         }
    2341             :       }
    2342             : 
    2343        1847 :       err += readVal(inrec, String("nterms"), nTaylorTerms);
    2344        1847 :       err += readVal(inrec, String("deconvolver"), deconvolver);
    2345             : 
    2346             :       // Force nchan=1 for anything other than cube modes...
    2347        1847 :       if (mode == "mfs") nchan = 1;
    2348             :       //read obslocation
    2349        1847 :       if (inrec.isDefined("obslocation_rec")) {
    2350         899 :         String errorobs;
    2351         899 :         const Record obsrec = inrec.asRecord("obslocation_rec");
    2352         899 :         MeasureHolder mh;
    2353         899 :         if (!mh.fromRecord(errorobs, obsrec)) {
    2354           0 :           err += errorobs;
    2355             :         }
    2356         899 :         obslocation = mh.asMPosition();
    2357         899 :       }
    2358        1847 :       err += verify(isSingleDish);
    2359        1847 :     }
    2360           0 :     catch (AipsError &x) {
    2361           0 :       err = err + x.getMesg() + "\n";
    2362           0 :     }
    2363             : 
    2364        1847 :     if (err.length() > 0) throw(AipsError("Invalid Image Parameter set : " + err));
    2365        1851 :   }
    2366             : 
    2367           0 :   String SynthesisParamsImage::MDopToVelString(Record &rec)
    2368             :   {
    2369           0 :     if( rec.isDefined("type") ) {
    2370           0 :       String measType;
    2371           0 :       String unit;
    2372           0 :       Double val = 0;
    2373           0 :       rec.get("type", measType);
    2374           0 :       if(measType=="doppler") {
    2375           0 :         rec.get(String("refer"), mveltype);
    2376           0 :         Record dopRecord = rec.subRecord("m0");
    2377           0 :         String dopstr = recordQMToString(dopRecord);
    2378             :         //cerr<<"dopstr="<<dopstr<<endl;
    2379             :         MRadialVelocity::Types mvType;
    2380             :         //use input frame
    2381           0 :         qmframe = frame!=""? frame: "LSRK";
    2382           0 :         MRadialVelocity::getType(mvType, qmframe);
    2383             :         MDoppler::Types mdType;
    2384           0 :         MDoppler::getType(mdType, mveltype);
    2385           0 :         MDoppler dop(Quantity(val,unit), mdType);
    2386           0 :         MRadialVelocity mRadVel(MRadialVelocity::fromDoppler(dop, mvType));
    2387           0 :         Double velval = mRadVel.get("m/s").getValue();
    2388           0 :         return start = String::toString(velval) + String("m/s");
    2389           0 :       }
    2390           0 :       else { return String("");}
    2391           0 :     }
    2392           0 :     else { return String("");}
    2393             :   }
    2394             : 
    2395           0 :   String SynthesisParamsImage::verify() const
    2396             :   {
    2397           0 :     verify(False);
    2398           0 :   }
    2399             : 
    2400        1847 :   String SynthesisParamsImage::verify(const casacore::Bool isSingleDish) const
    2401             :   {
    2402        1847 :     LogIO os;
    2403        1847 :     String err;
    2404             : 
    2405        1847 :     if(imageName=="") {err += "Please supply an image name\n";}
    2406             : 
    2407        1847 :     if(imsize.nelements() != 2){err += "imsize must be a vector of 2 Ints\n";}
    2408        1847 :     if(cellsize.nelements() != 2) {err += "cellsize must be a vector of 2 Quantities\n";}
    2409        1847 :     if(cellsize[0].getValue() == 0.0 || cellsize[1].getValue() == 0.0){
    2410           1 :         err += "cellsize must be nonzero\n";
    2411             :     }
    2412             : 
    2413             :     //// default is nt=2 but deconvolver != mtmfs by default.
    2414             :     //    if( nchan>1 and nTaylorTerms>1 )
    2415             :     //  {err += "Cannot have more than one channel with ntaylorterms>1\n";}
    2416             : 
    2417        1847 :     if((mode=="mfs") && nchan > 1){
    2418           0 :       err += "specmode=mfs cannot have nchan="+String::toString(nchan)+" (must be 1)\n";
    2419             :     }
    2420             : 
    2421        2073 :     if(! stokes.matches("I") && ! stokes.matches("Q") && 
    2422         215 :        ! stokes.matches("U") && ! stokes.matches("V") && 
    2423         153 :        ! stokes.matches("RR") && ! stokes.matches("LL") && 
    2424         153 :        ! stokes.matches("XX") && ! stokes.matches("YY") && 
    2425         151 :        ! stokes.matches("IV") && ! stokes.matches("IQ") && 
    2426         140 :        ! stokes.matches("RRLL") && ! stokes.matches("XXYY") &&
    2427         138 :        ! stokes.matches("QU") && ! stokes.matches("UV") && 
    2428        2201 :        ! stokes.matches("IQU") && ! stokes.matches("IUV") && 
    2429         128 :        ! stokes.matches("IQUV")){
    2430             : 
    2431           0 :       err += "Stokes " + stokes + " is an unsupported option \n";
    2432             :     }
    2433             : 
    2434             :     ///    err += verifySpectralSetup();  
    2435             : 
    2436             :     // Allow only one starting model. No additions to be done.
    2437        1847 :     if(startModel.nelements()>0){
    2438          22 :       if(deconvolver!="mtmfs"){
    2439             : 
    2440          16 :         if( startModel.nelements()!=1 ){
    2441           0 :           err += String("Only one startmodel image is allowed.\n");
    2442             :         }
    2443             :         else{
    2444          32 :           File fp(imageName+String(".model"));
    2445          16 :           if(fp.exists()) err += "Model " + imageName+".model exists, but a starting model of " + startModel[0] + " is also being requested. Please either reset startmodel='' to use what already exists, or delete " + imageName + ".model so that it uses the new model specified in startmodel.";
    2446          16 :         }
    2447             :       }
    2448             :       else{// mtmfs
    2449          12 :         File fp(imageName+String(".model.tt0")); 
    2450           6 :         if(fp.exists()){
    2451           0 :           err += "Model " + imageName+".model.tt* exists, but a starting model of ";
    2452           0 :           for (uInt i=0;i<startModel.nelements();i++){err += startModel[i] + ",";}
    2453           0 :           err +=" is also being requested. Please either reset startmodel='' to use what already exists, or delete " + imageName + ".model.tt* so that it uses the new model specified in startmodel";
    2454             :         }
    2455           6 :       }
    2456             : 
    2457             :       // Check that startmodel exists on disk !
    2458          49 :       for(uInt ss=0;ss<startModel.nelements();ss++){
    2459          27 :         File fp( startModel[ss] );
    2460          27 :         if(!fp.exists()){
    2461           0 :           err += "Startmodel " + startModel[ss] + " cannot be found on disk.";
    2462             :         }
    2463          27 :       }
    2464             :     }
    2465             : 
    2466             :     /// Check imsize for efficiency.
    2467        1847 :     Int imxnew = SynthesisUtilMethods::getOptimumSize(imsize[0]);
    2468        1847 :     Int imynew = SynthesisUtilMethods::getOptimumSize(imsize[1]);
    2469        1847 :     if((imxnew != imsize[0] || imynew != imsize[1]) && isSingleDish == False){
    2470          18 :       LogIO os(LogOrigin("SynthesisParamsImage","fromRecord",WHERE));
    2471           9 :       if( imxnew != imsize[0] ) {
    2472           2 :         os << LogIO::WARN << "imsize with "+String::toString(imsize[0])+
    2473           2 :         " pixels is not an efficient imagesize. Try "+
    2474           3 :         String::toString(imxnew)+" instead." << LogIO::POST;
    2475             :       }
    2476           9 :       if( imsize[0] != imsize[1] && imynew != imsize[1] ){
    2477          16 :         os << LogIO::WARN << "imsize with "+String::toString(imsize[1])+
    2478          16 :         " pixels is not an efficient imagesize. Try "+
    2479          24 :         String::toString(imynew)+" instead." << LogIO::POST;
    2480             :       }
    2481           9 :     }
    2482        3694 :     return err;
    2483        1847 :   }// verify()
    2484             : 
    2485             :   /*  
    2486             :   // Convert all user options to  LSRK freqStart, freqStep, 
    2487             :   // Could have (optional) log messages coming out of this function, to tell the user what the
    2488             :   // final frequency setup is ?
    2489             : 
    2490             :   String SynthesisParamsImage::verifySpectralSetup()
    2491             :   {
    2492             :   }
    2493             :   */
    2494             : 
    2495        7398 :   void SynthesisParamsImage::setDefaults()
    2496             :   {
    2497             :     // Image definition parameters
    2498        7398 :     imageName = String("");
    2499        7398 :     imsize.resize(2); imsize.set(100);
    2500        7398 :     cellsize.resize(2); cellsize.set( Quantity(1.0,"arcsec") );
    2501        7398 :     stokes="I";
    2502        7398 :     phaseCenter=MDirection();
    2503        7398 :     phaseCenterFieldId=-1;
    2504        7398 :     projection=Projection::SIN;
    2505        7398 :     useNCP=false;
    2506        7398 :     startModel=Vector<String>(0);
    2507        7398 :     freqFrameValid=True;
    2508        7398 :     overwrite=false;
    2509             :     // PseudoI
    2510        7398 :     pseudoi=false;
    2511             : 
    2512             :     // Spectral coordinates
    2513        7398 :     nchan=1;
    2514        7398 :     mode="mfs";
    2515        7398 :     start="";
    2516        7398 :     step="";
    2517        7398 :     chanStart=0;
    2518        7398 :     chanStep=1;
    2519             :     //freqStart=Quantity(0,"Hz");
    2520             :     //freqStep=Quantity(0,"Hz");
    2521             :     //velStart=Quantity(0,"m/s");
    2522             :     //velStep=Quantity(0,"m/s");
    2523        7398 :     freqStart=Quantity(0,"");
    2524        7398 :     freqStep=Quantity(0,"");
    2525        7398 :     velStart=Quantity(0,"");
    2526        7398 :     velStep=Quantity(0,"");
    2527        7398 :     veltype=String("radio");
    2528        7398 :     restFreq.resize(0);
    2529        7398 :     refFreq = Quantity(0,"Hz");
    2530        7398 :     frame = "";
    2531        7398 :     freqFrame=MFrequency::LSRK;
    2532        7398 :     sysvel="";
    2533        7398 :     sysvelframe="";
    2534        7398 :     sysvelvalue=Quantity(0.0,"m/s");
    2535        7398 :     nTaylorTerms=1;
    2536        7398 :     deconvolver="hogbom";
    2537             :     ///csysRecord=Record();
    2538        7398 :   }
    2539             : 
    2540         899 :   Record SynthesisParamsImage::toRecord() const
    2541             :   {
    2542         899 :     Record impar;
    2543         899 :     impar.define("imagename", imageName);
    2544         899 :     impar.define("imsize", imsize);
    2545         899 :     Vector<String> cells(2);
    2546         899 :     cells[0] = QuantityToString( cellsize[0] );
    2547         899 :     cells[1] = QuantityToString( cellsize[1] );
    2548         899 :     impar.define("cell", cells );
    2549         899 :     if(pseudoi==true){impar.define("stokes","pseudoI");}
    2550         899 :     else{impar.define("stokes", stokes);}
    2551         899 :     impar.define("nchan", nchan);
    2552         899 :     impar.define("nterms", nTaylorTerms);
    2553         899 :     impar.define("deconvolver",deconvolver);
    2554         899 :     impar.define("phasecenter", MDirectionToString( phaseCenter ) );
    2555         899 :     impar.define("phasecenterfieldid",phaseCenterFieldId);
    2556         899 :     impar.define("projection", (useNCP? "NCP" : projection.name()) );
    2557             : 
    2558         899 :     impar.define("specmode", mode );
    2559             :     // start and step can be one of these types
    2560         899 :     if( start!="" )
    2561             :       { 
    2562         299 :         if( !start.contains("Hz") && !start.contains("m/s") && 
    2563          65 :            String::toInt(start) == chanStart )
    2564             :           {
    2565          65 :             impar.define("start",chanStart); 
    2566             :           }
    2567         169 :         else if( startRecord.nfields() > 0 )
    2568             :           {
    2569          25 :             impar.defineRecord("start", startRecord ); 
    2570             :           }
    2571             :         else 
    2572             :           {
    2573         144 :             impar.define("start",start);
    2574             :         }
    2575             :       }
    2576             :     else { 
    2577         665 :         impar.define("start", start ); 
    2578             :       }
    2579         899 :     if( step!="" )
    2580             :       {
    2581         228 :         if( !step.contains("Hz") && !step.contains("m/s") && 
    2582          41 :            String::toInt(step) == chanStep )
    2583             :           {
    2584          41 :             impar.define("width", chanStep);
    2585             :           }
    2586         146 :         else if( stepRecord.nfields() > 0 )
    2587             :           { 
    2588          10 :             impar.defineRecord("width",stepRecord);
    2589             :           }
    2590             :         else
    2591             :           {
    2592         136 :             impar.define("width",step);
    2593             :           }
    2594             :       }
    2595             :     else 
    2596             :       { 
    2597         712 :         impar.define("width", step);
    2598             :       }
    2599             :     //impar.define("chanstart", chanStart );
    2600             :     //impar.define("chanstep", chanStep );
    2601             :     //impar.define("freqstart", QuantityToString( freqStart ));
    2602             :     //impar.define("freqstep", QuantityToString( freqStep ) );
    2603             :     //impar.define("velstart", QuantityToString( velStart ));
    2604             :     //impar.define("velstep", QuantityToString( velStep ) );
    2605         899 :     impar.define("veltype", veltype);
    2606         899 :     if (restfreqRecord.nfields() != 0 ) 
    2607             :       {
    2608           0 :         impar.defineRecord("restfreq", restfreqRecord);
    2609             :       }
    2610             :     else
    2611             :       {
    2612         899 :         Vector<String> rfs( restFreq.nelements() );
    2613        1084 :         for(uInt rf=0; rf<restFreq.nelements(); rf++){rfs[rf] = QuantityToString(restFreq[rf]);}
    2614         899 :         impar.define("restfreq", rfs);
    2615         899 :       }
    2616             :     //impar.define("reffreq", QuantityToString(refFreq));
    2617             :     //reffreq
    2618         899 :     if( reffreqRecord.nfields() != 0 )  
    2619           0 :       { impar.defineRecord("reffreq",reffreqRecord); }
    2620             :     else
    2621         899 :       { impar.define("reffreq",reffreq); }
    2622             :     //impar.define("reffreq", reffreq );
    2623             :     //impar.define("outframe", MFrequency::showType(freqFrame) );
    2624         899 :     impar.define("outframe", frame );
    2625             :     //sysvel
    2626         899 :     if( sysvelRecord.nfields() != 0 )
    2627           0 :       { impar.defineRecord("sysvel",sysvelRecord); } 
    2628             :     else
    2629         899 :       { impar.define("sysvel", sysvel );}
    2630         899 :     impar.define("sysvelframe", sysvelframe );
    2631             : 
    2632         899 :     impar.define("restart",overwrite );
    2633         899 :     impar.define("freqframevalid", freqFrameValid);
    2634         899 :     impar.define("startmodel", startModel );
    2635             : 
    2636         899 :     if( csysRecord.isDefined("coordsys") )
    2637             :       {
    2638             :         //        cout <<" HAS CSYS INFO.... writing to output record"<<endl;
    2639         899 :         impar.defineRecord("csys", csysRecord.subRecord("coordsys"));
    2640         899 :         impar.define("imshape", imshape);
    2641             :       } 
    2642             :     //    else cout << " NO CSYS INFO to write to output record " << endl;
    2643             :     ///Now save obslocation
    2644         899 :     Record tmprec;
    2645         899 :     String err;
    2646         899 :     MeasureHolder mh(obslocation);
    2647         899 :     if(mh.toRecord(err, tmprec)){
    2648         899 :       impar.defineRecord("obslocation_rec", tmprec);
    2649             :     }
    2650             :     else{
    2651           0 :       throw(AipsError("failed to save obslocation to record"));
    2652             :     }
    2653        1798 :     return impar;
    2654         899 :   }
    2655             : 
    2656             :   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2657             :   ///////////////////////////     Build a coordinate system.  ////////////////////////////////////////
    2658             :   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2659             :   ////   To be used from SynthesisImager, to construct the images it needs
    2660             :   ////   To also be connected to a 'makeimage' method of the synthesisimager tool.
    2661             :   ////       ( need to supply MS only to add  'ObsInfo' to the csys )
    2662             :   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2663             : 
    2664             :   
    2665             : 
    2666         945 :   CoordinateSystem SynthesisParamsImage::buildCoordinateSystem(vi::VisibilityIterator2& vi2, const std::map<Int, std::map<Int, Vector<Int> > >& chansel, Block<const MeasurementSet *> mss) 
    2667             : 
    2668             :   {
    2669             :     //vi2.getImpl()->spectralWindows( spwids );
    2670             :     //The above is not right
    2671             :     //////////// ///Kludge to find all spw selected
    2672             :     //std::vector<Int> pushspw;
    2673         945 :     vi::VisBuffer2* vb=vi2.getVisBuffer();
    2674         945 :     vi2.originChunks();
    2675         945 :     vi2.origin();
    2676             :     /// This version uses the new vi2/vb2
    2677             :     // get the first ms for multiple MSes
    2678             :     //MeasurementSet msobj=vi2.ms();
    2679         945 :     Int fld=vb->fieldId()(0);
    2680             : 
    2681             :         //handling first ms only
    2682         945 :         Double gfreqmax=-1.0;
    2683         945 :         Double gdatafend=-1.0;
    2684         945 :         Double gdatafstart=1e14;
    2685         945 :         Double gfreqmin=1e14;
    2686         945 :         Vector<Int> spwids0;
    2687         945 :         Int j=0;
    2688         945 :         Int minfmsid=0;
    2689             :         //for cube mode ,for a list of MSs, check ms to send to buildCoordSysCore contains start freq/vel
    2690         945 :         Double imStartFreq=getCubeImageStartFreq();
    2691         945 :         std::vector<Int> sourceMsWithStartFreq;
    2692             : 
    2693             :         
    2694        1954 :         for (auto forMS0=chansel.begin(); forMS0 !=chansel.end(); ++forMS0, ++j){
    2695             :     //auto forMS0=chansel.find(0);
    2696        1009 :           map<Int, Vector<Int> > spwsels=forMS0->second;
    2697        1009 :           Int nspws=spwsels.size();
    2698        1009 :           Vector<Int> spwids(nspws);
    2699        1009 :           Vector<Int> nChannels(nspws);
    2700        1009 :           Vector<Int> firstChannels(nspws);
    2701             :           //Vector<Int> channelIncrement(nspws);
    2702             :           
    2703        1009 :           Int k=0;
    2704        2315 :           for (auto it=spwsels.begin(); it != spwsels.end(); ++it, ++k){
    2705        1306 :             spwids[k]=it->first;
    2706        1306 :             nChannels[k]=(it->second)[0];
    2707        1306 :             firstChannels[k]=(it->second)[1];
    2708             :           }
    2709        1009 :           if(j==0) {
    2710         945 :       spwids0.resize();
    2711         945 :             spwids0=spwids;
    2712             :     }
    2713             :           // std::tie (spwids, nChannels, firstChannels, channelIncrement)=(static_cast<vi::VisibilityIteratorImpl2 * >(vi2.getImpl()))->getChannelInformation(false);
    2714             :           
    2715             :           //cerr << "SPWIDS "<< spwids <<  "  nchan " << nChannels << " firstchan " << firstChannels << endl;
    2716             :           
    2717             :           //////////////////This returns junk for multiple ms CAS-9994..so kludged up along with spw kludge
    2718             :           //Vector<Int> flds;
    2719             :           //vi2.getImpl()->fieldIds( flds );
    2720             :           //AlwaysAssert( flds.nelements()>0 , AipsError );
    2721             :           //fld = flds[0];
    2722        1009 :           Double freqmin=0, freqmax=0;
    2723        1009 :           freqFrameValid=(freqFrame != MFrequency::REST || mode=="cubesource");
    2724             :           
    2725             :           //MFrequency::Types dataFrame=(MFrequency::Types)vi2.subtableColumns().spectralWindow().measFreqRef()(spwids[0]);
    2726        1009 :           MFrequency::Types dataFrame=(MFrequency::Types)MSColumns(*mss[j]).spectralWindow().measFreqRef()(spwids[0]);
    2727             :           
    2728             :           Double datafstart, datafend;
    2729             :           //VisBufferUtil::getFreqRange(datafstart, datafend, vi2, dataFrame );
    2730             :           //cerr << std::setprecision(12) << "before " << datafstart << "   " << datafend << endl;
    2731        1009 :           Bool status=MSUtil::getFreqRangeInSpw( datafstart, datafend, spwids, firstChannels, nChannels,*mss[j], dataFrame,  True);
    2732             :           //cerr << "after " << datafstart << "   " << datafend << endl;
    2733        1009 :           if((datafstart > datafend) || !status)
    2734           0 :             throw(AipsError("spw selection failed")); 
    2735             :           //cerr << "datafstart " << datafstart << " end " << datafend << endl;
    2736             :           
    2737        1009 :           if (mode=="cubedata") {
    2738           2 :             freqmin = datafstart;
    2739           2 :             freqmax = datafend;
    2740             :           }
    2741        1007 :           else if(mode == "cubesource"){
    2742           5 :             if(!trackSource){
    2743           0 :               throw(AipsError("Cannot be in cubesource without tracking a moving source"));
    2744             :             }
    2745           5 :             String ephemtab(movingSource);
    2746           5 :             if(movingSource=="TRACKFIELD"){
    2747           3 :               Int fieldID=MSColumns(*mss[j]).fieldId()(0);
    2748           3 :               ephemtab=Path(MSColumns(*mss[j]).field().ephemPath(fieldID)).absoluteName();
    2749             :             }
    2750           5 :             MEpoch refep=MSColumns(*mss[j]).timeMeas()(0);
    2751           5 :             Quantity refsysvel;
    2752           5 :             MSUtil::getFreqRangeAndRefFreqShift(freqmin,freqmax,refsysvel, refep, spwids,firstChannels, nChannels, *mss[j], ephemtab, trackDir, true);
    2753           5 :             if(j==0)
    2754           5 :               sysvelvalue=refsysvel;
    2755             :             /*Double freqMinTopo, freqMaxTopo;
    2756             :             MSUtil::getFreqRangeInSpw( freqMinTopo, freqMaxTopo, spwids, firstChannels,
    2757             :                                        nChannels,*mss[j], freqFrameValid? MFrequency::TOPO:MFrequency::REST , True);
    2758             :             cerr << std::setprecision(10) << (freqmin-freqMinTopo) << "       "  << (freqmax-freqMaxTopo) << endl;
    2759             :             sysfreqshift=((freqmin-freqMinTopo)+(freqmax-freqMaxTopo))/2.0;
    2760             :             */
    2761           5 :           }
    2762             :           else {
    2763             :             //VisBufferUtil::getFreqRange(freqmin,freqmax, vi2, freqFrameValid? freqFrame:MFrequency::REST );
    2764             :             //cerr << "before " << freqmin << "   " << freqmax << endl;
    2765        2004 :             MSUtil::getFreqRangeInSpw( freqmin, freqmax, spwids, firstChannels,
    2766        2004 :                                        nChannels,*mss[j], freqFrameValid? freqFrame:MFrequency::REST , True);
    2767             :             //cerr << "after " << freqmin << "   " << freqmax << endl;
    2768             :           }
    2769             : 
    2770             :           
    2771             :           
    2772             :           
    2773        1009 :           if(freqmin < gfreqmin) gfreqmin=freqmin;
    2774        1009 :           if(freqmax > gfreqmax) gfreqmax=freqmax;
    2775        1009 :           if(datafstart < gdatafstart) gdatafstart=datafstart;
    2776        1009 :           if(datafend > gdatafend) gdatafend=datafend;
    2777             :           // pick ms to use for setting spectral coord for output images 
    2778             :           // when startfreq is specified find first ms that it fall within the freq range
    2779             :           // of the ms (with channel selection applied).
    2780             :           // startfreq is converted to the data frame freq based on Measure ref (for the direction, epech, location)
    2781             :           // of that ms.
    2782        1009 :           if(imStartFreq > 0.0 && imStartFreq >= freqmin && imStartFreq <= freqmax){
    2783          72 :             if(mode != "cubesource"){
    2784          72 :               minfmsid=j;
    2785          72 :               spwids0.resize();
    2786          72 :               spwids0=spwids;
    2787          72 :               vi2.originChunks();
    2788          72 :               vi2.origin();
    2789          74 :               while(vb->msId() != j && vi2.moreChunks() ){
    2790           2 :                 vi2.nextChunk();
    2791           2 :                 vi2.origin();
    2792             :               }
    2793          72 :               fld=vb->fieldId()(0);
    2794             :              
    2795             :             }
    2796             :             else{
    2797           0 :               sourceMsWithStartFreq.push_back(j);
    2798             :             }
    2799             :           }
    2800             :            
    2801        1009 :         }
    2802         945 :         if(sourceMsWithStartFreq.size() > 1){
    2803           0 :           auto result = std::find(std::begin(sourceMsWithStartFreq), std::end(sourceMsWithStartFreq), 0);
    2804           0 :           if(result == std::end(sourceMsWithStartFreq)){
    2805           0 :             throw(AipsError("Reorder the input list of MSs so that MS "+String::toString( sourceMsWithStartFreq[0])+ "is first to match startfreq you provided"));
    2806             :           }
    2807             :         }
    2808         945 :     MeasurementSet msobj = *mss[minfmsid];
    2809             :    // return buildCoordinateSystemCore( msobj, spwids0, fld, gfreqmin, gfreqmax, gdatafstart, gdatafend );
    2810        1890 :     return buildCoordinateSystemCore( msobj, spwids0, fld, gfreqmin, gfreqmax, gdatafstart, gdatafend );
    2811         947 :   }
    2812             :   
    2813             : 
    2814           0 :   CoordinateSystem SynthesisParamsImage::buildCoordinateSystem(ROVisibilityIterator* rvi ) 
    2815             :   {
    2816             :     /// This version uses the old vi/vb
    2817             :     // get the first ms for multiple MSes
    2818           0 :     MeasurementSet msobj=rvi->getMeasurementSet();
    2819           0 :     Vector<Int> spwids;
    2820           0 :     Vector<Int> nvischan;
    2821           0 :     rvi->allSelectedSpectralWindows(spwids,nvischan);
    2822           0 :     Int fld = rvi->fieldId();
    2823           0 :     Double freqmin=0, freqmax=0;
    2824             :     Double datafstart, datafend;
    2825             :     //freqFrameValid=(freqFrame != MFrequency::REST || mode != "cubedata" );
    2826           0 :     freqFrameValid=(freqFrame != MFrequency::REST );
    2827           0 :     MSColumns msc(msobj);
    2828           0 :     MFrequency::Types dataFrame=(MFrequency::Types)msc.spectralWindow().measFreqRef()(spwids[0]);
    2829           0 :     rvi->getFreqInSpwRange(datafstart, datafend, dataFrame );
    2830           0 :     if (mode=="cubedata") {
    2831           0 :        freqmin = datafstart;
    2832           0 :        freqmax = datafend;
    2833             :     }
    2834             :     else { 
    2835           0 :        rvi->getFreqInSpwRange(freqmin,freqmax,freqFrameValid? freqFrame:MFrequency::REST );
    2836             :     }
    2837             :     // Following three lines are  kind of redundant but need to get freq range in the data frame to be used
    2838             :     // to select channel range for default start 
    2839             :     //cerr<<"freqmin="<<freqmin<<" datafstart="<<datafstart<<" freqmax="<<freqmax<<" datafend="<<datafend<<endl;
    2840           0 :     return buildCoordinateSystemCore( msobj, spwids, fld, freqmin, freqmax, datafstart, datafend );
    2841           0 :   }
    2842             : 
    2843         945 :   CoordinateSystem SynthesisParamsImage::buildCoordinateSystemCore(
    2844             :                                                                    MeasurementSet& msobj, 
    2845             :                                                                    Vector<Int> spwids, Int fld, 
    2846             :                                                                    Double freqmin, Double freqmax,
    2847             :                                                                    Double datafstart, Double datafend )
    2848             :   {
    2849        1890 :     LogIO os( LogOrigin("SynthesisParamsImage","buildCoordinateSystem",WHERE) );
    2850             :   
    2851         945 :     CoordinateSystem csys;
    2852         945 :     if( csysRecord.nfields()!=0 ) 
    2853             :       {
    2854             :         //use cysRecord
    2855           1 :         Record subRec1;
    2856             :         //        cout<<"USE THE EXISTING CSYS +++++++++++++++++"<<endl;
    2857           1 :         CoordinateSystem *csysptr = CoordinateSystem::restore(csysRecord,"coordsys");
    2858             :         //csys = *csysptr; 
    2859             :         //CoordinateSystem csys(*csysptr); 
    2860           1 :         csys = *csysptr;
    2861             : 
    2862           1 :       }
    2863             :     else {
    2864         944 :       MSColumns msc(msobj);
    2865         944 :       String telescop = msc.observation().telescopeName()(0);
    2866         944 :       MEpoch obsEpoch = msc.timeMeas()(0);
    2867         944 :       MPosition obsPosition;
    2868         944 :     if(!(MeasTable::Observatory(obsPosition, telescop)))
    2869             :       {
    2870             :         os << LogIO::WARN << "Did not get the position of " << telescop
    2871           0 :            << " from data repository" << LogIO::POST;
    2872             :         os << LogIO::WARN
    2873             :            << "Please contact CASA to add it to the repository."
    2874           0 :            << LogIO::POST;
    2875           0 :         os << LogIO::WARN << "Using first antenna position as refence " << LogIO::POST;
    2876             :          // unknown observatory, use first antenna
    2877           0 :       obsPosition=msc.antenna().positionMeas()(0);
    2878             :       }
    2879         944 :       MDirection phaseCenterToUse = phaseCenter;
    2880             :       
    2881         944 :     if( phaseCenterFieldId != -1 )
    2882             :       {
    2883         598 :         MSFieldColumns msfield(msobj.field());
    2884         598 :         if(phaseCenterFieldId == -2) // the case for  phasecenter=''
    2885             :           {
    2886         572 :             if(trackSource){
    2887          14 :               phaseCenterToUse=getMovingSourceDir(msobj, obsEpoch, obsPosition, MDirection::ICRS);
    2888             :             }
    2889             :             else{
    2890         558 :               phaseCenterToUse=msfield.phaseDirMeas( fld );
    2891             :             }
    2892             :           }
    2893             :         else 
    2894             :           {
    2895          26 :             phaseCenterToUse=msfield.phaseDirMeas( phaseCenterFieldId ); 
    2896             :           }
    2897         598 :       }
    2898             :     // Setup Phase center if it is specified only by field id.
    2899             : 
    2900             :     /////////////////// Direction Coordinates
    2901         944 :     MVDirection mvPhaseCenter(phaseCenterToUse.getAngle());
    2902             :     // Normalize correctly
    2903         944 :     MVAngle ra=mvPhaseCenter.get()(0);
    2904         944 :     ra(0.0);
    2905             : 
    2906         944 :     MVAngle dec=mvPhaseCenter.get()(1);
    2907         944 :     Vector<Double> refCoord(2);
    2908         944 :     refCoord(0)=ra.get().getValue();    
    2909         944 :     refCoord(1)=dec;
    2910         944 :     Vector<Double> refPixel(2); 
    2911         944 :     refPixel(0) = Double(imsize[0]/2);
    2912         944 :     refPixel(1) = Double(imsize[1]/2);
    2913             : 
    2914         944 :     Vector<Double> deltas(2);
    2915         944 :     deltas(0)=-1* cellsize[0].get("rad").getValue();
    2916         944 :     deltas(1)=cellsize[1].get("rad").getValue();
    2917         944 :     Matrix<Double> xform(2,2);
    2918         944 :     xform=0.0;xform.diagonal()=1.0;
    2919             : 
    2920         944 :     Vector<Double> projparams(2); 
    2921         944 :     projparams = 0.0;
    2922         944 :     if( useNCP==true ) { projparams[0]=0.0, projparams[1]=1/tan(refCoord(1));   }
    2923         944 :     Projection projTo( projection.type(), projparams );
    2924             : 
    2925             :     DirectionCoordinate
    2926         944 :       myRaDec(MDirection::Types(phaseCenterToUse.getRefPtr()->getType()),
    2927             :               //              projection,
    2928             :               projTo,
    2929        2832 :               refCoord(0), refCoord(1),
    2930        2832 :               deltas(0), deltas(1),
    2931             :               xform,
    2932        1888 :               refPixel(0), refPixel(1));
    2933             : 
    2934             : 
    2935             :     //defining observatory...needed for position on earth
    2936             :     // get the first ms for multiple MSes
    2937             :     
    2938             :     
    2939         944 :     obslocation=obsPosition;
    2940         944 :     ObsInfo myobsinfo;
    2941         944 :     myobsinfo.setTelescope(telescop);
    2942         944 :     myobsinfo.setPointingCenter(mvPhaseCenter);
    2943         944 :     myobsinfo.setObsDate(obsEpoch);
    2944         944 :     myobsinfo.setObserver(msc.observation().observer()(0));
    2945             : 
    2946             :     /// Attach obsInfo to the CoordinateSystem
    2947             :     ///csys.setObsInfo(myobsinfo);
    2948             : 
    2949             : 
    2950             :     /////////////////// Spectral Coordinate
    2951             : 
    2952             :     //Make sure frame conversion is switched off for REST frame data.
    2953             :     //Bool freqFrameValid=(freqFrame != MFrequency::REST);
    2954             : 
    2955             :     //freqFrameValid=(freqFrame != MFrequency::REST );
    2956             :     //UR//freqFrameValid=(freqFrame != MFrequency::REST || mode != "cubedata" );
    2957             :     //UR - moved freqFrameValid calc to vi/vi2 dependent wrappers.
    2958             : 
    2959         944 :     if(spwids.nelements()==0)
    2960             :       {
    2961           0 :         Int nspw=msc.spectralWindow().nrow();
    2962           0 :         spwids.resize(nspw);
    2963           0 :         indgen(spwids); 
    2964             :       }
    2965         944 :     MFrequency::Types dataFrame=(MFrequency::Types)msc.spectralWindow().measFreqRef()(spwids[0]);
    2966         944 :     Vector<Double> dataChanFreq, dataChanWidth;
    2967         944 :     std::vector<std::vector<Int> > averageWhichChan;
    2968         944 :     std::vector<std::vector<Int> > averageWhichSPW;
    2969         944 :     std::vector<std::vector<Double> > averageChanFrac;
    2970             :     
    2971         944 :     if(spwids.nelements()==1)
    2972             :       {
    2973         787 :         dataChanFreq=msc.spectralWindow().chanFreq()(spwids[0]);
    2974         787 :         dataChanWidth=msc.spectralWindow().chanWidth()(spwids[0]);
    2975             :       }
    2976             :     else 
    2977             :       {
    2978         157 :         if(!MSTransformRegridder::combineSpwsCore(os,msobj, spwids,dataChanFreq,dataChanWidth,
    2979             :                                                                                           averageWhichChan,averageWhichSPW,averageChanFrac))
    2980             :           {
    2981           0 :             os << LogIO::SEVERE << "Error combining SpWs" << LogIO::POST;
    2982             :           }
    2983             :       }
    2984         944 :     Double minDataFreq = min(dataChanFreq);
    2985         944 :     if(start=="" && minDataFreq < datafstart  ) {
    2986             :         // limit data chan freq vector for default start case with channel selection
    2987             :         Int chanStart, chanEnd;
    2988           6 :         Int lochan = 0;
    2989           6 :         Int nDataChan = dataChanFreq.nelements();
    2990           6 :         Int hichan = nDataChan-1;
    2991             :         Double diff_fmin, diff_fmax;
    2992           6 :         Bool ascending = dataChanFreq[nDataChan-1] - dataChanFreq[0] > 0;
    2993          90 :         for(Int ichan = 0; ichan < nDataChan; ichan++) 
    2994             :           {
    2995          84 :             diff_fmin = dataChanFreq[ichan] - datafstart;  
    2996          84 :             diff_fmax = datafend - dataChanFreq[ichan];  
    2997             :             // freqmin and freqmax should corresponds to the channel edges
    2998          84 :             if(ascending) 
    2999             :               {
    3000             :                 
    3001          84 :                 if( diff_fmin > 0 &&  diff_fmin <= dataChanWidth[ichan]/2. )
    3002             :                   {
    3003           6 :                     lochan = ichan;
    3004             :                   }
    3005          78 :                 else if(diff_fmax > 0 && diff_fmax <= dataChanWidth[ichan]/2. )
    3006             :                   {
    3007           4 :                     hichan = ichan;
    3008             :                   }
    3009             :               }
    3010             :             else
    3011             :               {
    3012           0 :                 if( diff_fmax > 0 && diff_fmax <= dataChanWidth[ichan]/2. )
    3013             :                   {
    3014           0 :                     hichan = ichan;
    3015             :                   }
    3016           0 :                 else if( diff_fmin > 0 && diff_fmin <= dataChanWidth[ichan]/2. )
    3017             :                   {
    3018           0 :                     lochan = ichan;
    3019             :                   }   
    3020             :               }
    3021             :            }
    3022           6 :         chanStart = lochan;
    3023           6 :         chanEnd = hichan;
    3024           6 :         if (lochan > hichan) 
    3025             :           {
    3026           0 :             chanStart=hichan;
    3027           0 :             chanEnd=lochan; 
    3028             :           }
    3029           6 :         Vector<Double> tempChanFreq = dataChanFreq(Slice(chanStart,chanEnd-chanStart+1,1)); 
    3030           6 :         Vector<Double> tempChanWidth = dataChanWidth(Slice(chanStart,chanEnd-chanStart+1,1)); 
    3031           6 :         dataChanFreq.resize(tempChanFreq.nelements());
    3032           6 :         dataChanWidth.resize(tempChanWidth.nelements());
    3033           6 :         dataChanFreq = tempChanFreq;
    3034           6 :         dataChanWidth = tempChanWidth;
    3035           6 :       }
    3036         944 :     Quantity qrestfreq = restFreq.nelements() >0 ? restFreq[0]: Quantity(0.0, "Hz");
    3037         944 :     String cubemode;
    3038         944 :     if ( qrestfreq.getValue("Hz")==0 ) 
    3039             :       {
    3040         870 :         MSDopplerUtil msdoppler(msobj);
    3041         870 :         Vector<Double> restfreqvec;
    3042         870 :         msdoppler.dopplerInfo(restfreqvec, spwids(0), fld);
    3043         870 :         qrestfreq = restfreqvec.nelements() >0 ? Quantity(restfreqvec(0),"Hz"): Quantity(0.0, "Hz");
    3044         870 :         if ( qrestfreq.getValue("Hz")==0 and mode!="mfs" )
    3045             :           {
    3046          90 :           cubemode = findSpecMode(mode);
    3047          90 :           if ( cubemode=="channel" || cubemode=="frequency" )
    3048             :             {
    3049             :               //Double provisional_restfreq = msc.spectralWindow().refFrequency()(spwids(0));
    3050             :               //By PLWG request, changed to center (mean) frequency of the selected spws -2015-06-22(TT) 
    3051          90 :               Double provisional_restfreq = (datafend+datafstart)/2.0;
    3052          90 :               qrestfreq = Quantity(provisional_restfreq, "Hz");
    3053             :               os << LogIO::WARN << "No rest frequency info, using the center of the selected spw(s):"
    3054             :                  << provisional_restfreq <<" Hz. Velocity labelling may not be correct." 
    3055          90 :                  << LogIO::POST;
    3056             :             } 
    3057             :           else { // must be vel mode
    3058           0 :             throw(AipsError("No valid rest frequency is defined in the data, please specify the restfreq parameter") );
    3059             :             } 
    3060             :         }
    3061         870 :       }
    3062             :     Double refPix;
    3063         944 :     Vector<Double> chanFreq;
    3064         944 :     Vector<Double> chanFreqStep;
    3065         944 :     String specmode;
    3066             : 
    3067         944 :     if(mode=="cubesource"){
    3068           5 :       MDoppler mdop(sysvelvalue, MDoppler::RELATIVISTIC);
    3069           5 :       dataChanFreq=mdop.shiftFrequency(dataChanFreq);
    3070           5 :       dataChanWidth=mdop.shiftFrequency(dataChanWidth);
    3071           5 :       if (std::isnan(dataChanFreq[0]) || std::isnan(dataChanFreq[dataChanFreq.nelements()-1])) {
    3072           0 :         throw(AipsError("The Doppler shift correction of the data channel frequencies resulted in 'NaN' using the radial velocity = "+
    3073           0 :               String::toString(sysvelvalue)+". Typically this indicates a problem in the ephemeris data being used.")); 
    3074             :       }
    3075           5 :     }
    3076             :     
    3077         944 :     if (!getImFreq(chanFreq, chanFreqStep, refPix, specmode, obsEpoch, 
    3078             :                    obsPosition, dataChanFreq, dataChanWidth, dataFrame, qrestfreq, freqmin, freqmax,
    3079             :                    phaseCenterToUse))
    3080           0 :       throw(AipsError("Failed to determine channelization parameters"));
    3081             : 
    3082         943 :     Bool nonLinearFreq(false);
    3083         943 :     String veltype_p=veltype;
    3084         943 :     veltype_p.upcase(); 
    3085        2825 :     if(veltype_p.contains("OPTICAL") || veltype_p.matches("Z") || veltype_p.contains("BETA") ||
    3086        2825 :          veltype_p.contains("RELATI") || veltype_p.contains("GAMMA")) 
    3087             :       {
    3088           2 :         nonLinearFreq= true;
    3089             :       }
    3090             : 
    3091         943 :     SpectralCoordinate mySpectral;
    3092             :     Double stepf;
    3093         943 :     if(!nonLinearFreq) 
    3094             :     //TODO: velocity mode default start case (use last channels?)
    3095             :       {
    3096         941 :         Double startf=chanFreq[0];
    3097             :         //Double stepf=chanFreqStep[0];
    3098         941 :         if(chanFreq.nelements()==1) 
    3099             :           {
    3100         586 :             stepf=chanFreqStep[0];
    3101             :           }
    3102             :         else 
    3103             :           { 
    3104         355 :             stepf=chanFreq[1]-chanFreq[0];
    3105             :           }
    3106         941 :         Double restf=qrestfreq.getValue("Hz");
    3107             :         //stepf=9e8;
    3108         941 :         if ( mode=="mfs" and restf == 0.0 ) restf = restFreq[0].getValue("Hz");
    3109             :         //cerr<<" startf="<<startf<<" stepf="<<stepf<<" refPix="<<refPix<<" restF="<<restf<<endl;
    3110             :         // once NOFRAME is implemented do this 
    3111         941 :         if(mode=="cubedata") 
    3112             :           {
    3113             :       //       mySpectral = SpectralCoordinate(freqFrameValid ? MFrequency::Undefined : MFrequency::REST, 
    3114           4 :              mySpectral = SpectralCoordinate(freqFrame == MFrequency::REST? 
    3115             :                                              MFrequency::REST : MFrequency::Undefined, 
    3116           2 :                                              startf, stepf, refPix, restf);
    3117             :           }
    3118         939 :         else if(mode=="cubesource") 
    3119             :           {
    3120             :             /*stepf=chanFreq.nelements() > 1 ?(freqmax-freqmin)/Double(chanFreq.nelements()-1) : freqmax-freqmin;
    3121             :             startf=freqmin+stepf/2.0;
    3122             :             */
    3123          10 :              mySpectral = SpectralCoordinate(MFrequency::REST, 
    3124           5 :                                              startf, stepf, refPix, restf);
    3125             :           }
    3126             :         else 
    3127             :           {
    3128        1868 :              mySpectral = SpectralCoordinate(freqFrameValid ? freqFrame : MFrequency::REST, 
    3129         934 :                 startf, stepf, refPix, restf);
    3130             :           }
    3131             :       }
    3132             :     else 
    3133             :       { // nonlinear freq coords - use tabular setting
    3134             :         // once NOFRAME is implemented do this 
    3135           2 :         if(mode=="cubedata") 
    3136             :           {
    3137             :             //mySpectral = SpectralCoordinate(freqFrameValid ? MFrequency::Undefined : MFrequency::REST,
    3138           0 :             mySpectral = SpectralCoordinate(freqFrame == MFrequency::REST ? 
    3139             :                                             MFrequency::REST : MFrequency::Undefined,
    3140           0 :                                             chanFreq, (Double)qrestfreq.getValue("Hz"));
    3141             :           }
    3142           2 :         else if (mode=="cubesource") 
    3143             :           {
    3144           0 :             mySpectral = SpectralCoordinate(MFrequency::REST,
    3145           0 :                                             chanFreq, (Double)qrestfreq.getValue("Hz"));
    3146             :           }
    3147             :         else 
    3148             :           {
    3149           4 :             mySpectral = SpectralCoordinate(freqFrameValid ? freqFrame : MFrequency::REST,
    3150           6 :                  chanFreq, (Double)qrestfreq.getValue("Hz"));
    3151             :           }
    3152             :       }
    3153             :     //cout << "Rest Freq : " << restFreq << endl;
    3154             : 
    3155             :     //for(uInt k=1 ; k < restFreq.nelements(); ++k)
    3156             :       //mySpectral.setRestFrequency(restFreq[k].getValue("Hz"));
    3157             :      
    3158         943 :     uInt nrestfreq = restFreq.nelements();
    3159         943 :     if ( nrestfreq > 1 ) {
    3160           0 :       Vector<Double> restfreqval( nrestfreq - 1 );
    3161           0 :       for ( uInt k=1 ; k < nrestfreq; ++k ) {
    3162           0 :         restfreqval[k-1] = restFreq[k].getValue("Hz");
    3163             :       }    
    3164           0 :       mySpectral.setRestFrequencies(restfreqval, 0, true);
    3165           0 :     }
    3166             : 
    3167             :     // no longer needed, done inside SIImageStore
    3168             :     //if ( freqFrameValid ) {
    3169             :     // mySpectral.setReferenceConversion(MFrequency::LSRK,obsEpoch,obsPosition,phaseCenterToUse);   
    3170             :     //}
    3171             : 
    3172             :     //    cout << "RF from coordinate : " << mySpectral.restFrequency() << endl;
    3173             : 
    3174             :     ////////////////// Stokes Coordinate
    3175             :    
    3176         943 :     Vector<Int> whichStokes = decideNPolPlanes(stokes);
    3177         943 :     if(whichStokes.nelements()==0)
    3178           0 :       throw(AipsError("Stokes selection of " + stokes + " is invalid"));
    3179         943 :     StokesCoordinate myStokes(whichStokes);
    3180             : 
    3181             :     //////////////////  Build Full coordinate system. 
    3182             : 
    3183             :     //CoordinateSystem csys;
    3184         943 :     csys.addCoordinate(myRaDec);
    3185         943 :     csys.addCoordinate(myStokes);
    3186         943 :     csys.addCoordinate(mySpectral);
    3187         943 :     csys.setObsInfo(myobsinfo);
    3188             : 
    3189             :     //store back csys to impars record
    3190             :     //cerr<<"save csys to csysRecord..."<<endl;
    3191         943 :     if(csysRecord.isDefined("coordsys"))
    3192           0 :       csysRecord.removeField("coordsys");
    3193         943 :     csys.save(csysRecord,"coordsys");
    3194             :     //cerr<<"BUILDCOORDSYS:: new csysRecord ="<<csysRecord<<endl;
    3195             :     // imshape
    3196         943 :     imshape.resize(4);
    3197         943 :     imshape[0] = imsize[0];
    3198         943 :     imshape[1] = imsize[0];
    3199         943 :     imshape[2] = whichStokes.nelements();
    3200         943 :     imshape[3] = chanFreq.nelements(); 
    3201             :     //toRecord();
    3202             :     //////////////// Set Observatory info, if MS is provided.
    3203             :     // (remove this section after verified...)
    3204             :     /***
    3205             :     if( ! msobj.isNull() )
    3206             :       {
    3207             :         //defining observatory...needed for position on earth
    3208             :         MSColumns msc(msobj);
    3209             :         String telescop = msc.observation().telescopeName()(0);
    3210             :         MEpoch obsEpoch = msc.timeMeas()(0);
    3211             :         MPosition obsPosition;
    3212             :         if(!(MeasTable::Observatory(obsPosition, telescop)))
    3213             :           {
    3214             :             os << LogIO::WARN << "Did not get the position of " << telescop 
    3215             :                << " from data repository" << LogIO::POST;
    3216             :             os << LogIO::WARN 
    3217             :                << "Please contact CASA to add it to the repository."
    3218             :                << LogIO::POST;
    3219             :             os << LogIO::WARN << "Frequency conversion will not work " << LogIO::POST;
    3220             :           }
    3221             :         
    3222             :         ObsInfo myobsinfo;
    3223             :         myobsinfo.setTelescope(telescop);
    3224             :         myobsinfo.setPointingCenter(mvPhaseCenter);
    3225             :         myobsinfo.setObsDate(obsEpoch);
    3226             :         myobsinfo.setObserver(msc.observation().observer()(0));
    3227             : 
    3228             :         /// Attach obsInfo to the CoordinateSystem
    3229             :         csys.setObsInfo(myobsinfo);
    3230             : 
    3231             :       }// if MS is provided.
    3232             :       ***/
    3233         969 :     } // end of else when coordsys record is not defined...
    3234             :  
    3235             :     //    cout << " ----- ----- ------ ------ CSYS WORLD AXIS UNITS : " << csys.worldAxisUnits() << endl;
    3236             : 
    3237        1888 :    return csys;
    3238         946 :   }
    3239             : 
    3240             : 
    3241             :   /*
    3242             : #ifdef USEVIVB2
    3243             :   CoordinateSystem SynthesisParamsImage::buildCoordinateSystem(vi::VisibilityIterator2* vi2)
    3244             : #else
    3245             :   CoordinateSystem SynthesisParamsImage::buildCoordinateSystem(ROVisibilityIterator* rvi )
    3246             : #endif
    3247             :   {
    3248             :     LogIO os( LogOrigin("SynthesisParamsImage","buildCoordinateSystem",WHERE) );
    3249             :   
    3250             : 
    3251             :     // get the first ms for multiple MSes
    3252             : #ifdef USEVIVB2
    3253             :     MeasurementSet msobj=vi2->getMeasurementSet();
    3254             : #else
    3255             :     MeasurementSet msobj=rvi->getMeasurementSet();
    3256             : #endif
    3257             : 
    3258             :     MDirection phaseCenterToUse = phaseCenter;
    3259             :     if( phaseCenterFieldId != -1 )
    3260             :       {
    3261             :         MSFieldColumns msfield(msobj.field());
    3262             :         phaseCenterToUse=msfield.phaseDirMeas( phaseCenterFieldId ); 
    3263             :       }
    3264             :     // Setup Phase center if it is specified only by field id.
    3265             : 
    3266             :     /////////////////// Direction Coordinates
    3267             :     MVDirection mvPhaseCenter(phaseCenterToUse.getAngle());
    3268             :     // Normalize correctly
    3269             :     MVAngle ra=mvPhaseCenter.get()(0);
    3270             :     ra(0.0);
    3271             : 
    3272             :     MVAngle dec=mvPhaseCenter.get()(1);
    3273             :     Vector<Double> refCoord(2);
    3274             :     refCoord(0)=ra.get().getValue();    
    3275             :     refCoord(1)=dec;
    3276             :     Vector<Double> refPixel(2); 
    3277             :     refPixel(0) = Double(imsize[0]/2);
    3278             :     refPixel(1) = Double(imsize[1]/2);
    3279             : 
    3280             :     Vector<Double> deltas(2);
    3281             :     deltas(0)=-1* cellsize[0].get("rad").getValue();
    3282             :     deltas(1)=cellsize[1].get("rad").getValue();
    3283             :     Matrix<Double> xform(2,2);
    3284             :     xform=0.0;xform.diagonal()=1.0;
    3285             : 
    3286             :     Vector<Double> projparams(2); 
    3287             :     projparams = 0.0;
    3288             :     if( useNCP==true ) { projparams[0]=0.0, projparams[1]=1/tan(refCoord(1));   }
    3289             :     Projection projTo( projection.type(), projparams );
    3290             : 
    3291             :     DirectionCoordinate
    3292             :       myRaDec(MDirection::Types(phaseCenterToUse.getRefPtr()->getType()),
    3293             :               //              projection,
    3294             :               projTo,
    3295             :               refCoord(0), refCoord(1),
    3296             :               deltas(0), deltas(1),
    3297             :               xform,
    3298             :               refPixel(0), refPixel(1));
    3299             : 
    3300             : 
    3301             :     //defining observatory...needed for position on earth
    3302             :     // get the first ms for multiple MSes
    3303             :     MSColumns msc(msobj);
    3304             :     String telescop = msc.observation().telescopeName()(0);
    3305             :     MEpoch obsEpoch = msc.timeMeas()(0);
    3306             :     MPosition obsPosition;
    3307             :     if(!(MeasTable::Observatory(obsPosition, telescop)))
    3308             :       {
    3309             :         os << LogIO::WARN << "Did not get the position of " << telescop
    3310             :            << " from data repository" << LogIO::POST;
    3311             :         os << LogIO::WARN
    3312             :            << "Please contact CASA to add it to the repository."
    3313             :            << LogIO::POST;
    3314             :         os << LogIO::WARN << "Frequency conversion will not work " << LogIO::POST;
    3315             :       }
    3316             : 
    3317             :     ObsInfo myobsinfo;
    3318             :     myobsinfo.setTelescope(telescop);
    3319             :     myobsinfo.setPointingCenter(mvPhaseCenter);
    3320             :     myobsinfo.setObsDate(obsEpoch);
    3321             :     myobsinfo.setObserver(msc.observation().observer()(0));
    3322             : 
    3323             :     /// Attach obsInfo to the CoordinateSystem
    3324             :     ///csys.setObsInfo(myobsinfo);
    3325             : 
    3326             : 
    3327             :     /////////////////// Spectral Coordinate
    3328             : 
    3329             :     //Make sure frame conversion is switched off for REST frame data.
    3330             :     //Bool freqFrameValid=(freqFrame != MFrequency::REST);
    3331             : 
    3332             :     //freqFrameValid=(freqFrame != MFrequency::REST );
    3333             :     freqFrameValid=(freqFrame != MFrequency::REST || mode != "cubedata" );
    3334             : 
    3335             :     // *** get selected spw ids ***
    3336             :     Vector<Int> spwids;
    3337             : #ifdef USEVIVB2
    3338             :     vi2->spectralWindows( spwids );
    3339             : #else
    3340             :     Vector<Int> nvischan;
    3341             :     rvi->allSelectedSpectralWindows(spwids,nvischan);
    3342             : #endif
    3343             :     if(spwids.nelements()==0)
    3344             :       {
    3345             :         Int nspw=msc.spectralWindow().nrow();
    3346             :         spwids.resize(nspw);
    3347             :         indgen(spwids); 
    3348             :       }
    3349             :     MFrequency::Types dataFrame=(MFrequency::Types)msc.spectralWindow().measFreqRef()(spwids[0]);
    3350             :     Vector<Double> dataChanFreq, dataChanWidth;
    3351             :     if(spwids.nelements()==1)
    3352             :       {
    3353             :         dataChanFreq=msc.spectralWindow().chanFreq()(spwids[0]);
    3354             :         dataChanWidth=msc.spectralWindow().chanWidth()(spwids[0]);
    3355             :       }
    3356             :     else 
    3357             :       {
    3358             :         SubMS thems(msobj);
    3359             :         if(!thems.combineSpws(spwids,true,dataChanFreq,dataChanWidth))
    3360             :           //if(!MSTransformRegridder::combineSpws(os,msobj.tableName(),spwids,dataChanFreq,dataChanWidth))
    3361             :           {
    3362             :             os << LogIO::SEVERE << "Error combining SpWs" << LogIO::POST;
    3363             :           }
    3364             :       }
    3365             :     
    3366             :     Quantity qrestfreq = restFreq.nelements() >0 ? restFreq[0]: Quantity(0.0, "Hz");
    3367             :     if( qrestfreq.getValue("Hz")==0 ) 
    3368             :       {
    3369             : #ifdef USEVIVB2
    3370             :         ///// TTCheck
    3371             :         Vector<Int> flds;
    3372             :         vi2->fieldIds( flds );
    3373             :         AlwaysAssert( flds.nelements()>0 , AipsError );
    3374             :         Int fld = flds[0];
    3375             : #else
    3376             :         Int fld = rvi->fieldId();
    3377             : #endif
    3378             :         MSDopplerUtil msdoppler(msobj);
    3379             :         Vector<Double> restfreqvec;
    3380             :         msdoppler.dopplerInfo(restfreqvec, spwids[0], fld);
    3381             :         qrestfreq = restfreqvec.nelements() >0 ? Quantity(restfreqvec[0],"Hz"): Quantity(0.0, "Hz");
    3382             :       }
    3383             :     Double refPix;
    3384             :     Vector<Double> chanFreq;
    3385             :     Vector<Double> chanFreqStep;
    3386             :     String specmode;
    3387             : 
    3388             :     //for mfs 
    3389             :     Double freqmin=0, freqmax=0;
    3390             : #ifdef USEVIVB2
    3391             :     vi2->getFreqInSpwRange(freqmin,freqmax,freqFrameValid? freqFrame:MFrequency::REST );
    3392             : #else
    3393             :     rvi->getFreqInSpwRange(freqmin,freqmax,freqFrameValid? freqFrame:MFrequency::REST );
    3394             : #endif
    3395             : 
    3396             :     if (!getImFreq(chanFreq, chanFreqStep, refPix, specmode, obsEpoch, 
    3397             :                    obsPosition, dataChanFreq, dataChanWidth, dataFrame, qrestfreq, freqmin, freqmax,
    3398             :                    phaseCenterToUse))
    3399             :       throw(AipsError("Failed to determine channelization parameters"));
    3400             : 
    3401             :     Bool nonLinearFreq(false);
    3402             :     String veltype_p=veltype;
    3403             :     veltype_p.upcase(); 
    3404             :     if(veltype_p.contains("OPTICAL") || veltype_p.matches("Z") || veltype_p.contains("BETA") ||
    3405             :          veltype_p.contains("RELATI") || veltype_p.contains("GAMMA")) 
    3406             :       {
    3407             :         nonLinearFreq= true;
    3408             :       }
    3409             : 
    3410             :     SpectralCoordinate mySpectral;
    3411             :     Double stepf;
    3412             :     if(!nonLinearFreq) 
    3413             :     //TODO: velocity mode default start case (use last channels?)
    3414             :       {
    3415             :         Double startf=chanFreq[0];
    3416             :         //Double stepf=chanFreqStep[0];
    3417             :         if(chanFreq.nelements()==1) 
    3418             :           {
    3419             :             stepf=chanFreqStep[0];
    3420             :           }
    3421             :         else 
    3422             :           { 
    3423             :             stepf=chanFreq[1]-chanFreq[0];
    3424             :           }
    3425             :         Double restf=qrestfreq.getValue("Hz");
    3426             :         //cerr<<" startf="<<startf<<" stepf="<<stepf<<" refPix="<<refPix<<" restF="<<restf<<endl;
    3427             :         // once NOFRAME is implemented do this 
    3428             :         if(mode=="cubedata") 
    3429             :           {
    3430             :       //       mySpectral = SpectralCoordinate(freqFrameValid ? MFrequency::Undefined : MFrequency::REST, 
    3431             :              mySpectral = SpectralCoordinate(freqFrame == MFrequency::REST? 
    3432             :                                              MFrequency::REST : MFrequency::Undefined, 
    3433             :                                              startf, stepf, refPix, restf);
    3434             :           }
    3435             :         else 
    3436             :           {
    3437             :              mySpectral = SpectralCoordinate(freqFrameValid ? freqFrame : MFrequency::REST, 
    3438             :                 startf, stepf, refPix, restf);
    3439             :           }
    3440             :       }
    3441             :     else 
    3442             :       { // nonlinear freq coords - use tabular setting
    3443             :         // once NOFRAME is implemented do this 
    3444             :         if(mode=="cubedata") 
    3445             :           {
    3446             :             //mySpectral = SpectralCoordinate(freqFrameValid ? MFrequency::Undefined : MFrequency::REST,
    3447             :             mySpectral = SpectralCoordinate(freqFrame == MFrequency::REST ? 
    3448             :                                             MFrequency::REST : MFrequency::Undefined,
    3449             :                                             chanFreq, (Double)qrestfreq.getValue("Hz"));
    3450             :           }
    3451             :         else 
    3452             :           {
    3453             :             mySpectral = SpectralCoordinate(freqFrameValid ? freqFrame : MFrequency::REST,
    3454             :                  chanFreq, (Double)qrestfreq.getValue("Hz"));
    3455             :           }
    3456             :       }
    3457             :     //cout << "Rest Freq : " << restFreq << endl;
    3458             : 
    3459             :     for(uInt k=1 ; k < restFreq.nelements(); ++k)
    3460             :       mySpectral.setRestFrequency(restFreq[k].getValue("Hz"));
    3461             : 
    3462             :     if ( freqFrameValid ) {
    3463             :       mySpectral.setReferenceConversion(MFrequency::LSRK,obsEpoch,obsPosition,phaseCenterToUse);   
    3464             :     }
    3465             : 
    3466             :     //    cout << "RF from coordinate : " << mySpectral.restFrequency() << endl;
    3467             : 
    3468             :     ////////////////// Stokes Coordinate
    3469             :    
    3470             :     Vector<Int> whichStokes = decideNPolPlanes(stokes);
    3471             :     if(whichStokes.nelements()==0)
    3472             :       throw(AipsError("Stokes selection of " + stokes + " is invalid"));
    3473             :     StokesCoordinate myStokes(whichStokes);
    3474             : 
    3475             :     //////////////////  Build Full coordinate system. 
    3476             : 
    3477             :     CoordinateSystem csys;
    3478             :     csys.addCoordinate(myRaDec);
    3479             :     csys.addCoordinate(myStokes);
    3480             :     csys.addCoordinate(mySpectral);
    3481             :     csys.setObsInfo(myobsinfo);
    3482             : 
    3483             :     //////////////// Set Observatory info, if MS is provided.
    3484             :     // (remove this section after verified...)
    3485             :     return csys;
    3486             :   }
    3487             : */
    3488             : 
    3489          14 :   MDirection SynthesisParamsImage::getMovingSourceDir(const MeasurementSet& ms, const MEpoch& refEp, const MPosition& obsposition, const MDirection::Types outframe){
    3490          14 :     MDirection outdir;
    3491          14 :     String ephemtab(movingSource);
    3492          14 :     if(movingSource=="TRACKFIELD"){
    3493           6 :       Int fieldID=MSColumns(ms).fieldId()(0);
    3494           6 :       ephemtab=Path(MSColumns(ms).field().ephemPath(fieldID)).absoluteName();
    3495             :     }
    3496          14 :     casacore::MDirection::Types planetType=MDirection::castType(trackDir.getRef().getType());
    3497          14 :     if( (! Table::isReadable(ephemtab)) &&   ( (planetType <= MDirection::N_Types) || (planetType >= MDirection::COMET)))
    3498           0 :       throw(AipsError("Does not have a valid ephemeris table or major solar system object defined"));
    3499          14 :     MeasFrame mframe(refEp, obsposition);
    3500          14 :     MDirection::Ref outref1(MDirection::AZEL, mframe);
    3501          14 :     MDirection::Ref outref(outframe, mframe);
    3502          14 :     MDirection tmpazel;
    3503             :     // (TT) Switched the order of evaluation of if statement (if ephem table is readable
    3504             :     // one should use that. MDirection::getType will match MDirection::Types if a string conains and starts with
    3505             :     // one of the enum names in MDirection::Types. So the table name can be mistaken as a major planets in MDirection::Types
    3506             :     // if it is evaluated first.
    3507          14 :     if (Table::isReadable(ephemtab)){
    3508          12 :       MeasComet mcomet(Path(ephemtab).absoluteName());
    3509          12 :       mframe.set(mcomet);
    3510          12 :       tmpazel=MDirection::Convert(MDirection(MDirection::COMET), outref1)();
    3511          12 :     }
    3512           2 :     else if (planetType >=MDirection::MERCURY && planetType <MDirection::COMET){
    3513           2 :       tmpazel=MDirection::Convert(trackDir, outref1)();
    3514             :     }
    3515          14 :     outdir=MDirection::Convert(tmpazel, outref)();
    3516             : 
    3517          28 :     return outdir;
    3518          14 :   }
    3519             :   
    3520         944 :   Bool SynthesisParamsImage::getImFreq(Vector<Double>& chanFreq, Vector<Double>& chanFreqStep, 
    3521             :                                        Double& refPix, String& specmode,
    3522             :                                        const MEpoch& obsEpoch, const MPosition& obsPosition, 
    3523             :                                        const Vector<Double>& dataChanFreq, 
    3524             :                                        const Vector<Double>& dataChanWidth,
    3525             :                                        const MFrequency::Types& dataFrame, 
    3526             :                                        const Quantity& qrestfreq, const Double& freqmin, const Double& freqmax,
    3527             :                                        const MDirection& phaseCenter) 
    3528             :   {
    3529             : 
    3530         944 :     String inStart, inStep; 
    3531         944 :     specmode = findSpecMode(mode);
    3532         944 :     String freqframe;
    3533         944 :     Bool verbose("true"); // verbose logging messages from calcChanFreqs
    3534        1888 :     LogIO os( LogOrigin("SynthesisParamsImage","getImFreq",WHERE) );
    3535             : 
    3536         944 :     refPix=0.0; 
    3537         944 :     Bool descendingfreq(false);
    3538         944 :     Bool descendingoutfreq(false);
    3539             : 
    3540         944 :     if( mode.contains("cube") )
    3541             :       { 
    3542         479 :         String restfreq=QuantityToString(qrestfreq);
    3543             :         // use frame from input start or width in MFreaquency or MRadialVelocity
    3544         479 :         freqframe = qmframe!=""? qmframe: MFrequency::showType(freqFrame);
    3545             :         // emit warning here if qmframe is used 
    3546             :         //
    3547         479 :         inStart = start;
    3548         479 :         inStep = step;
    3549         479 :         if( specmode=="channel" ) 
    3550             :           {
    3551         398 :             inStart = String::toString(chanStart);
    3552         398 :             inStep = String::toString(chanStep); 
    3553             :             // negative step -> descending channel indices 
    3554         398 :             if (inStep.contains(casacore::Regex("^-"))) descendingfreq=true;
    3555             :             // input frame is the data frame
    3556             :             //freqframe = MFrequency::showType(dataFrame);
    3557             :           }
    3558          81 :         else if( specmode=="frequency" ) 
    3559             :           {
    3560             :             //if ( freqStart.getValue("Hz") == 0 && freqStart.getUnit() != "" ) { // default start
    3561             :             //start = String::toString( freqmin ) + freqStart.getUnit();
    3562             :             //}
    3563             :             //else {
    3564             :             //start = String::toString( freqStart.getValue(freqStart.getUnit()) )+freqStart.getUnit();  
    3565             :             //}
    3566             :             //step = String::toString( freqStep.getValue(freqStep.getUnit()) )+freqStep.getUnit();  
    3567             :             // negative freq width -> descending freq ordering
    3568          49 :             if(inStep.contains(casacore::Regex("^-"))) descendingfreq=true;
    3569             :           }
    3570          32 :         else if( specmode=="velocity" ) 
    3571             :           {
    3572             :             // if velStart is empty set start to vel of freqmin or freqmax?
    3573             :             //if ( velStart.getValue(velStart.getUnit()) == 0 && !(velStart.getUnit().contains("m/s")) ) {
    3574             :             //  start = "";
    3575             :             //}
    3576             :             //else { 
    3577             :             //  start = String::toString( velStart.getValue(velStart.getUnit()) )+velStart.getUnit();  
    3578             :             //}
    3579             :             //step = String::toString( velStep.getValue(velStep.getUnit()) )+velStep.getUnit();  
    3580             :             // positive velocity width -> descending freq ordering
    3581          32 :             if (!inStep.contains(casacore::Regex("^-"))) descendingfreq=true;
    3582             :           }
    3583             : 
    3584         479 :       if (inStep=='0') inStep="";
    3585             : 
    3586         479 :       MRadialVelocity mSysVel; 
    3587         479 :       Quantity qVel;
    3588             :       MRadialVelocity::Types mRef;
    3589         479 :       if(mode!="cubesource") 
    3590             :         {
    3591             :           
    3592             :           
    3593         474 :           if(freqframe=="SOURCE") 
    3594             :             {
    3595             :               os << LogIO::SEVERE << "freqframe=\"SOURCE\" is only allowed for mode=\"cubesrc\""
    3596           0 :                  << LogIO::EXCEPTION;
    3597           0 :               return false; 
    3598             :             }
    3599             :         }
    3600             :       else // only for cubesrc mode: TODO- check for the ephemeris info.
    3601             :         {
    3602           5 :           freqframe=MFrequency::showType(dataFrame);
    3603           5 :           if(sysvel!="") {
    3604           0 :             stringToQuantity(sysvel,qVel);
    3605           0 :             MRadialVelocity::getType(mRef,sysvelframe);
    3606           0 :             mSysVel=MRadialVelocity(qVel,mRef);
    3607             :           }
    3608             :           else // and if no ephemeris info, issue a warning... 
    3609           5 :             {  mSysVel=MRadialVelocity();}
    3610             :         }
    3611             :       // cubedata mode: input start, step are those of the input data frame
    3612         479 :       if ( mode=="cubedata" ) 
    3613             :         {
    3614           2 :           freqframe=MFrequency::showType(dataFrame);
    3615           2 :           freqFrameValid=false; // no conversion for vb.lsrfrequency()
    3616             :         }
    3617             :       //if ( mode=="cubedata" ) freqframe=MFrequency::REST;
    3618             :       
    3619             :       // *** NOTE *** 
    3620             :       // calcChanFreqs alway returns chanFreq in
    3621             :       // ascending freq order. 
    3622             :       // for step < 0 calcChanFreqs returns chanFreq that 
    3623             :       // contains start freq. in its last element of the vector. 
    3624             :       //
    3625         479 :       os << LogIO::DEBUG1<<"mode="<<mode<<" specmode="<<specmode<<" inStart="<<inStart
    3626             :          <<" inStep="<<inStep<<" restfreq="<<restfreq<<" freqframe="<<freqframe
    3627         958 :          <<" dataFrame="<<dataFrame <<" veltype="<<veltype<<" nchan="<<nchan
    3628         479 :          << LogIO::POST;
    3629         479 :       ostringstream ostr;
    3630         479 :       ostr << " phaseCenter='" << phaseCenter;
    3631         479 :       os << String(ostr)<<"' ";
    3632             : 
    3633             :       Double dummy; // dummy variable  - weightScale is not used here
    3634         958 :       Bool rst=MSTransformRegridder::calcChanFreqs(os,
    3635             :                            chanFreq, 
    3636             :                            chanFreqStep,
    3637             :                            dummy,
    3638             :                            dataChanFreq,
    3639             :                            dataChanWidth,
    3640             :                            phaseCenter,
    3641             :                            dataFrame,
    3642             :                            obsEpoch,
    3643             :                            obsPosition,
    3644             :                            specmode,
    3645             :                            nchan,
    3646             :                            inStart,
    3647             :                            inStep,
    3648             :                            restfreq,
    3649             :                            freqframe,
    3650         479 :                            veltype,
    3651             :                            verbose, 
    3652             :                            mSysVel
    3653             :                            );
    3654             : 
    3655         479 :       if( nchan==-1 ) 
    3656             :         { 
    3657         280 :           nchan = chanFreq.nelements(); 
    3658         280 :           os << LogIO::DEBUG1 << "Setting nchan to number of selected channels : " << nchan << LogIO::POST;
    3659             :         }
    3660             : 
    3661         479 :       if (!rst) {
    3662             :         os << LogIO::SEVERE << "calcChanFreqs failed, check input start and width parameters"
    3663           1 :            << LogIO::EXCEPTION;
    3664           0 :         return false;
    3665             :       }
    3666             :       os << LogIO::DEBUG1
    3667         478 :          <<"chanFreq 0="<<chanFreq[0]<<" chanFreq last="<<chanFreq[chanFreq.nelements()-1]
    3668         956 :          << LogIO::POST;
    3669             : 
    3670         478 :       if (chanFreq[0]>chanFreq[chanFreq.nelements()-1]) {
    3671          14 :         descendingoutfreq = true;
    3672             :       }
    3673             : 
    3674             :        //if (descendingfreq && !descendingoutfreq) {
    3675         876 :       if ((specmode=="channel" && descendingfreq==1) 
    3676         876 :           || (specmode!="channel" && (descendingfreq != descendingoutfreq))) { 
    3677             :         // reverse the freq vector if necessary so the first element can be
    3678             :         // used to set spectralCoordinates in all the cases.
    3679             :         //
    3680             :         // also do for chanFreqStep..
    3681          31 :         std::vector<Double> stlchanfreq;
    3682          31 :         chanFreq.tovector(stlchanfreq);
    3683          31 :         std::reverse(stlchanfreq.begin(),stlchanfreq.end());
    3684          31 :         chanFreq=Vector<Double>(stlchanfreq);
    3685          31 :         chanFreqStep=-chanFreqStep;
    3686          31 :       }
    3687         482 :     }
    3688         465 :     else if ( mode=="mfs" ) {
    3689         465 :       chanFreq.resize(1);
    3690         465 :       chanFreqStep.resize(1);
    3691             :       //chanFreqStep[0] = freqmax - freqmin;
    3692         465 :       Double freqmean = (freqmin + freqmax)/2;
    3693         465 :       if (refFreq.getValue("Hz")==0) {
    3694         409 :         chanFreq[0] = freqmean;
    3695         409 :         refPix = 0.0;
    3696         409 :         chanFreqStep[0] = freqmax - freqmin;
    3697             :       }
    3698             :       else { 
    3699          56 :         chanFreq[0] = refFreq.getValue("Hz"); 
    3700             :         // Set the new reffreq to be the refPix (CAS-9518)
    3701          56 :         refPix  = 0.0; // (refFreq.getValue("Hz") - freqmean)/chanFreqStep[0];
    3702             :         // A larger bandwidth to compensate for the shifted reffreq (CAS-9518)
    3703          56 :         chanFreqStep[0] = freqmax - freqmin + 2*fabs(chanFreq[0] - freqmean);
    3704             :       }
    3705             : 
    3706         465 :       if( nchan==-1 ) nchan=1;
    3707         465 :       if( qrestfreq.getValue("Hz")==0.0 )  {
    3708          48 :          restFreq.resize(1);
    3709          48 :          restFreq[0] = Quantity(freqmean,"Hz");
    3710             :       }
    3711             :     }
    3712             :     else {
    3713             :        // unrecognized mode, error
    3714           0 :        os << LogIO::SEVERE << "mode="<<mode<<" is unrecognized."
    3715           0 :           << LogIO::EXCEPTION;
    3716           0 :        return false;
    3717             :     }
    3718         943 :     return true;
    3719             : 
    3720         947 :   }//getImFreq
    3721             :   /////////////////////////
    3722         945 :   Double SynthesisParamsImage::getCubeImageStartFreq(){
    3723         945 :     Double inStartFreq=-1.0;
    3724         945 :     String checkspecmode("");
    3725         945 :     if(mode.contains("cube")) {
    3726         480 :       checkspecmode = findSpecMode(mode);
    3727             :     } 
    3728         945 :     if(checkspecmode!="") {
    3729         480 :       MFrequency::Types mfreqframe = frame!="" ? MFrequency::typeFromString(frame):MFrequency::LSRK;
    3730         480 :       if(checkspecmode=="channel") {
    3731         399 :         inStartFreq=-1.0;  
    3732             :       }
    3733             :       else {
    3734          81 :         if(checkspecmode=="frequency") {
    3735          49 :           inStartFreq = freqStart.get("Hz").getValue();  
    3736             :         }
    3737          32 :         else if(checkspecmode=="velocity") {
    3738             :           MDoppler::Types DopType;
    3739          32 :           MDoppler::getType(DopType, veltype);
    3740          32 :           MDoppler mdop(velStart,DopType);
    3741          32 :           Quantity qrestfreq = restFreq.nelements() >0 ? restFreq[0]: Quantity(0.0, "Hz");
    3742          32 :           inStartFreq = MFrequency::fromDoppler(mdop, qrestfreq.getValue(Unit("Hz")), mfreqframe).getValue(); 
    3743          32 :         }
    3744             :       }
    3745             :     }
    3746             : 
    3747         945 :     return inStartFreq;
    3748             : 
    3749         945 :   }
    3750             : 
    3751        1514 :   String SynthesisParamsImage::findSpecMode(const String& mode) const
    3752             :   {
    3753        1514 :     String specmode;
    3754        1514 :     specmode="channel";
    3755        1514 :     if ( mode.contains("cube") ) {
    3756             :       // if velstart or velstep is defined -> specmode='vel'
    3757             :       // else if freqstart or freqstep is defined -> specmode='freq'
    3758             :       // velocity: assume unset if velStart => 0.0 with no unit
    3759             :       //           assume unset if velStep => 0.0 with/without unit
    3760        2054 :       if ( !(velStart.getValue()==0.0 && velStart.getUnit()=="" ) ||
    3761        1005 :            !( velStep.getValue()==0.0)) { 
    3762          64 :         specmode="velocity";
    3763             :       }
    3764        1875 :       else if ( !(freqStart.getValue()==0.0 && freqStart.getUnit()=="") ||
    3765         890 :                 !(freqStep.getValue()==0.0)) {
    3766         103 :         specmode="frequency";
    3767             :       }
    3768             :     }
    3769        1514 :     return specmode;
    3770           0 :   }
    3771             : 
    3772             : 
    3773        2830 :   Vector<Int> SynthesisParamsImage::decideNPolPlanes(const String& stokes) const
    3774             :   {
    3775        2830 :     Vector<Int> whichStokes(0);
    3776        3301 :     if(stokes=="I" || stokes=="Q" || stokes=="U" || stokes=="V" || 
    3777         567 :        stokes=="RR" ||stokes=="LL" || 
    3778        3301 :        stokes=="XX" || stokes=="YY" ) {
    3779        2647 :       whichStokes.resize(1);
    3780        2647 :       whichStokes(0)=Stokes::type(stokes);
    3781             :     }
    3782         519 :     else if(stokes=="IV" || stokes=="IQ" || 
    3783         498 :             stokes=="RRLL" || stokes=="XXYY" ||
    3784         513 :             stokes=="QU" || stokes=="UV"){
    3785          33 :       whichStokes.resize(2);
    3786             :       
    3787          33 :       if(stokes=="IV"){ whichStokes[0]=Stokes::I; whichStokes[1]=Stokes::V;}
    3788          18 :       else if(stokes=="IQ"){whichStokes[0]=Stokes::I; whichStokes[1]=Stokes::Q;}
    3789          18 :       else if(stokes=="RRLL"){whichStokes[0]=Stokes::RR; whichStokes[1]=Stokes::LL;}
    3790          18 :       else if(stokes=="XXYY"){whichStokes[0]=Stokes::XX; whichStokes[1]=Stokes::YY; }
    3791          12 :       else if(stokes=="QU"){whichStokes[0]=Stokes::Q; whichStokes[1]=Stokes::U; }
    3792           0 :       else if(stokes=="UV"){ whichStokes[0]=Stokes::U; whichStokes[1]=Stokes::V; }
    3793             :         
    3794             :     }
    3795             :   
    3796         150 :     else if(stokes=="IQU" || stokes=="IUV") {
    3797           0 :       whichStokes.resize(3);
    3798           0 :       if(stokes=="IUV")
    3799           0 :         {whichStokes[0]=Stokes::I; whichStokes[1]=Stokes::U; whichStokes[2]=Stokes::V;}
    3800             :       else
    3801           0 :         {whichStokes[0]=Stokes::I; whichStokes[1]=Stokes::Q; whichStokes[2]=Stokes::U;}
    3802             :     }
    3803         150 :     else if(stokes=="IQUV"){
    3804         150 :       whichStokes.resize(4);
    3805         150 :       whichStokes(0)=Stokes::I; whichStokes(1)=Stokes::Q;
    3806         150 :       whichStokes(2)=Stokes::U; whichStokes(3)=Stokes::V;
    3807             :     }
    3808             :       
    3809        2830 :     return whichStokes;
    3810           0 :   }// decidenpolplanes
    3811             : 
    3812        1887 :   IPosition SynthesisParamsImage::shp() const
    3813             :   {
    3814        1887 :     uInt nStokes = ( decideNPolPlanes(stokes) ).nelements();
    3815             : 
    3816        1887 :     if( imsize[0]<=0 || imsize[1]<=0 || nStokes<=0 || nchan<=0 )
    3817             :       {
    3818           1 :         throw(AipsError("Internal Error : Image shape is invalid : [" + String::toString(imsize[0]) + "," + String::toString(imsize[1]) + "," + String::toString(nStokes) + "," + String::toString(nchan) + "]" )); 
    3819             :       }
    3820             : 
    3821        3772 :     return IPosition( 4, imsize[0], imsize[1], nStokes, nchan );
    3822             :   }
    3823             : 
    3824         943 :   Record SynthesisParamsImage::getcsys() const
    3825             :   {
    3826         943 :       return csysRecord;
    3827             :   }
    3828             : 
    3829           0 :   Record SynthesisParamsImage::updateParams(const Record& impar)
    3830             :   {
    3831           0 :       Record newimpar( impar );
    3832           0 :       if ( impar.isDefined("csys") ) 
    3833             :        { 
    3834           0 :            Vector<Int> newimsize(2);
    3835           0 :            newimsize[0] = imshape[0];
    3836           0 :            newimsize[1] = imshape[1];
    3837           0 :            newimpar.define("imsize", newimsize);
    3838           0 :            if ( newimpar.isDefined("direction0") )
    3839             :              {
    3840           0 :                Record dirRec = newimpar.subRecord("direction0");
    3841           0 :                Vector<Double> cdelta = dirRec.asArrayDouble("cdelt");
    3842           0 :                Vector<String> cells(2);
    3843           0 :                cells[0] = String::toString(-1*cdelta[0]) + "rad";
    3844           0 :                cells[1] = String::toString(-1*cdelta[1]) + "rad";
    3845           0 :                newimpar.define("cell", cells );
    3846           0 :              } 
    3847           0 :            if ( newimpar.isDefined("stokes1") )
    3848             :              {
    3849           0 :                Record stokesRec = newimpar.subRecord("stokes1");
    3850           0 :                Vector<String> stokesvecs = stokesRec.asArrayString("stokes"); 
    3851           0 :                String stokesStr;
    3852           0 :                for (uInt j = 0; j < stokesvecs.nelements(); j++)
    3853             :                  {
    3854           0 :                      stokesStr+=stokesvecs[j];
    3855             :                  }
    3856           0 :              }
    3857           0 :            if ( newimpar.isDefined("nchan") ) 
    3858             :              {
    3859           0 :                newimpar.define("nchan",imshape[2]);
    3860             :              }
    3861           0 :            if ( newimpar.isDefined("spectral2") ) 
    3862             :              {
    3863           0 :                Record specRec = newimpar.subRecord("spectral2");
    3864           0 :                if ( specRec.isDefined("restfreqs") ) 
    3865             :                  {
    3866           0 :                    Vector<Double> restfs = specRec.asArrayDouble("restfreqs");
    3867           0 :                    Vector<String> restfstrs(restfs.nelements());
    3868           0 :                    for(uInt restf=0; restf<restfs.nelements(); restf++){restfstrs[restf] = String::toString(restfs[restf]) + "Hz";}
    3869           0 :                    newimpar.define("restfreq",restfstrs);
    3870           0 :                  }
    3871             :                //reffreq?
    3872             :                //outframe
    3873             :                //sysvel
    3874             :                //sysvelframe
    3875           0 :              }      
    3876           0 :         }
    3877           0 :       return newimpar;
    3878           0 :   }
    3879             : 
    3880             :  /////////////////////// Grid/FTMachine Parameters
    3881             : 
    3882        5551 :   SynthesisParamsGrid::SynthesisParamsGrid():SynthesisParams()
    3883             :   {
    3884        5551 :     setDefaults();
    3885        5551 :   }
    3886             : 
    3887        5550 :   SynthesisParamsGrid::~SynthesisParamsGrid()
    3888             :   {
    3889        5550 :   }
    3890             : 
    3891             : 
    3892        1847 :   void SynthesisParamsGrid::fromRecord(const Record &inrec)
    3893             :   {
    3894        1847 :     setDefaults();
    3895             : 
    3896        1847 :     String err("");
    3897             : 
    3898             :     try {
    3899        1847 :       err += readVal( inrec, String("imagename"), imageName );
    3900             : 
    3901             :       // FTMachine parameters
    3902        1847 :       err += readVal( inrec, String("gridder"), gridder );
    3903        1847 :       err += readVal( inrec, String("padding"), padding );
    3904        1847 :       err += readVal( inrec, String("useautocorr"), useAutoCorr );
    3905        1847 :       err += readVal( inrec, String("usedoubleprec"), useDoublePrec );
    3906        1847 :       err += readVal( inrec, String("wprojplanes"), wprojplanes );
    3907        1847 :       err += readVal( inrec, String("convfunc"), convFunc );
    3908             : 
    3909        1847 :       err += readVal( inrec, String("vptable"), vpTable );
    3910             : 
    3911             : 
    3912             : 
    3913             :       // convert 'gridder' to 'ftmachine' and 'mtype'
    3914        1847 :       ftmachine = "gridft";
    3915        1847 :       mType = "default";
    3916        1847 :       if (gridder=="ft" || gridder=="gridft" || gridder=="standard") {
    3917        1270 :         ftmachine = "gridft";
    3918             :       }
    3919         623 :       else if ( (gridder=="widefield" || gridder=="wproject" || gridder=="wprojectft" ) &&
    3920          46 :            (wprojplanes>1 || wprojplanes==-1) ) {
    3921          45 :         ftmachine = "wprojectft";
    3922             :       }
    3923             :         //facetting alone use gridft
    3924         532 :       else if( (gridder=="widefield" || gridder=="wproject" || gridder=="wprojectft" ) && (wprojplanes==1))
    3925           1 :           {ftmachine=="gridft";}
    3926             :       
    3927         531 :       else if (gridder=="ftmosaic" || gridder=="mosaicft" || gridder=="mosaic" ) {
    3928         222 :         ftmachine = "mosaicft";
    3929             :       }
    3930             : 
    3931         309 :       else if (gridder=="imagemosaic") {
    3932           0 :         mType = "imagemosaic";
    3933           0 :         if (wprojplanes>1 || wprojplanes==-1) {
    3934           0 :           ftmachine = "wprojectft";
    3935             :         }
    3936             :       }
    3937             : 
    3938         309 :       else if (gridder=="awproject" || gridder=="awprojectft" || gridder=="awp") {
    3939          93 :         ftmachine = "awprojectft";
    3940             :       }
    3941             : 
    3942         216 :       else if (gridder=="singledish") {
    3943             : 
    3944         160 :         ftmachine = "sd";
    3945             :       }
    3946             :       else{
    3947          56 :         ftmachine=gridder;
    3948          56 :         ftmachine.downcase();
    3949             :         
    3950             :       }
    3951             : 
    3952        1847 :       String deconvolver;
    3953        1847 :       err += readVal( inrec, String("deconvolver"), deconvolver );
    3954        1847 :       if (deconvolver=="mtmfs") {
    3955         122 :         mType = "multiterm"; // Takes precedence over imagemosaic
    3956             :       }
    3957             : 
    3958             :       // facets
    3959        1847 :       err += readVal( inrec, String("facets"), facets );
    3960             :       // chanchunks
    3961        1847 :       err += readVal( inrec, String("chanchunks"), chanchunks );
    3962             : 
    3963             :       // Spectral interpolation
    3964        1847 :       err += readVal( inrec, String("interpolation"), interpolation ); // not used in SI yet...
    3965             :       // Track moving source ?
    3966        1847 :       err += readVal( inrec, String("distance"), distance );
    3967        1847 :       err += readVal( inrec, String("tracksource"), trackSource );
    3968        1847 :       err += readVal( inrec, String("trackdir"), trackDir );
    3969             : 
    3970             :       // The extra params for WB-AWP
    3971        1847 :       err += readVal( inrec, String("aterm"), aTermOn );
    3972        1847 :       err += readVal( inrec, String("psterm"), psTermOn );
    3973        1847 :       err += readVal( inrec, String("mterm"), mTermOn );
    3974        1847 :       err += readVal( inrec, String("wbawp"), wbAWP );
    3975        1847 :       err += readVal( inrec, String("cfcache"), cfCache );
    3976        1847 :       err += readVal( inrec, String("usepointing"), usePointing );
    3977        1847 :       err += readVal( inrec, String("pointingoffsetsigdev"), pointingOffsetSigDev );
    3978        1847 :       err += readVal( inrec, String("dopbcorr"), doPBCorr );
    3979        1847 :       err += readVal( inrec, String("conjbeams"), conjBeams );
    3980        1847 :       err += readVal( inrec, String("computepastep"), computePAStep );
    3981        1847 :       err += readVal( inrec, String("rotatepastep"), rotatePAStep );
    3982             : 
    3983             :       // The extra params for single-dish
    3984        1847 :       err += readVal( inrec, String("pointingcolumntouse"), pointingDirCol );
    3985        1847 :       err += readVal( inrec, String("convertfirst"), convertFirst );
    3986        1847 :       err += readVal( inrec, String("skypolthreshold"), skyPosThreshold );
    3987        1847 :       err += readVal( inrec, String("convsupport"), convSupport );
    3988        1847 :       err += readVal( inrec, String("truncate"), truncateSize );
    3989        1847 :       err += readVal( inrec, String("gwidth"), gwidth );
    3990        1847 :       err += readVal( inrec, String("jwidth"), jwidth );
    3991        1847 :       err += readVal( inrec, String("minweight"), minWeight );
    3992        1847 :       err += readVal( inrec, String("clipminmax"), clipMinMax );
    3993             : 
    3994             :       // Single or MultiTerm mapper : read in 'deconvolver' and set mType here.
    3995             :       // err += readVal( inrec, String("mtype"), mType );
    3996             : 
    3997        1847 :       if (ftmachine=="awprojectft" && cfCache=="") {
    3998           0 :         cfCache = imageName + ".cf";
    3999             :       }
    4000             : 
    4001        1847 :       if ( ftmachine=="awprojectft" &&
    4002        1881 :            usePointing==True &&
    4003          34 :            pointingOffsetSigDev.nelements() != 2 ) {
    4004             :           // Set the default to a large value so that it behaves like CASA 5.6's usepointing=True.
    4005           8 :           pointingOffsetSigDev.resize(2);
    4006           8 :           pointingOffsetSigDev[0] = 600.0;
    4007           8 :           pointingOffsetSigDev[1] = 600.0;
    4008             :       }
    4009             : 
    4010        1847 :       err += verify();
    4011             : 
    4012        1847 :        } catch(AipsError &x) {
    4013           0 :       err = err + x.getMesg() + "\n";
    4014           0 :     }
    4015             : 
    4016        1847 :     if (err.length()>0) {
    4017           0 :       throw(AipsError("Invalid Gridding/FTM Parameter set: " + err));
    4018             :     }
    4019             : 
    4020        1847 :   }
    4021             : 
    4022        1847 :   String SynthesisParamsGrid::verify() const
    4023             :   {
    4024        1847 :     String err;
    4025             : 
    4026             :     // Check for valid FTMachine type.
    4027             :     // Valid other params per FTM type, etc... ( check about nterms>1 )
    4028             : 
    4029             : 
    4030             : 
    4031        1847 :     if ( imageName == "" ) {
    4032           0 :       err += "Please supply an image name\n";
    4033             :     }
    4034             : 
    4035        1107 :     if( (ftmachine != "gridft") && (ftmachine != "wprojectft") && 
    4036        2847 :         (ftmachine != "mosaicft") && (ftmachine.at(0,3) != "awp") && 
    4037        2583 :         (ftmachine != "mawprojectft")  &&
    4038         160 :         (ftmachine != "sd"))
    4039             :      {
    4040             :       err += "Invalid ftmachine name. Must be one of"
    4041             :         " 'gridft', 'wprojectft',"
    4042             :         " 'mosaicft', 'awprojectft',"
    4043             :         " 'mawpojectft', 'protoft',"
    4044           0 :         " 'sd'\n";
    4045             :     }
    4046             : 
    4047             : 
    4048        3787 :     if ( ( ftmachine == "mosaicft"    and mType == "imagemosaic" ) or
    4049        1940 :          ( ftmachine == "awprojectft" and mType == "imagemosaic" ) ) {
    4050           0 :       err +=  "Cannot use " + ftmachine + " with " + mType +
    4051             :         " because it is a redundant choice for mosaicing."
    4052             :         " In the future, we may support the combination"
    4053             :         " to signal the use of single-pointing sized image grids"
    4054             :         " during gridding and iFT,"
    4055             :         " and only accumulating it on the large mosaic image."
    4056             :         " For now, please set"
    4057             :         " either mappertype='default' to get mosaic gridding"
    4058           0 :         " or ftmachine='ft' or 'wprojectft' to get image domain mosaics.\n";
    4059             :     }
    4060             : 
    4061        1847 :     if ( facets < 1 ) {
    4062           0 :       err += "Must have at least 1 facet\n";
    4063             :     }
    4064             : 
    4065             :     //if( chanchunks < 1 )
    4066             :     //  {err += "Must have at least 1 chanchunk\n"; }
    4067        1847 :     if ( facets > 1 and chanchunks > 1 ) {
    4068             :       err += "The combination of facetted imaging"
    4069             :         " with channel chunking is not yet supported."
    4070           0 :         " Please choose only one or the other for now.\n";
    4071             :     }
    4072             : 
    4073        1847 :     if ( ftmachine == "wproject" and ( wprojplanes == 0 or wprojplanes == 1 ) ) {
    4074             :       err += "The wproject gridder must be accompanied with"
    4075           0 :         " wprojplanes>1 or wprojplanes=-1\n";
    4076             :     }
    4077             : 
    4078        1847 :     if ( ftmachine == "awprojectft" and facets > 1 ) {
    4079             :       err += "The awprojectft gridder supports A- and W-Projection."
    4080             :         " Instead of using facets>1 to deal with the W-term,"
    4081             :         " please set the number of wprojplanes to a value > 1"
    4082           0 :         " to trigger the combined AW-Projection algorithm. \n";
    4083             :       // Also, the way the AWP cfcache is managed,
    4084             :       // even if all facets share a common one so that they reuse convolution functions,
    4085             :       // the first facet's gridder writes out the avgPB
    4086             :       // and all others see that it's there and don't compute their own.
    4087             :       // As a result, the code will run,
    4088             :       // but the first facet's weight image will be duplicated for all facets.
    4089             :       // If needed, this must be fixed in the way the AWP gridder manages its cfcache.
    4090             :       // But, since the AWP gridder supports joint A and W projection,
    4091             :       // facet support may never be needed in the first place...
    4092             :     }
    4093             : 
    4094        1847 :     if ( ftmachine == "awprojectft" and wprojplanes == -1 ) {
    4095             :       err += "The awprojectft gridder does not support wprojplanes=-1"
    4096           0 :         " for automatic calculation. Please pick a value >1\n";
    4097             :     }
    4098             : 
    4099        1847 :     if ( ftmachine == "mosaicft" and facets > 1 ) {
    4100             :       err += "The combination of mosaicft gridding"
    4101             :         " with multiple facets is not supported."
    4102             :         " Please use the awprojectft gridder instead,"
    4103           0 :         " and set wprojplanes to a value > 1 to trigger AW-Projection.\n";
    4104             :     }
    4105             : 
    4106        1881 :     if ( ftmachine == "awprojectft" and usePointing == True and
    4107          34 :          pointingOffsetSigDev.nelements() != 2 ) {
    4108             :       err += "The pointingoffsetsigdev parameter must be"
    4109             :         " a two-element vector of doubles in order to be used with usepointing=True"
    4110           0 :         " and the AWProject gridder. Setting it to the default of \n";
    4111             :     }
    4112             : 
    4113             :     // Single-dish parameters check
    4114        1847 :     if ( ftmachine == "sd" ) {
    4115         320 :       if ( convertFirst != "always" and
    4116         320 :            convertFirst != "never" and
    4117           0 :            convertFirst != "auto" ) {
    4118           0 :         err += "convertfirst parameter: illegal value: '" + convertFirst + "'."
    4119           0 :           " Allowed values: 'always', 'never', 'auto'.\n";
    4120             :       }
    4121             :     }
    4122             : 
    4123        1847 :     return err;
    4124           0 :   }
    4125             : 
    4126        7398 :   void SynthesisParamsGrid::setDefaults()
    4127             :   {
    4128        7398 :     imageName="";
    4129             :     // FTMachine parameters
    4130             :     //ftmachine="GridFT";
    4131        7398 :     ftmachine="gridft";
    4132        7398 :     gridder=ftmachine;
    4133        7398 :     padding=1.2;
    4134        7398 :     useAutoCorr=false;
    4135        7398 :     useDoublePrec=true; 
    4136        7398 :     wprojplanes=1; 
    4137        7398 :     convFunc="SF"; 
    4138        7398 :     vpTable="";
    4139             :     
    4140             :     // facets
    4141        7398 :     facets=1;
    4142             : 
    4143             :     // chanchunks
    4144        7398 :     chanchunks=1;
    4145             : 
    4146             :     // Spectral Axis interpolation
    4147        7398 :     interpolation=String("nearest");
    4148             : 
    4149             :     //mosaic use pointing
    4150        7398 :     usePointing=false;
    4151             :     // Moving phase center ?
    4152        7398 :     distance=Quantity(0,"m");
    4153        7398 :     trackSource=false;
    4154        7398 :     trackDir=MDirection(Quantity(0.0, "deg"), Quantity(90.0, "deg"));
    4155             : 
    4156             :     // The extra params for WB-AWP
    4157        7398 :     aTermOn    = true;
    4158        7398 :     psTermOn   = true;
    4159        7398 :     mTermOn    = false;
    4160        7398 :     wbAWP      = true;
    4161        7398 :     cfCache  = "";
    4162        7398 :     usePointing = false;
    4163        7398 :     pointingOffsetSigDev.resize(0);
    4164             :     //    pointingOffsetSigDev.set(30.0);
    4165        7398 :     doPBCorr   = true;
    4166        7398 :     conjBeams  = true;
    4167        7398 :     computePAStep=360.0;
    4168        7398 :     rotatePAStep=5.0;
    4169             : 
    4170             :     // extra params for single-dish
    4171        7398 :     pointingDirCol = "";
    4172        7398 :     convertFirst = "never";
    4173        7398 :     skyPosThreshold = 0.0;
    4174        7398 :     convSupport = -1;
    4175        7398 :     truncateSize = Quantity(-1.0);
    4176        7398 :     gwidth = Quantity(-1.0);
    4177        7398 :     jwidth = Quantity(-1.0);
    4178        7398 :     minWeight = 0.0;
    4179        7398 :     clipMinMax = False;
    4180             : 
    4181             :     // Mapper type
    4182        7398 :     mType = String("default");
    4183             :     
    4184        7398 :   }
    4185             : 
    4186         899 :   Record SynthesisParamsGrid::toRecord() const
    4187             :   {
    4188         899 :     Record gridpar;
    4189             : 
    4190         899 :     gridpar.define("imagename", imageName);
    4191             :     // FTMachine params
    4192         899 :     gridpar.define("padding", padding);
    4193         899 :     gridpar.define("useautocorr",useAutoCorr );
    4194         899 :     gridpar.define("usedoubleprec", useDoublePrec);
    4195         899 :     gridpar.define("wprojplanes", wprojplanes);
    4196         899 :     gridpar.define("convfunc", convFunc);
    4197         899 :     gridpar.define("vptable", vpTable);
    4198             : 
    4199         899 :     gridpar.define("facets", facets);
    4200         899 :     gridpar.define("chanchunks", chanchunks);
    4201             :     
    4202         899 :     gridpar.define("interpolation",interpolation);
    4203             : 
    4204         899 :     gridpar.define("distance", QuantityToString(distance));
    4205         899 :     gridpar.define("tracksource", trackSource);
    4206         899 :     gridpar.define("trackdir", MDirectionToString( trackDir ));
    4207             : 
    4208         899 :     gridpar.define("aterm",aTermOn );
    4209         899 :     gridpar.define("psterm",psTermOn );
    4210         899 :     gridpar.define("mterm",mTermOn );
    4211         899 :     gridpar.define("wbawp", wbAWP);
    4212         899 :     gridpar.define("cfcache", cfCache);
    4213         899 :     gridpar.define("usepointing",usePointing );
    4214         899 :     gridpar.define("pointingoffsetsigdev", pointingOffsetSigDev);
    4215         899 :     gridpar.define("dopbcorr", doPBCorr);
    4216         899 :     gridpar.define("conjbeams",conjBeams );
    4217         899 :     gridpar.define("computepastep", computePAStep);
    4218         899 :     gridpar.define("rotatepastep", rotatePAStep);
    4219             : 
    4220         899 :     gridpar.define("pointingcolumntouse", pointingDirCol );
    4221         899 :     gridpar.define("convertfirst", convertFirst );
    4222         899 :     gridpar.define("skyposthreshold", skyPosThreshold );
    4223         899 :     gridpar.define("convsupport", convSupport );
    4224         899 :     gridpar.define("truncate", QuantityToString(truncateSize) );
    4225         899 :     gridpar.define("gwidth", QuantityToString(gwidth) );
    4226         899 :     gridpar.define("jwidth", QuantityToString(jwidth) );
    4227         899 :     gridpar.define("minweight", minWeight );
    4228         899 :     gridpar.define("clipminmax", clipMinMax );
    4229             : 
    4230         899 :     if( mType=="multiterm") gridpar.define("deconvolver","mtmfs");
    4231             :     ///    else gridpar.define("deconvolver","singleterm");
    4232             : 
    4233         899 :     if( mType=="imagemosaic") gridpar.define("gridder","imagemosaic");
    4234         899 :     else gridpar.define("gridder", gridder);
    4235             : 
    4236             :     //    gridpar.define("mtype", mType);
    4237             : 
    4238         899 :     return gridpar;
    4239           0 :   }
    4240             : 
    4241             : 
    4242             : 
    4243             :   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    4244             : 
    4245             :  /////////////////////// Deconvolver Parameters
    4246             : 
    4247        2526 :   SynthesisParamsDeconv::SynthesisParamsDeconv():SynthesisParams()
    4248             :   {
    4249        2526 :     setDefaults();
    4250        2526 :   }
    4251             : 
    4252        2526 :   SynthesisParamsDeconv::~SynthesisParamsDeconv()
    4253             :   {
    4254        2526 :   }
    4255             : 
    4256             : 
    4257        2522 :   void SynthesisParamsDeconv::fromRecord(const Record &inrec)
    4258             :   {
    4259        2522 :     setDefaults();
    4260             : 
    4261        2522 :     String err("");
    4262             : 
    4263             :     try
    4264             :       {
    4265             :         
    4266        2522 :         err += readVal( inrec, String("imagename"), imageName );
    4267        2522 :         err += readVal( inrec, String("deconvolver"), algorithm );
    4268             : 
    4269             : 
    4270             :         //err += readVal( inrec, String("startmodel"), startModel );
    4271             :         // startmodel parsing copied from SynthesisParamsImage. Clean this up !!!
    4272        2522 :         if( inrec.isDefined("startmodel") ) 
    4273             :           {
    4274        2522 :             if( inrec.dataType("startmodel")==TpString )
    4275             :               {
    4276         838 :                 String onemodel;
    4277         838 :                 err += readVal( inrec, String("startmodel"), onemodel );
    4278         838 :                 if( onemodel.length()>0 )
    4279             :                   {
    4280          22 :                     startModel.resize(1);
    4281          22 :                     startModel[0] = onemodel;
    4282             :                   }
    4283         816 :                 else {startModel.resize();}
    4284         838 :               }
    4285        3370 :             else if( inrec.dataType("startmodel")==TpArrayString || 
    4286        1686 :                      inrec.dataType("startmodel")==TpArrayBool)
    4287             :               {
    4288        1684 :                 err += readVal( inrec, String("startmodel"), startModel );
    4289             :               }
    4290             :             else {
    4291           0 :               err += String("startmodel must be either a string(singleterm) or a list of strings(multiterm)\n");
    4292             :               }
    4293             :           }
    4294             :         //------------------------
    4295             : 
    4296        2522 :         err += readVal( inrec, String("id"), deconvolverId );
    4297        2522 :         err += readVal( inrec, String("nterms"), nTaylorTerms );
    4298             : 
    4299        2522 :         err += readVal( inrec, String("scales"), scales );
    4300        2522 :         err += readVal( inrec, String("scalebias"), scalebias );
    4301             : 
    4302        2522 :         err += readVal( inrec, String("usemask"), maskType );
    4303        2522 :         if( maskType=="auto-thresh" ) 
    4304             :           {
    4305           0 :             autoMaskAlgorithm = "thresh";
    4306             :           }
    4307        2522 :         else if( maskType=="auto-thesh2" )
    4308             :           {
    4309           0 :             autoMaskAlgorithm = "thresh2";
    4310             :           }
    4311        2522 :         else if( maskType=="auto-onebox" ) 
    4312             :           {
    4313           0 :             autoMaskAlgorithm = "onebox";
    4314             :           }
    4315        2522 :         else if( maskType=="user" || maskType=="pb" )
    4316             :           {
    4317        2415 :             autoMaskAlgorithm = "";
    4318             :           }
    4319             :               
    4320             : 
    4321        2522 :         if( inrec.isDefined("mask") ) 
    4322             :           {
    4323        2522 :             if( inrec.dataType("mask")==TpString )
    4324             :               {
    4325        1968 :                 err+= readVal( inrec, String("mask"), maskString );
    4326             :               }
    4327         554 :             else if( inrec.dataType("mask")==TpArrayString ) 
    4328             :               {
    4329         552 :                 err+= readVal( inrec, String("mask"), maskList );
    4330             :               }
    4331             :            }
    4332             :         
    4333        2522 :         if( inrec.isDefined("pbmask") )
    4334             :           {
    4335        2522 :             err += readVal( inrec, String("pbmask"), pbMask ); 
    4336             :           }
    4337        2522 :         if( inrec.isDefined("maskthreshold") ) 
    4338             :           {
    4339        2522 :             if( inrec.dataType("maskthreshold")==TpString )
    4340             :               {
    4341        2522 :                 err += readVal( inrec, String("maskthreshold"), maskThreshold );
    4342             :                 //deal with the case a string is a float value without unit
    4343        2522 :                 Quantity testThresholdString;
    4344        2522 :                 Quantity::read(testThresholdString,maskThreshold);
    4345        2522 :                 if( testThresholdString.getUnit()=="" )
    4346             :                   {
    4347        2522 :                     if(testThresholdString.getValue()<1.0)
    4348             :                       {
    4349        2522 :                           fracOfPeak = testThresholdString.getValue();
    4350        2522 :                           maskThreshold=String("");
    4351             :                       }
    4352             :                   }
    4353        2522 :               }
    4354           0 :             else if( inrec.dataType("maskthreshold")==TpFloat || inrec.dataType("maskthreshold")==TpDouble )
    4355             :               {
    4356             : 
    4357           0 :                 err += readVal( inrec, String("maskthreshold"), fracOfPeak );
    4358           0 :                 if( fracOfPeak >=1.0 ) 
    4359             :                   {
    4360             :                     // maskthreshold is sigma ( * rms = threshold) 
    4361             :                     //
    4362           0 :                     maskThreshold=String::toString(fracOfPeak);
    4363           0 :                     fracOfPeak=0.0;
    4364             :                   }
    4365             :               }
    4366             :             else 
    4367             :               {
    4368           0 :                 err += "maskthreshold must be a string, float, or double\n";
    4369             :               }
    4370             :            }
    4371        2522 :         if( inrec.isDefined("maskresolution") ) 
    4372             :           { 
    4373        2522 :             if( inrec.dataType("maskresolution")==TpString )
    4374             :               {
    4375        2522 :                 err += readVal(inrec, String("maskresolution"), maskResolution );
    4376             :                 //deal with the case a string is a float value without unit
    4377        2522 :                 Quantity testResolutionString;
    4378        2522 :                 Quantity::read(testResolutionString,maskResolution);
    4379        2522 :                 if( testResolutionString.getUnit()=="" )
    4380             :                   {
    4381        2522 :                       maskResByBeam = testResolutionString.getValue();
    4382        2522 :                       maskResolution=String("");
    4383             :                   }
    4384        2522 :               }
    4385           0 :             else if( inrec.dataType("maskresolution")==TpFloat || inrec.dataType("maskresolution")==TpDouble )
    4386             :               {
    4387             : 
    4388           0 :                 err += readVal( inrec, String("maskresolution"), maskResByBeam );
    4389             :               }
    4390             :             else 
    4391             :               {
    4392           0 :                 err += "maskresolution must be a string, float, or double\n";
    4393             :               }
    4394             :            }
    4395             :              
    4396             :        
    4397        2522 :         if( inrec.isDefined("nmask") ) 
    4398             :           {
    4399        2522 :             if( inrec.dataType("nmask")==TpInt )
    4400             :               {
    4401        2522 :                 err+= readVal(inrec, String("nmask"), nMask );
    4402             :               }
    4403             :             else 
    4404             :               {
    4405           0 :                 err+= "nmask must be an integer\n";
    4406             :               }
    4407             :           }
    4408        2522 :         if( inrec.isDefined("autoadjust") )
    4409             :           {
    4410        1675 :             if( inrec.dataType("autoadjust")==TpBool )
    4411             :               {
    4412        1675 :                 err+= readVal(inrec, String("autoadjust"), autoAdjust );
    4413             :               }
    4414             :             else 
    4415             :               {
    4416           0 :                 err+= "autoadjust must be a bool\n";
    4417             :               }
    4418             :           }
    4419             :         //param for the Asp-Clean to trigger Hogbom Clean
    4420        2522 :         if (inrec.isDefined("fusedthreshold"))
    4421             :         {
    4422        2522 :           if (inrec.dataType("fusedthreshold") == TpFloat || inrec.dataType("fusedthreshold") == TpDouble)
    4423        2522 :             err += readVal(inrec, String("fusedthreshold"), fusedThreshold);
    4424             :           else 
    4425           0 :             err += "fusedthreshold must be a float or double";
    4426             :         }
    4427        2522 :          if (inrec.isDefined("specmode"))
    4428             :         {
    4429        2522 :           if(inrec.dataType("specmode") == TpString)
    4430        2522 :             err += readVal(inrec, String("specmode"), specmode);
    4431             :           else 
    4432           0 :             err += "specmode must be a string";
    4433             :         }
    4434             :         //largest scale size for the Asp-Clean to overwrite the default
    4435        2522 :         if (inrec.isDefined("largestscale"))
    4436             :         {
    4437        2522 :           if (inrec.dataType("largestscale") == TpInt)
    4438        2522 :             err += readVal(inrec, String("largestscale"), largestscale);
    4439             :           else 
    4440           0 :             err += "largestscale must be an integer";
    4441             :         }
    4442             :         //params for the new automasking algorithm
    4443        2522 :         if( inrec.isDefined("sidelobethreshold"))
    4444             :           {
    4445        2522 :             if(inrec.dataType("sidelobethreshold")==TpFloat || inrec.dataType("sidelobethreshold")==TpDouble )
    4446             :               {
    4447        2522 :                 err+= readVal(inrec, String("sidelobethreshold"), sidelobeThreshold );
    4448             :               }
    4449             :             else 
    4450             :               {
    4451           0 :                 err+= "sidelobethreshold must be a float or double";
    4452             :               }
    4453             :           }
    4454             : 
    4455        2522 :         if( inrec.isDefined("noisethreshold"))
    4456             :           {
    4457        2522 :             if(inrec.dataType("noisethreshold")==TpFloat || inrec.dataType("noisethreshold")==TpDouble )
    4458             :               {
    4459        2522 :                 err+= readVal(inrec, String("noisethreshold"), noiseThreshold );
    4460             :               }
    4461             :             else 
    4462             :               {
    4463           0 :                 err+= "noisethreshold must be a float or double";
    4464             :               }
    4465             :           }
    4466        2522 :         if( inrec.isDefined("lownoisethreshold"))
    4467             :           {
    4468        2522 :             if(inrec.dataType("lownoisethreshold")==TpFloat || inrec.dataType("lownoisethreshold")==TpDouble )
    4469             :               {
    4470        2522 :                 err+= readVal(inrec, String("lownoisethreshold"), lowNoiseThreshold );
    4471             :               }
    4472             :             else 
    4473             :               {
    4474           0 :                 err+= "lownoisethreshold must be a float or double";
    4475             :               }
    4476             :           }
    4477        2522 :         if( inrec.isDefined("negativethreshold"))
    4478             :           {
    4479        2522 :             if(inrec.dataType("negativethreshold")==TpFloat || inrec.dataType("negativethreshold")==TpDouble )
    4480             :               {
    4481        2522 :                 err+= readVal(inrec, String("negativethreshold"), negativeThreshold );
    4482             :               }
    4483             :             else 
    4484             :               {
    4485           0 :                 err+= "negativethreshold must be a float or double";
    4486             :               }
    4487             :           }
    4488        2522 :         if( inrec.isDefined("smoothfactor"))
    4489             :           {
    4490        2522 :             if( inrec.dataType("smoothfactor")==TpFloat || inrec.dataType("smoothfactor")==TpDouble )
    4491             :               {
    4492        2522 :                 err+= readVal(inrec, String("smoothfactor"), smoothFactor );
    4493             :               }
    4494             :             else 
    4495             :               {
    4496           0 :                 err+= "smoothfactor must be a float or double";
    4497             :               }
    4498             :           }
    4499        2522 :         if( inrec.isDefined("minbeamfrac"))
    4500             :           {
    4501        2522 :             if( inrec.dataType("minbeamfrac")==TpFloat || inrec.dataType("minbeamfrac")==TpDouble )
    4502             :               {
    4503        2522 :                 err+= readVal(inrec, String("minbeamfrac"), minBeamFrac );
    4504             :               }
    4505             :             else 
    4506             :               {
    4507           0 :                 if (inrec.dataType("minbeamfrac")==TpInt) {
    4508           0 :                   cerr<<"minbeamfrac is int"<<endl;
    4509             :                 }
    4510           0 :                 if (inrec.dataType("minbeamfrac")==TpString) {
    4511           0 :                   cerr<<"minbeamfrac is String"<<endl;
    4512             :                 }
    4513           0 :                 err+= "minbeamfrac must be a float or double";
    4514             :               }
    4515             :           }
    4516        2522 :         if( inrec.isDefined("cutthreshold"))
    4517             :           {
    4518        2522 :             if( inrec.dataType("cutthreshold")==TpFloat || inrec.dataType("cutthreshold")==TpDouble )
    4519             :               {
    4520        2522 :                 err+= readVal(inrec, String("cutthreshold"), cutThreshold );
    4521             :               }
    4522             :             else {
    4523           0 :                 err+= "cutthreshold must be a float or double";
    4524             :             }
    4525             :           }
    4526        2522 :         if( inrec.isDefined("growiterations"))
    4527             :           {
    4528        2522 :             if (inrec.dataType("growiterations")==TpInt) {
    4529        2522 :                 err+= readVal(inrec, String("growiterations"), growIterations );
    4530             :             }
    4531             :             else {
    4532           0 :                 err+= "growiterations must be an integer\n";
    4533             :             }
    4534             :           } 
    4535        2522 :         if( inrec.isDefined("dogrowprune"))
    4536             :           {
    4537        2522 :             if (inrec.dataType("dogrowprune")==TpBool) {
    4538        2522 :                 err+= readVal(inrec, String("dogrowprune"), doGrowPrune );
    4539             :             }
    4540             :             else {
    4541           0 :                 err+= "dogrowprune must be a bool\n";
    4542             :             }
    4543             :           } 
    4544        2522 :         if( inrec.isDefined("minpercentchange"))
    4545             :           {
    4546        2522 :             if (inrec.dataType("minpercentchange")==TpFloat || inrec.dataType("minpercentchange")==TpDouble ) {
    4547        2522 :                 err+= readVal(inrec, String("minpercentchange"), minPercentChange );
    4548             :             }
    4549             :             else {
    4550           0 :                 err+= "minpercentchange must be a float or double";
    4551             :             }
    4552             :           }
    4553        2522 :         if( inrec.isDefined("verbose")) 
    4554             :           {
    4555        2522 :             if (inrec.dataType("verbose")==TpBool ) {
    4556        2522 :                err+= readVal(inrec, String("verbose"), verbose);
    4557             :             }
    4558             :             else {
    4559           0 :                err+= "verbose must be a bool";
    4560             :             }
    4561             :           }
    4562        2522 :         if( inrec.isDefined("fastnoise"))
    4563             :           {
    4564        2522 :             if (inrec.dataType("fastnoise")==TpBool ) {
    4565        2522 :                err+= readVal(inrec, String("fastnoise"), fastnoise);
    4566             :             }
    4567             :             else {
    4568           0 :                err+= "fastnoise must be a bool";
    4569             :             }
    4570             :           }
    4571        2522 :         if( inrec.isDefined("nsigma") )
    4572             :           {
    4573        2522 :             if(inrec.dataType("nsigma")==TpFloat || inrec.dataType("nsigma")==TpDouble ) {
    4574        2522 :                err+= readVal(inrec, String("nsigma"), nsigma );
    4575             :               }
    4576           0 :             else if(inrec.dataType("nsigma")==TpInt)
    4577             :               {
    4578             :                 int tnsigma;
    4579           0 :                 err+= readVal(inrec, String("nsigma"), tnsigma );
    4580           0 :                 nsigma = float(tnsigma);
    4581             :               }
    4582             :             else {
    4583           0 :                err+= "nsigma must be an int, float or double";
    4584             :             }
    4585             :           }
    4586        2522 :         if( inrec.isDefined("noRequireSumwt") )
    4587             :           {
    4588        1861 :             if (inrec.dataType("noRequireSumwt")==TpBool) {
    4589        1861 :               err+= readVal(inrec, String("noRequireSumwt"), noRequireSumwt);
    4590             :             }
    4591             :             else {
    4592           0 :               err+= "noRequireSumwt must be a bool";
    4593             :             }
    4594             :           }
    4595        2522 :         if( inrec.isDefined("fullsummary") )
    4596             :           {
    4597        2522 :             if (inrec.dataType("fullsummary")==TpBool) {
    4598        2522 :               err+= readVal(inrec, String("fullsummary"), fullsummary);
    4599             :             }
    4600             :             else {
    4601           0 :               err+= "fullsummary must be a bool";
    4602             :             }
    4603             :           }
    4604        2522 :         if( inrec.isDefined("restoringbeam") )     
    4605             :           {
    4606         847 :             String errinfo("");
    4607             :             try {
    4608             :               
    4609         847 :               if( inrec.dataType("restoringbeam")==TpString )     
    4610             :                 {
    4611          16 :                   err += readVal( inrec, String("restoringbeam"), usebeam);
    4612             :           // FIXME ! usebeam.length() == 0 is a poorly formed conditional, it
    4613             :           // probably needs simplification or parenthesis, the compiler is
    4614             :           // compaining about it
    4615          16 :                   if( (! usebeam.matches("common")) && usebeam.length()!=0 )
    4616             :                     {
    4617           4 :                       Quantity bsize;
    4618           4 :                       err += readVal( inrec, String("restoringbeam"), bsize );
    4619           4 :                       restoringbeam.setMajorMinor( bsize, bsize );
    4620           4 :                       usebeam = String("");
    4621           4 :                     }
    4622          16 :                   errinfo = usebeam;
    4623             :                 }
    4624         831 :               else if( inrec.dataType("restoringbeam")==TpArrayString )
    4625             :                 {
    4626           0 :                   Vector<String> bpars;
    4627           0 :                   err += readVal( inrec, String("restoringbeam"), bpars );
    4628             : 
    4629           0 :                   for (uInt i=0;i<bpars.nelements();i++) { errinfo += bpars[i] + " "; }
    4630             : 
    4631           0 :                   if( bpars.nelements()==1 && bpars[0].length()>0 ) { 
    4632           0 :                     if( bpars[0]=="common") { usebeam="common"; }
    4633             :                     else {
    4634           0 :                       Quantity axis; stringToQuantity( bpars[0] , axis);
    4635           0 :                       restoringbeam.setMajorMinor( axis, axis ); 
    4636           0 :                     }
    4637           0 :                   }else if( bpars.nelements()==2 ) { 
    4638           0 :                     Quantity majaxis, minaxis;
    4639           0 :                     stringToQuantity( bpars[0], majaxis ); stringToQuantity( bpars[1], minaxis );
    4640           0 :                     restoringbeam.setMajorMinor( majaxis, minaxis );
    4641           0 :                   }else if( bpars.nelements()==3 ) {
    4642           0 :                     Quantity majaxis, minaxis, pa;
    4643           0 :                     stringToQuantity( bpars[0], majaxis ); stringToQuantity( bpars[1], minaxis ); stringToQuantity( bpars[2], pa );
    4644           0 :                     restoringbeam.setMajorMinor( majaxis, minaxis );
    4645           0 :                     restoringbeam.setPA( pa );
    4646           0 :                   }else {
    4647           0 :                     restoringbeam = GaussianBeam();
    4648           0 :                     usebeam = String("");
    4649             :                   }
    4650           0 :                 }
    4651           0 :             } catch( AipsError &x) {
    4652           0 :               err += "Cannot construct a restoringbeam from supplied parameters " + errinfo + ". Please check that majoraxis >= minoraxis and all entries are strings.";
    4653           0 :               restoringbeam = GaussianBeam();
    4654           0 :               usebeam = String("");
    4655           0 :             }
    4656             :             
    4657         847 :           }// if isdefined(restoringbeam)
    4658             : 
    4659        2522 :         if( inrec.isDefined("interactive") ) 
    4660             :           {    
    4661        2522 :             if( inrec.dataType("interactive")==TpBool )     
    4662        2522 :               {err += readVal( inrec, String("interactive"), interactive );}
    4663           0 :             else if ( inrec.dataType("interactive")==TpInt )
    4664           0 :               {Int inter=0; err += readVal( inrec, String("interactive"), inter); interactive=(Bool)inter;}
    4665             :           }
    4666             : 
    4667             :         //err += readVal( inrec, String("interactive"), interactive );
    4668             :         
    4669        2522 :         err += verify();
    4670             :         
    4671             :       }
    4672           0 :     catch(AipsError &x)
    4673             :       {
    4674           0 :         err = err + x.getMesg() + "\n";
    4675           0 :       }
    4676             :       
    4677        2522 :       if( err.length()>0 ) throw(AipsError("Invalid Deconvolver Parameter set : " + err));
    4678             :       
    4679        2522 :   }
    4680             : 
    4681        2522 :   String SynthesisParamsDeconv::verify() const
    4682             :   {
    4683        2522 :     String err;
    4684             : 
    4685        2522 :     if( imageName=="" ) {err += "Please supply an image name\n";}
    4686             :     
    4687             :     // Allow mask inputs in only one way. User specified OR already on disk. Not both
    4688        2522 :     if( maskString.length()>0 )
    4689             :       {
    4690         170 :           File fp( imageName+".mask" );
    4691         170 :           if( fp.exists() ) err += "Mask image " + imageName+".mask exists, but a specific input mask of " + maskString + " has also been supplied. Please either reset mask='' to reuse the existing mask, or delete " + imageName + ".mask before restarting";
    4692         170 :       }
    4693             : 
    4694        2522 :     if( pbMask >= 1.0)
    4695           0 :       {err += "pbmask must be < 1.0 \n"; }
    4696        2522 :     else if( pbMask < 0.0)
    4697           0 :       {err += "pbmask must be a positive value \n"; }
    4698             : 
    4699        2522 :     if(  maskType=="none" ) 
    4700             :       {
    4701           0 :         if( maskString!="" || (maskList.nelements()!=0 && maskList[0]!="") )
    4702             :           {
    4703           0 :            cerr<<"maskString="<<maskString<<endl;
    4704           0 :            cerr<<"maskList.nelements()="<<maskList.nelements()<<" maskList[0]="<<maskList[0]<<endl;
    4705           0 :            err += "mask is specified but usemask='none'. Please set usemask='user' to use the mask parameter\n";}
    4706             :       } 
    4707        2522 :     if ( fracOfPeak >= 1.0) 
    4708           0 :       {err += "fracofpeak must be < 1.0 \n"; }
    4709        2522 :     else if ( fracOfPeak < 0.0) 
    4710           0 :       {err += "fracofpeak must be a positive value \n"; }
    4711             :   
    4712        2522 :     return err;
    4713           0 :   }
    4714             : 
    4715        5048 :   void SynthesisParamsDeconv::setDefaults()
    4716             :   {
    4717        5048 :     imageName="";
    4718        5048 :     algorithm="hogbom";
    4719        5048 :     startModel=Vector<String>(0);
    4720        5048 :     deconvolverId=0;
    4721        5048 :     nTaylorTerms=1;
    4722        5048 :     scales.resize(1); scales[0]=0.0;
    4723        5048 :     scalebias=0.6;
    4724        5048 :     maskType="none";
    4725        5048 :     maskString="";
    4726        5048 :     maskList.resize(1); maskList[0]="";
    4727        5048 :     pbMask=0.0;
    4728        5048 :     autoMaskAlgorithm="thresh";
    4729        5048 :     maskThreshold="";
    4730        5048 :     maskResolution="";
    4731        5048 :     fracOfPeak=0.0; 
    4732        5048 :     nMask=0;
    4733        5048 :     interactive=false;
    4734        5048 :     autoAdjust=False;
    4735        5048 :     fusedThreshold = 0.0;
    4736        5048 :     specmode="mfs";
    4737        5048 :     largestscale = -1;
    4738        5048 :   }
    4739             : 
    4740        1675 :   Record SynthesisParamsDeconv::toRecord() const
    4741             :   {
    4742        1675 :     Record decpar;
    4743             : 
    4744        1675 :     decpar.define("imagename", imageName);
    4745        1675 :     decpar.define("deconvolver", algorithm);
    4746        1675 :     decpar.define("startmodel",startModel);
    4747        1675 :     decpar.define("id",deconvolverId);
    4748        1675 :     decpar.define("nterms",nTaylorTerms);
    4749        1675 :     decpar.define("scales",scales);
    4750        1675 :     decpar.define("scalebias",scalebias);
    4751        1675 :     decpar.define("usemask",maskType);
    4752        1675 :     decpar.define("fusedthreshold", fusedThreshold);
    4753        1675 :     decpar.define("specmode", specmode);
    4754        1675 :     decpar.define("largestscale", largestscale);
    4755        1675 :     if( maskList.nelements()==1 && maskList[0]=="") 
    4756             :       {
    4757        1123 :         decpar.define("mask",maskString);
    4758             :       }
    4759             :     else {
    4760         552 :         decpar.define("mask",maskList);
    4761             :     }
    4762        1675 :     decpar.define("pbmask",pbMask);
    4763        1675 :     if (fracOfPeak > 0.0) 
    4764             :       {
    4765           0 :         decpar.define("maskthreshold",fracOfPeak);
    4766             :       }
    4767             :     else 
    4768             :       {
    4769        1675 :         decpar.define("maskthreshold",maskThreshold);
    4770             :       }
    4771        1675 :     decpar.define("maskresolution",maskResolution);
    4772        1675 :     decpar.define("nmask",nMask);
    4773        1675 :     decpar.define("autoadjust",autoAdjust);
    4774        1675 :     decpar.define("sidelobethreshold",sidelobeThreshold);
    4775        1675 :     decpar.define("noisethreshold",noiseThreshold);
    4776        1675 :     decpar.define("lownoisethreshold",lowNoiseThreshold);
    4777        1675 :     decpar.define("negativethreshold",negativeThreshold);
    4778        1675 :     decpar.define("smoothfactor",smoothFactor);
    4779        1675 :     decpar.define("minbeamfrac",minBeamFrac);
    4780        1675 :     decpar.define("cutthreshold",cutThreshold);
    4781        1675 :     decpar.define("growiterations",growIterations);
    4782        1675 :     decpar.define("dogrowprune",doGrowPrune);
    4783        1675 :     decpar.define("minpercentchange",minPercentChange);
    4784        1675 :     decpar.define("verbose", verbose);
    4785        1675 :     decpar.define("fastnoise", fastnoise);
    4786        1675 :     decpar.define("interactive",interactive);
    4787        1675 :     decpar.define("nsigma",nsigma);
    4788        1675 :     decpar.define("noRequireSumwt",noRequireSumwt);
    4789        1675 :     decpar.define("fullsummary",fullsummary);
    4790             : 
    4791        1675 :     return decpar;
    4792           0 :   }
    4793             : 
    4794             :   /////////////////////////////////////////////////////////////////////////////////////////////////////
    4795             : 
    4796             : 
    4797             : } //# NAMESPACE CASA - END
    4798             : 

Generated by: LCOV version 1.16