LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SynthesisUtilMethods.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1771 2468 71.8 %
Date: 2024-11-06 17:42:47 Functions: 65 81 80.2 %

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

Generated by: LCOV version 1.16