LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - Imager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 627 3916 16.0 %
Date: 2025-08-21 08:01:32 Functions: 15 78 19.2 %

          Line data    Source code
       1             : //# Imager.cc: Implementation of Imager.h
       2             : //# Copyright (C) 1997-2008
       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 <casacore/casa/iostream.h>
      30             : #include <synthesis/MeasurementEquations/Imager.h>
      31             : #include <synthesis/MeasurementComponents/EPJones.h>
      32             : #include <synthesis/TransformMachines/VisModelData.h>
      33             : 
      34             : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
      35             : 
      36             : #include <casacore/casa/Arrays/Matrix.h>
      37             : #include <casacore/casa/Arrays/ArrayMath.h>
      38             : #include <casacore/casa/Arrays/ArrayLogical.h>
      39             : 
      40             : #include <casacore/casa/Logging.h>
      41             : #include <casacore/casa/Logging/LogIO.h>
      42             : #include <casacore/casa/Logging/LogMessage.h>
      43             : 
      44             : #include <casacore/casa/OS/DirectoryIterator.h>
      45             : #include <casacore/casa/OS/File.h>
      46             : #include <casacore/casa/OS/Path.h>
      47             : 
      48             : #include <casacore/casa/OS/HostInfo.h>
      49             : #include <casacore/tables/Tables/RefRows.h>
      50             : #include <casacore/tables/Tables/Table.h>
      51             : #include <casacore/tables/Tables/TableUtil.h>
      52             : #include <casacore/tables/Tables/SetupNewTab.h>
      53             : #include <casacore/tables/TaQL/TableParse.h>
      54             : #include <casacore/tables/Tables/TableRecord.h>
      55             : #include <casacore/tables/Tables/TableDesc.h>
      56             : #include <casacore/tables/Tables/TableLock.h>
      57             : #include <casacore/tables/TaQL/ExprNode.h>
      58             : 
      59             : #include <casacore/casa/BasicSL/String.h>
      60             : #include <casacore/casa/Utilities/Assert.h>
      61             : #include <casacore/casa/Utilities/Fallible.h>
      62             : #include <casacore/casa/Utilities/CompositeNumber.h>
      63             : 
      64             : #include <casacore/casa/BasicSL/Constants.h>
      65             : #include <casacore/casa/Utilities/Regex.h>
      66             : 
      67             : #include <casacore/casa/Logging/LogSink.h>
      68             : #include <casacore/casa/Logging/LogMessage.h>
      69             : 
      70             : #include <casacore/casa/Arrays/ArrayMath.h>
      71             : #include <casacore/casa/Arrays/Slice.h>
      72             : #include <casacore/images/Images/ImageExpr.h>
      73             : #include <imageanalysis/ImageAnalysis/ImagePolarimetry.h>
      74             : #include <synthesis/MeasurementEquations/ClarkCleanProgress.h>
      75             : #include <casacore/lattices/LatticeMath/LatticeCleanProgress.h>
      76             : #include <msvis/MSVis/MSUtil.h>
      77             : #include <msvis/MSVis/VisSet.h>
      78             : #include <msvis/MSVis/VisSetUtil.h>
      79             : #include <msvis/MSVis/VisImagingWeight.h>
      80             : /////////#include <msvis/MSVis/VisBufferAsync.h>
      81             : 
      82             : // Disabling Imager::correct() (gmoellen 06Nov20)
      83             : //#include <synthesis/MeasurementComponents/TimeVarVisJones.h>
      84             : 
      85             : #include <casacore/measures/Measures/Stokes.h>
      86             : #include <casacore/casa/Quanta/UnitMap.h>
      87             : #include <casacore/casa/Quanta/UnitVal.h>
      88             : #include <casacore/casa/Quanta/MVAngle.h>
      89             : #include <casacore/measures/Measures/MDirection.h>
      90             : #include <casacore/measures/Measures/MPosition.h>
      91             : #include <casacore/casa/Quanta/MVEpoch.h>
      92             : #include <casacore/casa/Quanta/MVTime.h>
      93             : #include <casacore/measures/Measures/MEpoch.h>
      94             : #include <casacore/measures/Measures/MeasTable.h>
      95             : 
      96             : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
      97             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      98             : #include <casacore/ms/MSSel/MSSelection.h>
      99             : #include <casacore/ms/MSSel/MSSelectionTools.h>
     100             : #include <casacore/ms/MSSel/MSDataDescIndex.h>
     101             : #include <casacore/ms/MeasurementSets/MSDopplerUtil.h>
     102             : #include <casacore/ms/MSSel/MSSourceIndex.h>
     103             : #include <casacore/ms/MSOper/MSSummary.h>
     104             : #include <synthesis/MeasurementEquations/CubeSkyEquation.h>
     105             : #include <synthesis/MeasurementEquations/Feather.h>
     106             : #include <synthesis/MeasurementComponents/ImageSkyModel.h>
     107             : #include <synthesis/MeasurementComponents/CEMemImageSkyModel.h>
     108             : #include <synthesis/MeasurementComponents/MFCEMemImageSkyModel.h>
     109             : #include <synthesis/MeasurementComponents/MFCleanImageSkyModel.h>
     110             : #include <synthesis/MeasurementComponents/CSCleanImageSkyModel.h>
     111             : #include <synthesis/MeasurementComponents/MFMSCleanImageSkyModel.h>
     112             : #include <synthesis/MeasurementComponents/HogbomCleanImageSkyModel.h>
     113             : #include <synthesis/MeasurementComponents/MSCleanImageSkyModel.h>
     114             : #include <synthesis/MeasurementComponents/NNLSImageSkyModel.h>
     115             : #include <synthesis/MeasurementComponents/WBCleanImageSkyModel.h>
     116             : #include <synthesis/MeasurementComponents/GridBoth.h>
     117             : #include <synthesis/TransformMachines/SetJyGridFT.h>
     118             : #include <synthesis/TransformMachines/MosaicFT.h>
     119             : #include <synthesis/TransformMachines/WProjectFT.h>
     120             : #include <synthesis/MeasurementComponents/nPBWProjectFT.h>
     121             : #include <synthesis/MeasurementComponents/PBMosaicFT.h>
     122             : #include <synthesis/TransformMachines/PBMath.h>
     123             : #include <synthesis/TransformMachines/SimpleComponentFTMachine.h>
     124             : #include <synthesis/TransformMachines/VPSkyJones.h>
     125             : #include <synthesis/TransformMachines/SynthesisError.h>
     126             : #include <synthesis/TransformMachines/HetArrayConvFunc.h>
     127             : 
     128             : #include <synthesis/DataSampling/SynDataSampling.h>
     129             : #include <synthesis/DataSampling/SDDataSampling.h>
     130             : #include <synthesis/DataSampling/ImageDataSampling.h>
     131             : 
     132             : #include <casacore/lattices/LRegions/LattRegionHolder.h>
     133             : #include <casacore/lattices/Lattices/TiledLineStepper.h> 
     134             : #include <casacore/lattices/Lattices/LatticeIterator.h> 
     135             : #include <casacore/lattices/LEL/LatticeExpr.h> 
     136             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
     137             : #include <casacore/lattices/LRegions/LCEllipsoid.h>
     138             : #include <casacore/lattices/LRegions/LCRegion.h>
     139             : #include <casacore/lattices/LRegions/LCBox.h>
     140             : #include <casacore/lattices/LRegions/LCIntersection.h>
     141             : #include <casacore/lattices/LRegions/LCUnion.h>
     142             : #include <casacore/lattices/LRegions/LCExtension.h>
     143             : 
     144             : #include <casacore/images/Images/ImageRegrid.h>
     145             : #include <casacore/images/Regions/ImageRegion.h>
     146             : #include <casacore/images/Regions/RegionManager.h>
     147             : #include <casacore/images/Regions/WCBox.h>
     148             : #include <casacore/images/Regions/WCUnion.h>
     149             : #include <casacore/images/Regions/WCIntersection.h>
     150             : #include <synthesis/TransformMachines/PBMath.h>
     151             : #include <casacore/images/Images/PagedImage.h>
     152             : #include <casacore/images/Images/ImageInfo.h>
     153             : #include <casacore/images/Images/SubImage.h>
     154             : #include <casacore/images/Images/ImageUtilities.h>
     155             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
     156             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
     157             : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
     158             : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
     159             : #include <casacore/coordinates/Coordinates/Projection.h>
     160             : #include <casacore/coordinates/Coordinates/ObsInfo.h>
     161             : 
     162             : #include <components/ComponentModels/ComponentList.h>
     163             : #include <components/ComponentModels/ConstantSpectrum.h>
     164             : #include <components/ComponentModels/SpectralIndex.h>
     165             : #include <components/ComponentModels/TabularSpectrum.h>
     166             : #include <components/ComponentModels/Flux.h>
     167             : #include <components/ComponentModels/FluxStandard.h>
     168             : #include <components/ComponentModels/PointShape.h>
     169             : #include <components/ComponentModels/DiskShape.h>
     170             : 
     171             : #ifdef USE_GRPC
     172             : #include <synthesis/ImagerObjects/grpcInteractiveClean.h>
     173             : #endif
     174             : 
     175             : #include <casacore/casa/OS/HostInfo.h>
     176             : 
     177             : #include <components/ComponentModels/ComponentList.h>
     178             : 
     179             : #include <casacore/measures/Measures/UVWMachine.h>
     180             : 
     181             : #include <casacore/casa/sstream.h>
     182             : 
     183             : #include <sys/types.h>
     184             : #include <unistd.h>
     185             : #ifdef _OPENMP
     186             : #include <omp.h>
     187             : #endif
     188             : using namespace std;
     189             : 
     190             : using namespace casacore;
     191             : namespace casa { //# NAMESPACE CASA - BEGIN
     192             : 
     193         187 : Imager::Imager() 
     194         187 :   :  msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), ft_p(0), 
     195         187 :      cft_p(0), se_p(0),
     196         187 :      sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false), 
     197         187 :      mssFreqSel_p(), mssChanSel_p(),
     198         187 :      clean_panel_p(0), image_id_p(0), mask_id_p(0), 
     199         561 :       prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
     200             : {
     201         187 :   ms_p=0;
     202         187 :   mssel_p=0;
     203         187 :   lockCounter_p=0;
     204         187 :   numMS_p=0;
     205         187 :   defaults();
     206         187 : };
     207             : 
     208             : 
     209         187 : void Imager::defaults() 
     210             : {
     211             : 
     212         187 :   setimaged_p=false;
     213         187 :   nullSelect_p=false;
     214         187 :   nx_p=128; ny_p=128; facets_p=1;
     215         187 :   wprojPlanes_p=-1;
     216         187 :   mcellx_p=Quantity(1, "arcsec"); mcelly_p=Quantity(1, "arcsec");
     217         187 :   shiftx_p=Quantity(0.0, "arcsec"); shifty_p=Quantity(0.0, "arcsec");
     218         187 :   distance_p=Quantity(0.0, "m");
     219         187 :   stokes_p="I"; npol_p=1;
     220         187 :   nscales_p=5;
     221         187 :   ntaylor_p=1;
     222         187 :   reffreq_p=0.0;
     223         187 :   useNewMTFT_p=false;
     224         187 :   scaleMethod_p="nscales";  
     225         187 :   scaleInfoValid_p=false;
     226         187 :   dataMode_p="none";
     227         187 :   imageMode_p="MFS";
     228         187 :   dataNchan_p=0;
     229         187 :   imageNchan_p=0;
     230         187 :   doVP_p=false;
     231         187 :   doDefaultVP_p = true;
     232         187 :   parAngleInc_p=Quantity(360.,"deg");
     233         187 :   skyPosThreshold_p=Quantity(180.,"deg");
     234         187 :   telescope_p="";
     235         187 :   gridfunction_p="SF";
     236         187 :   minWeight_p=0.;
     237         187 :   clipminmax_p=false;
     238         187 :   doMultiFields_p=false;
     239         187 :   doWideBand_p=false;
     240         187 :   multiFields_p=false;
     241             :   // Use half the machine memory as cache. The user can override
     242             :   // this via the setoptions function().
     243         187 :   cache_p=(HostInfo::memoryTotal(true)/8)*1024;
     244             :   //On 32 bit machines with more than 2G of mem this can become negative
     245             :   // overriding it to 2 Gb.
     246         187 :   if(cache_p <=0 )
     247           0 :     cache_p=2000000000/8;
     248         187 :   tile_p=16;
     249         187 :   ftmachine_p="ft";
     250         187 :   wfGridding_p=false;
     251         187 :   padding_p=1.2;
     252         187 :   sdScale_p=1.0;
     253         187 :   sdWeight_p=1.0;
     254         187 :   sdConvSupport_p=-1;
     255             : 
     256         187 :   doShift_p=false;
     257         187 :   spectralwindowids_p.resize(1); 
     258         187 :   spectralwindowids_p=0;
     259         187 :   fieldid_p=0;
     260         187 :   dataspectralwindowids_p.resize(0); 
     261         187 :   datadescids_p.resize(0);
     262         187 :   datafieldids_p.resize(0);
     263         187 :   mImageStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     264         187 :   mImageStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     265         187 :   mDataStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     266         187 :   mDataStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     267         187 :   beamValid_p=false;
     268         187 :   beam_p = ImageBeamSet();
     269         187 :   images_p.resize(0);
     270         187 :   masks_p.resize(0);
     271         187 :   fluxMasks_p.resize(0);
     272         187 :   residuals_p.resize(0);
     273         187 :   componentList_p=0;
     274             : 
     275         187 :   cyclefactor_p = 1.5;
     276         187 :   cyclespeedup_p =  -1;
     277         187 :   cyclemaxpsffraction_p = 0.8;
     278         187 :   stoplargenegatives_p = 2;
     279         187 :   stoppointmode_p = -1;
     280         187 :   fluxscale_p.resize(0);
     281         187 :   scaleType_p = "NONE";
     282         187 :   minPB_p = 0.1;
     283         187 :   constPB_p = 0.4;
     284         187 :   redoSkyModel_p=true;
     285         187 :   nmodels_p=0;
     286         187 :   useModelCol_p=false;
     287         187 :   freqFrameValid_p=false;
     288         187 :   doTrackSource_p=false;
     289         187 :   freqInterpMethod_p="nearest";
     290         187 :   pointingDirCol_p="DIRECTION";
     291         187 :   logSink_p=LogSink(LogMessage::NORMAL, false);
     292         187 :   imwgt_p=VisImagingWeight();
     293         187 :   smallScaleBias_p=0.6;
     294         187 :   freqFrame_p=MFrequency::LSRK;
     295         187 :   imageTileVol_p=0;
     296         187 :   singlePrec_p=false;
     297         187 :   spwchansels_p.resize();
     298         187 :   flatnoise_p=true;
     299         187 :   freqrange_p.resize();
     300         187 :   numthreads_p=-1;
     301         187 :   avoidTempLatt_p=false;
     302         187 :   mssFreqSel_p.resize();
     303         187 :   mssChanSel_p.resize();
     304         187 :   projection_p=String("SIN");
     305             : 
     306         187 : }
     307             : 
     308             : 
     309           0 : Imager::Imager(MeasurementSet& theMS,  Bool compress, Bool useModel)
     310           0 :   : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), 
     311           0 :     ft_p(0), cft_p(0), se_p(0),
     312           0 :     sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false), 
     313           0 :     mssFreqSel_p(), mssChanSel_p(),
     314           0 :     clean_panel_p(0), image_id_p(0), mask_id_p(0), prev_image_id_p(0), prev_mask_id_p(0),
     315           0 :     projection_p("SIN")
     316             : 
     317             : {
     318             : 
     319           0 :   mssel_p=0;
     320           0 :   ms_p=0;
     321           0 :   lockCounter_p=0;
     322           0 :   LogIO os(LogOrigin("Imager", "Imager(MeasurementSet &theMS)", WHERE));
     323           0 :   if(!open(theMS, compress, useModel)) {
     324           0 :     os << LogIO::SEVERE << "Open of MeasurementSet failed" << LogIO::EXCEPTION;
     325             :   };
     326             : 
     327           0 :   numMS_p=1;
     328           0 :   defaults();
     329           0 :   latestObsInfo_p=ObsInfo();
     330           0 : }
     331             : 
     332             : 
     333             : 
     334           0 : Imager::Imager(MeasurementSet& theMS, Bool compress)
     335           0 :   :  msname_p(""),  vs_p(0), rvi_p(0), wvi_p(0), ft_p(0), cft_p(0), se_p(0),
     336           0 :      sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false), 
     337           0 :      mssFreqSel_p(), mssChanSel_p(),
     338           0 :      clean_panel_p(0), image_id_p(0), mask_id_p(0),
     339           0 :      prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
     340             : {
     341           0 :   mssel_p=0;
     342           0 :   ms_p=0;
     343           0 :   lockCounter_p=0;
     344           0 :   LogIO os(LogOrigin("Imager", "Imager(MeasurementSet &theMS)", WHERE));
     345           0 :   if(!open(theMS, compress)) {
     346           0 :     os << LogIO::SEVERE << "Open of MeasurementSet failed" << LogIO::EXCEPTION;
     347             :   };
     348             : 
     349           0 :   numMS_p=1;
     350           0 :   defaults();
     351             : 
     352           0 :   latestObsInfo_p=ObsInfo();
     353           0 : }
     354             : 
     355           0 : Imager::Imager(const Imager & other)
     356           0 :   :  msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), 
     357           0 :      ft_p(0), cft_p(0), se_p(0),
     358           0 :      sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false), 
     359           0 :      clean_panel_p(0), image_id_p(0), mask_id_p(0), prev_image_id_p(0), prev_mask_id_p(0)
     360             : {
     361           0 :   mssel_p=0;
     362           0 :   ms_p=0;
     363           0 :   operator=(other);
     364           0 : }
     365             : 
     366           0 : Imager &Imager::operator=(const Imager & other)
     367             : {
     368           0 :   if (!ms_p.null() && this != &other) {
     369           0 :     *ms_p = *(other.ms_p);
     370             :   }
     371           0 :   if(this != &other){
     372             :     //Equating the table and ms parameters
     373           0 :     antab_p=other.antab_p;
     374           0 :     datadesctab_p=other.datadesctab_p;
     375           0 :     feedtab_p=other.feedtab_p;
     376           0 :     fieldtab_p=other.fieldtab_p;
     377           0 :     obstab_p=other.obstab_p;
     378           0 :     pointingtab_p=other.pointingtab_p;
     379           0 :     poltab_p=other.poltab_p;
     380           0 :     proctab_p=other.proctab_p;
     381           0 :     spwtab_p=other.spwtab_p;
     382           0 :     statetab_p=other.statetab_p;
     383           0 :     latestObsInfo_p=other.latestObsInfo_p;
     384           0 :     parAngleInc_p=other.parAngleInc_p;
     385           0 :     skyPosThreshold_p=other.skyPosThreshold_p;
     386           0 :     doTrackSource_p=other.doTrackSource_p;
     387           0 :     trackDir_p=other.trackDir_p;
     388           0 :     smallScaleBias_p=other.smallScaleBias_p;
     389           0 :     numMS_p=other.numMS_p;
     390           0 :     if (!mssel_p.null() && this != &other) {
     391           0 :       *mssel_p = *(other.mssel_p);
     392             :     }
     393           0 :     if (vs_p && this != &other) {
     394           0 :       *vs_p = *(other.vs_p);
     395             :     }
     396           0 :     if (wvi_p && this != &other) {
     397           0 :       *wvi_p = *(other.wvi_p);
     398           0 :       rvi_p=wvi_p;
     399             :     }
     400           0 :     else if(rvi_p && this != &other){
     401           0 :       *rvi_p = *(other.rvi_p);
     402           0 :       wvi_p=NULL;
     403             :     }
     404           0 :     if (ft_p && this != &other) {
     405           0 :       *ft_p = *(other.ft_p);
     406             :     }
     407           0 :     if (cft_p && this != &other) {
     408           0 :       *cft_p = *(other.cft_p);
     409             :     }
     410           0 :     if (se_p && this != &other) {
     411           0 :       *se_p = *(other.se_p);
     412             :     }
     413           0 :     if (sm_p && this != &other) {
     414           0 :       *sm_p = *(other.sm_p);
     415             :     }
     416           0 :     if (vp_p && this != &other) {
     417           0 :       *vp_p = *(other.vp_p);
     418             :     }
     419           0 :     if (gvp_p && this != &other) {
     420           0 :       *gvp_p = *(other.gvp_p);
     421             :     }
     422           0 :     imageTileVol_p=other.imageTileVol_p;
     423           0 :     flatnoise_p=other.flatnoise_p;
     424           0 :     mssFreqSel_p.assign(other.mssFreqSel_p);
     425           0 :     mssChanSel_p.assign(other.mssChanSel_p);
     426           0 :     projection_p = other.projection_p;
     427             :   }
     428           0 :   return *this;
     429             : }
     430             : 
     431         232 : Imager::~Imager()
     432             : {
     433             :   try{
     434         187 :     destroySkyEquation();
     435         187 :     this->unlock(); //unlock things if they are in a locked state
     436             :     
     437             :     //if (mssel_p) {
     438             :     //  delete mssel_p;
     439             :     // }
     440         187 :     mssel_p = 0;
     441             :     //if (ms_p) {
     442             :     //  delete ms_p;
     443             :     //}
     444         187 :     ms_p = 0;
     445         187 :     if (vs_p) {
     446           0 :       delete vs_p;
     447             :     }
     448         187 :     if(rvi_p)
     449          45 :       delete rvi_p;
     450         187 :     rvi_p=wvi_p=0;
     451             : 
     452         187 :     vs_p = 0;
     453         187 :     if (ft_p) {
     454          20 :       delete ft_p;
     455             :     }
     456             :     
     457             :     
     458         187 :     ft_p = 0;
     459         187 :     if (cft_p) {
     460          22 :       delete cft_p;
     461             :     }
     462         187 :     cft_p = 0;
     463             : 
     464             :   }
     465           0 :   catch (AipsError x){
     466           0 :     String mess=x.getMesg();
     467             :     //This is a bug for wproject and facet together...
     468             :     //somebody is erasing a TempLattice before desturctor.
     469             :     //will keep this in place till i figure it out...its benign
     470           0 :     if(mess.contains("does not exist") && mess.contains("TempLattice")){
     471           0 :       String rootpath="/"+String(mess.after("/")).before("TempLattice");
     472           0 :       String pid=String(mess.after("TempLattice")).before("_");
     473           0 :       DirectoryIterator dir(rootpath, Regex(Regex::fromPattern("TempLattice"+pid+"*")));
     474           0 :       while(!dir.pastEnd()){
     475           0 :           Directory ledir(rootpath+"/"+dir.name());
     476           0 :           ledir.removeRecursive();
     477           0 :           dir++;
     478             :           
     479           0 :       }
     480             : 
     481           0 :     }
     482             :     else{
     483           0 :       throw(AipsError(x));
     484             : 
     485             :     }
     486             : 
     487           0 :   }
     488             : 
     489             : 
     490         232 : }
     491             : 
     492             : 
     493          45 : Bool Imager::open(MeasurementSet& theMs, Bool /*compress*/, Bool useModelCol)
     494             : {
     495             : 
     496          90 :   LogIO os(LogOrigin("Imager", "open()", WHERE));
     497             :   
     498          45 :   if (!ms_p.null()) {
     499           0 :     *ms_p = theMs;
     500             :   } else {
     501          45 :     ms_p = new MeasurementSet(theMs);
     502          45 :     AlwaysAssert(!ms_p.null(), AipsError);
     503             :   }
     504             :   
     505             : 
     506             :   try {
     507          45 :     this->openSubTables();
     508          45 :     this->lock();
     509          45 :     msname_p = ms_p->tableName();
     510             :     
     511          45 :     os << "Opening MeasurementSet " << msname_p << LogIO::POST;
     512             : 
     513             :     // Check for DATA or FLOAT_DATA column
     514          90 :     if(!ms_p->tableDesc().isColumn("DATA") && 
     515          45 :        !ms_p->tableDesc().isColumn("FLOAT_DATA")) {
     516           0 :       ms_p->unlock();
     517             :       //delete ms_p; 
     518           0 :       ms_p=0;
     519             :       os << LogIO::SEVERE
     520             :          << "Missing DATA or FLOAT_DATA column: imager cannot be run"
     521           0 :          << LogIO::EXCEPTION;
     522           0 :       return false;
     523             :     }
     524             :     
     525             :     // The unused return value creates a compiler warning, there shouldn't be any side-effect of this statement
     526             :     //(!ms_p->tableDesc().isColumn("CORRECTED_DATA")); // if no side effect then delete this statement?
     527             :     
     528             :     /*if(vs_p) {
     529             :       delete vs_p; vs_p=0;
     530             :     }
     531             :     */
     532          45 :     if(rvi_p){
     533           0 :       delete rvi_p;
     534           0 :       rvi_p=0;
     535           0 :       wvi_p=0;
     536             :     }
     537             :     
     538             :     // Now open the selected MeasurementSet to be initially the
     539             :     // same as the original MeasurementSet
     540             : 
     541          45 :     mssel_p=new MeasurementSet(*ms_p);
     542          45 :     useModelCol_p=useModelCol;
     543             :     
     544             :     // Now create the VisSet
     545          45 :     this->makeVisSet(*mssel_p);
     546          45 :     AlwaysAssert(rvi_p, AipsError);
     547             :     
     548             :     // Polarization
     549          45 :     MSColumns msc(*mssel_p);
     550          45 :     Vector<String> polType=msc.feed().polarizationType()(0);
     551         101 :     if (polType(0)!="X" && polType(0)!="Y" &&
     552         101 :         polType(0)!="R" && polType(0)!="L") {
     553           0 :       this->unlock();
     554             :       os << LogIO::SEVERE << "Warning: Unknown stokes types in feed table: "
     555           0 :          << polType(0) << endl
     556           0 :          << "Results open to question!" << LogIO::POST;
     557             :     }
     558          45 :     numMS_p=1;
     559             : 
     560          45 :     this->unlock();
     561             : 
     562          45 :     return true;
     563          45 :   } catch (AipsError x) {
     564           0 :     this->unlock();
     565           0 :     os << LogIO::SEVERE << "Caught Exception: "<< x.getMesg() << LogIO::EXCEPTION;
     566             : 
     567           0 :     return false;
     568           0 :   } 
     569             : 
     570             :   return true;
     571          45 : }
     572             : 
     573           0 : Bool Imager::close()
     574             : {
     575           0 :   if(!valid()) return false;
     576           0 :   if (detached()) return true;
     577           0 :   LogIO os(LogOrigin("imager", "close()", WHERE));
     578             :   os << LogIO::NORMAL // Loglevel PROGRESS
     579             :      << "Closing MeasurementSet and detaching from imager"
     580           0 :      << LogIO::POST;
     581           0 :   this->unlock();
     582           0 :   if(ft_p) delete ft_p; ft_p = 0;
     583           0 :   if(cft_p) delete cft_p; cft_p = 0;
     584           0 :   if(vs_p) delete vs_p; vs_p = 0;
     585           0 :   if(rvi_p) delete rvi_p; 
     586           0 :   rvi_p=0;
     587           0 :   wvi_p=0;
     588             :   //if(mssel_p) delete mssel_p; 
     589           0 :   mssel_p = 0;
     590             :   //if(ms_p) delete ms_p; 
     591           0 :   ms_p = 0;
     592             : 
     593           0 :   if(se_p) delete se_p; se_p = 0;
     594             : 
     595           0 :   if(vp_p) delete vp_p; vp_p = 0;
     596           0 :   if(gvp_p) delete gvp_p; gvp_p = 0;
     597             : 
     598           0 :   destroySkyEquation();
     599             : 
     600           0 :   return true;
     601           0 : }
     602             : 
     603           0 : String Imager::name() const
     604             : {
     605           0 :   if (detached()) {
     606           0 :     return "none";
     607             :   }
     608           0 :   return msname_p;
     609             : }
     610             : 
     611             : 
     612             : 
     613             : 
     614           0 : IPosition Imager::imageshape() const
     615             : {
     616           0 :   return IPosition(4, nx_p, ny_p, npol_p, imageNchan_p);
     617             : }
     618             : 
     619           0 : Bool Imager::summary() 
     620             : {
     621           0 :   if(!valid()) return false;
     622           0 :   LogOrigin OR("imager", "Imager::summary()", WHERE);
     623             :   
     624           0 :   LogIO los(OR);
     625             :   
     626           0 :   los << "Logging summary" << LogIO::POST;
     627             :   try {
     628             :     
     629           0 :     this->lock();
     630           0 :     MSSummary mss(*ms_p);
     631           0 :     mss.list(los, true);
     632             :     
     633           0 :     los << endl << state() << LogIO::POST;
     634           0 :     this->unlock();
     635           0 :     return true;
     636           0 :   } catch (AipsError x) {
     637           0 :     this->unlock();
     638             :     los << LogIO::SEVERE << "Caught Exception: " << x.getMesg()
     639           0 :         << LogIO::EXCEPTION;
     640           0 :     return false;
     641           0 :   } 
     642             :   
     643             :   return true;
     644           0 : }
     645             : 
     646             : 
     647           0 : Bool Imager::setimage(const Int nx, const Int ny,
     648             :                       const Quantity& cellx, const Quantity& celly,
     649             :                       const String& stokes,
     650             :                       Bool doShift,
     651             :                       const MDirection& phaseCenter, 
     652             :                       const Quantity& shiftx, const Quantity& shifty,
     653             :                       const String& mode, const Int nchan,
     654             :                       const Int start, const Int step,
     655             :                       const MRadialVelocity& mStart, const MRadialVelocity& mStep,
     656             :                       const Vector<Int>& spectralwindowids,
     657             :                       const Int fieldid,
     658             :                       const Int facets,
     659             :                       const Quantity& distance)
     660             : {
     661             : 
     662           0 :   if(!valid())
     663             :     {
     664           0 :       return false;
     665             :     }
     666             : 
     667             :   //Clear the sink 
     668           0 :   logSink_p.clearLocally();
     669           0 :   LogIO os(LogOrigin("imager", "setimage()"), logSink_p);
     670             : 
     671             :   os << "nx=" << nx << " ny=" << ny
     672           0 :      << " cellx='" << cellx.getValue() << cellx.getUnit()
     673           0 :      << "' celly='" << celly.getValue() << celly.getUnit()
     674             :      << "' stokes=" << stokes << " doShift=" << doShift
     675           0 :      << " shiftx='" << shiftx.getValue() << shiftx.getUnit()
     676           0 :      << "' shifty='" << shifty.getValue() << shifty.getUnit()
     677             :      << "' mode=" << mode << " nchan=" << nchan
     678             :      << " start=" << start << " step=" << step
     679             :      << " spwids=" << spectralwindowids
     680             :      << " fieldid=" <<   fieldid << " facets=" << facets
     681           0 :      << " distance='" << distance.getValue() << distance.getUnit() <<"'";
     682           0 :   ostringstream clicom;
     683           0 :   clicom << " phaseCenter='" << phaseCenter;
     684           0 :   clicom << "' mStart='" << mStart << "' mStep='" << mStep << "'";
     685           0 :   os << String(clicom);
     686             :   
     687             :   try {
     688             :     
     689           0 :     this->lock();
     690           0 :     this->writeCommand(os);
     691             : 
     692           0 :     os << LogIO::NORMAL << "Defining image properties" << LogIO::POST; // Loglevel INFO
     693             :   
     694             :     /**** this check is not really needed here especially for SD imaging
     695             :     if(2*Int(nx/2)!=nx) {
     696             :       this->unlock();
     697             :       os << LogIO::SEVERE << "nx must be even" << LogIO::POST;
     698             :       return false;
     699             :     }
     700             :     if(2*Int(ny/2)!=ny) {
     701             :       this->unlock();
     702             :       os << LogIO::SEVERE << "ny must be even" << LogIO::POST;
     703             :       return false;
     704             :     }
     705             : 
     706             :     */
     707             :     {
     708           0 :       CompositeNumber cn(nx);
     709           0 :       if (! cn.isComposite(nx)) {
     710           0 :         Int nxc = (Int)cn.nextLargerEven(nx);
     711           0 :         Int nnxc = (Int)cn.nearestEven(nx);
     712           0 :         if (nxc == nnxc) {
     713             :           os << LogIO::WARN << "nx = " << nx << " is not composite; nx = " 
     714           0 :              << nxc << " will be more efficient" << LogIO::POST;
     715             :         } else {
     716             :           os <<  LogIO::WARN << "nx = " << nx << " is not composite; nx = " 
     717           0 :              << nxc <<  " or " << nnxc << " will be more efficient for FFTs" << LogIO::POST;
     718             :         }
     719             :       }
     720           0 :       if (! cn.isComposite(ny)) {
     721           0 :         Int nyc = (Int)cn.nextLargerEven(ny);
     722           0 :         Int nnyc = (Int)cn.nearestEven(ny);
     723           0 :         if (nyc == nnyc) {
     724             :           os <<  LogIO::WARN << "ny = " << ny << " is not composite; ny = " 
     725           0 :              << nyc << " will be more efficient" << LogIO::POST;
     726             :         } else {
     727             :           os <<  LogIO::WARN << "ny = " << ny << " is not composite ; ny = " << nyc << 
     728           0 :               " or " << nnyc << " will be more efficient for FFTs" << LogIO::POST;
     729             :         }
     730             :         os << LogIO::WARN 
     731             :            << "You may safely ignore this message for single dish imaging" 
     732           0 :            << LogIO::POST;
     733             : 
     734             :       }
     735             :       
     736           0 :     }
     737             : 
     738             :   
     739           0 :     nx_p=nx;
     740           0 :     ny_p=ny;
     741           0 :     mcellx_p=cellx;
     742           0 :     mcelly_p=celly;
     743           0 :     distance_p=distance;
     744           0 :     stokes_p=stokes;
     745           0 :     imageMode_p=mode;
     746           0 :     imageMode_p.upcase();
     747           0 :     imageNchan_p=nchan;
     748           0 :     imageStart_p=start;
     749           0 :     imageStep_p=step;
     750           0 :     mImageStart_p=mStart;
     751           0 :     mImageStep_p=mStep;
     752           0 :     spectralwindowids_p.resize(spectralwindowids.nelements());
     753           0 :     spectralwindowids_p=spectralwindowids;
     754           0 :     fieldid_p=fieldid;
     755           0 :     facets_p=facets;
     756           0 :     redoSkyModel_p=true;
     757           0 :     destroySkyEquation();    
     758             : 
     759           0 :      Vector<Int> whichStokes = decideNPolPlanes(false);
     760           0 :      if( whichStokes.nelements()==1 && whichStokes[0]==0 )
     761             :       {
     762           0 :       this->unlock();
     763           0 :       os << LogIO::SEVERE << "Stokes selection " << stokes_p << " is currently not supported." << LogIO::EXCEPTION;
     764           0 :       return false;
     765             :       }
     766             : 
     767             :     
     768             : 
     769             :     //THIS NEEDS TO GO
     770             :     ////this->setImageParam(nx_p, ny_p, npol_p, imageNchan_p);
     771           0 :     nchan_p = imageNchan_p; // check if this is needed.... it's the only non-redundant thing in setImageParam.
     772             : 
     773             :     // Now do the shifts
     774             :     //    MSColumns msc(*ms_p);
     775             : 
     776           0 :     doShift_p=doShift;
     777           0 :     if(doShift_p) {
     778           0 :       phaseCenter_p=phaseCenter;
     779             :     }
     780             :     else {
     781             : 
     782           0 :       MSFieldColumns msfield(ms_p->field());
     783           0 :       phaseCenter_p=msfield.phaseDirMeas(fieldid_p);
     784             :       //    phaseCenter_p=msc.field().phaseDirMeas(fieldid_p);
     785           0 :     }
     786             :     
     787             :     // Now add the optional shifts
     788           0 :     shiftx_p=shiftx;
     789           0 :     shifty_p=shifty;
     790           0 :     if(shiftx_p.get().getValue()!=0.0||shifty_p.get().getValue()!=0.0) {
     791           0 :       Vector<Double> vPhaseCenter(phaseCenter_p.getAngle().getValue());
     792           0 :       if(cos(vPhaseCenter(1))!=0.0) {
     793           0 :         vPhaseCenter(0)+=shiftx_p.get().getValue()/cos(vPhaseCenter(1));
     794             :       }
     795           0 :       vPhaseCenter(1)+=shifty_p.get().getValue();
     796           0 :       phaseCenter_p.set(MVDirection(vPhaseCenter));
     797           0 :     }
     798             :     
     799             :     // Now we have set the image parameters
     800           0 :     setimaged_p=true;
     801           0 :     beamValid_p=false;
     802             :     
     803           0 :     this->unlock();
     804             : 
     805           0 :     return true;
     806           0 :   } catch (AipsError x) {
     807             :     
     808           0 :     this->unlock();
     809             : 
     810             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     811           0 :        << LogIO::EXCEPTION;
     812           0 :     return false;
     813           0 :   } 
     814             : 
     815             :   return true;
     816           0 : }
     817             : 
     818             : 
     819           0 : Bool Imager::defineImage(const Int nx, const Int ny,
     820             :                          const Quantity& cellx, const Quantity& celly,
     821             :                          const String& stokes,
     822             :                          const MDirection& phaseCenter, const Int fieldid,
     823             :                          const String& mode, const Int nchan,
     824             :                          const Int start, const Int step,
     825             :                          const MFrequency& mFreqStart,
     826             :                          const MRadialVelocity& mStart, 
     827             :                          const Quantity& qStep,
     828             :                          const Vector<Int>& spectralwindowids,
     829             :                          const Int facets,
     830             :                          const Quantity& restFreq,
     831             :                          const MFrequency::Types& mFreqFrame,
     832             :                          const Quantity& distance, const Bool dotrackDir, 
     833             :                          const MDirection& trackDir,
     834             :                          const String& projection)
     835             : {
     836             : 
     837             : 
     838             : 
     839             : 
     840             :   //Clear the sink 
     841           0 :   logSink_p.clearLocally();
     842           0 :   LogIO os(LogOrigin("imager", "defineimage()"), logSink_p);
     843           0 :   if(cellx.getValue() == 0.0  || celly.getValue()==0.0)
     844           0 :          throw(AipsError("Infinite resolution not possible... please do let us know what you are drinking"));
     845           0 :   os << LogIO::NORMAL << "Defining image properties:"; // Loglevel INFO
     846             :   os << "nx=" << nx << " ny=" << ny
     847           0 :      << " cellx='" << cellx.getValue() << cellx.getUnit()
     848           0 :      << "' celly='" << celly.getValue() << celly.getUnit()
     849             :      << "' stokes=" << stokes 
     850             :      << "' mode=" << mode << " nchan=" << nchan
     851             :      << " start=" << start << " step=" << step
     852             :      << " spwids=" << spectralwindowids
     853             :      << " fieldid=" <<   fieldid << " facets=" << facets
     854           0 :      << " frame=" << mFreqFrame 
     855           0 :      << " distance='" << distance.getValue() << distance.getUnit() <<"'";
     856           0 :   os << LogIO::POST;
     857           0 :   ostringstream clicom;
     858           0 :   clicom << " phaseCenter='"  ;
     859           0 :   if(fieldid < 0){
     860           0 :     MVAngle mvRA=phaseCenter.getAngle().getValue()(0);
     861           0 :     MVAngle mvDEC=phaseCenter.getAngle().getValue()(1);
     862           0 :     clicom << mvRA(0.0).string(MVAngle::TIME,8) << ", ";
     863           0 :     clicom << mvDEC(0.0).string(MVAngle::ANGLE_CLEAN,8) << ", ";
     864           0 :   }
     865             :   else{
     866           0 :     clicom << "field-" << fieldid<< " "; 
     867             :   }
     868           0 :   clicom << "' mStart='" << mStart << "' qStep='" << qStep << "'";
     869           0 :   clicom << "' mFreqStart='" << mFreqStart;
     870           0 :   os << String(clicom);
     871           0 :   os << LogIO::POST;
     872             :   
     873             :   try {
     874             :     
     875           0 :     this->lock();
     876           0 :     this->writeCommand(os);
     877             :   
     878           0 :     doTrackSource_p=dotrackDir;
     879           0 :     trackDir_p=trackDir;
     880             : 
     881             : 
     882             :     /**** this check is not really needed here especially for SD imaging
     883             :     if(2*Int(nx/2)!=nx) {
     884             :       this->unlock();
     885             :       os << LogIO::SEVERE << "nx must be even" << LogIO::POST;
     886             :       return false;
     887             :     }
     888             :     if(2*Int(ny/2)!=ny) {
     889             :       this->unlock();
     890             :       os << LogIO::SEVERE << "ny must be even" << LogIO::POST;
     891             :       return false;
     892             :     }
     893             : 
     894             :     */
     895             :     // RVU : Disabling this Composite Number check, because image sizes are
     896             :     //          anyway being re-calculated inside the FTMachines (accounding for padding too).
     897             :     if(0)
     898             :     {
     899             :       CompositeNumber cn(nx);
     900             :       if (! cn.isComposite(nx)) {
     901             :         Int nxc = (Int)cn.nextLargerEven(nx);
     902             :         Int nnxc = (Int)cn.nearestEven(nx);
     903             :         if (nxc == nnxc) {
     904             :           os << LogIO::POST << "nx = " << nx << " is not composite; nx = " 
     905             :              << nxc << " will be more efficient" << LogIO::POST;
     906             :         } else {
     907             :           os <<  LogIO::POST << "nx = " << nx << " is not composite; nx = " 
     908             :              << nxc <<  " or " << nnxc << " will be more efficient" << LogIO::POST;
     909             :         }
     910             :       }
     911             :       if (! cn.isComposite(ny)) {
     912             :         Int nyc = (Int)cn.nextLargerEven(ny);
     913             :         Int nnyc = (Int)cn.nearestEven(ny);
     914             :         if (nyc == nnyc) {
     915             :           os <<  LogIO::POST << "ny = " << ny << " is not composite; ny = " 
     916             :              << nyc << " will be more efficient" << LogIO::POST;
     917             :         } else {
     918             :           os <<  LogIO::POST << "ny = " << ny << " is not composite; ny = " << nyc << 
     919             :               " or " << nnyc << " will be more efficient" << LogIO::POST;
     920             :         }
     921             :         os << LogIO::POST
     922             :            << "You may safely ignore this message for single dish imaging" 
     923             :            << LogIO::POST;
     924             : 
     925             :       }
     926             :       
     927             :     }
     928             : 
     929             : 
     930           0 :     if((abs(Double(nx)*cellx.getValue("rad")) > M_PI) || (abs(Double(ny)*celly.getValue("rad")) > M_PI))
     931           0 :       throw(AipsError("Cannot image the extent requested for this image;  more that PI ialong one or both of the axes " ));
     932             :     
     933             : 
     934             : 
     935           0 :     nx_p=nx;
     936           0 :     ny_p=ny;
     937           0 :     mcellx_p=cellx;
     938           0 :     mcelly_p=celly;
     939           0 :     distance_p=distance;
     940           0 :     stokes_p=stokes;
     941           0 :     imageMode_p=mode;
     942           0 :     imageMode_p.upcase();
     943           0 :     imageNchan_p=nchan;
     944           0 :     imageStart_p=start;
     945           0 :     imageStep_p=step;
     946           0 :     if(mode.contains("VEL")){
     947           0 :       mImageStart_p=mStart;
     948           0 :       mImageStep_p=MRadialVelocity(qStep);
     949             :     }
     950           0 :     if(mode.contains("FREQ")){
     951           0 :       mfImageStart_p=mFreqStart;
     952           0 :       mfImageStep_p=MFrequency(qStep);
     953             :     }
     954           0 :     restFreq_p=restFreq;
     955           0 :     freqFrame_p=mFreqFrame;
     956           0 :     spectralwindowids_p.resize(spectralwindowids.nelements());
     957           0 :     spectralwindowids_p=spectralwindowids;
     958           0 :     fieldid_p=fieldid;
     959           0 :     facets_p=facets;
     960           0 :     redoSkyModel_p=true;
     961           0 :     destroySkyEquation();    
     962             : 
     963             :     // Now make the derived quantities 
     964           0 :     Vector<Int> whichStokes = decideNPolPlanes(false);
     965           0 :     if( whichStokes.nelements()==1 && whichStokes[0]==0 )
     966             :       {
     967           0 :       this->unlock();
     968           0 :       os << LogIO::SEVERE << "Stokes selection " << stokes_p << " is currently not supported." << LogIO::EXCEPTION;
     969           0 :       return false;
     970             :       }
     971             : 
     972             :     // nchan we need to get rid of one of these variables 
     973           0 :     nchan_p=imageNchan_p;
     974             :     
     975           0 :     if(fieldid < 0){      
     976           0 :       doShift_p=true;
     977           0 :       phaseCenter_p=phaseCenter;
     978             :     }
     979             :     else {
     980           0 :       MSFieldColumns msfield(ms_p->field());
     981           0 :       phaseCenter_p=msfield.phaseDirMeas(fieldid_p);
     982           0 :     }
     983             :     
     984             :     // we only support projections SIN, CAR, TAN, and SFL
     985           0 :     Projection::Type const ptype = Projection::type(projection);
     986           0 :     if (ptype != Projection::SIN && ptype != Projection::CAR
     987           0 :         && ptype != Projection::TAN && ptype != Projection::SFL) {
     988           0 :       this->unlock();
     989           0 :       os << LogIO::SEVERE << "Projection " << projection << " is currently not supported." << LogIO::EXCEPTION;
     990           0 :       return false;
     991             :     } else {
     992           0 :       projection_p = projection;
     993             :     }
     994             : 
     995             :     
     996             :     // Now we have set the image parameters
     997           0 :     setimaged_p=true;
     998           0 :     beamValid_p=false;
     999             :     
    1000           0 :     this->unlock();
    1001             : 
    1002             : 
    1003           0 :     return true;
    1004           0 :   } catch (AipsError x) {
    1005           0 :     this->unlock();
    1006             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1007           0 :        << LogIO::EXCEPTION;
    1008           0 :     return false;
    1009           0 :   } 
    1010             :   return true;
    1011           0 : }
    1012             : 
    1013             : 
    1014           0 : Bool Imager::advise(const Bool takeAdvice, const Float amplitudeLoss,
    1015             :                     const Quantity& fieldOfView, Quantity& cell,
    1016             :                     Int& pixels, Int& facets, MDirection& phaseCenter)
    1017             : {
    1018           0 :   if(!valid()) return false;
    1019             :   
    1020           0 :   LogIO os(LogOrigin("imager", "advise()", WHERE));
    1021             :   
    1022             :   try {
    1023             :     
    1024           0 :     os << "Advising image properties" << LogIO::POST;
    1025             :     
    1026           0 :     Float maxAbsUV=0.0;
    1027           0 :     Float maxWtAbsUV=0.0;
    1028             :     // To determine the number of facets, we need to fit w to
    1029             :     // a.u + b.v. The misfit from this (i.e. the dispersion 
    1030             :     // will determine the error beam due to the non-coplanar
    1031             :     // baselines. We'll do both cases: where the position
    1032             :     // errors are important and where they are not. We'll use
    1033             :     // the latter.
    1034           0 :     Double sumWt = 0.0;
    1035             : 
    1036           0 :     Double sumUU=0.0;
    1037           0 :     Double sumUV=0.0;
    1038           0 :     Double sumUW=0.0;
    1039           0 :     Double sumVV=0.0;
    1040           0 :     Double sumVW=0.0;
    1041           0 :     Double sumWW=0.0;
    1042             : 
    1043           0 :     Double sumWtUU=0.0;
    1044           0 :     Double sumWtUV=0.0;
    1045           0 :     Double sumWtUW=0.0;
    1046           0 :     Double sumWtVV=0.0;
    1047           0 :     Double sumWtVW=0.0;
    1048           0 :     Double sumWtWW=0.0;
    1049             : 
    1050           0 :     Double sum = 0.0;
    1051             : 
    1052           0 :     this->lock();
    1053           0 :     ROVisIter& vi(*rvi_p);
    1054           0 :     VisBuffer vb(vi);
    1055             :     
    1056           0 :     for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
    1057           0 :       for (vi.origin();vi.more();vi++) {
    1058           0 :         Int nRow=vb.nRow();
    1059           0 :         Int nChan=vb.nChannel();
    1060           0 :         for (Int row=0; row<nRow; ++row) {
    1061           0 :           for (Int chn=0; chn<nChan; ++chn) {
    1062           0 :             if(!vb.flag()(chn,row)) {
    1063           0 :               Float f=vb.frequency()(chn)/C::c;
    1064           0 :               Float u=vb.uvw()(row)(0)*f;
    1065           0 :               Float v=vb.uvw()(row)(1)*f;
    1066           0 :               Float w=vb.uvw()(row)(2)*f;
    1067           0 :               Double wt=vb.imagingWeight()(chn,row);
    1068           0 :               if(wt>0.0) {
    1069           0 :                 if(abs(u)>maxWtAbsUV) maxWtAbsUV=abs(u);
    1070           0 :                 if(abs(v)>maxWtAbsUV) maxWtAbsUV=abs(v);
    1071           0 :                 sumWt += wt;
    1072           0 :                 sumWtUU += wt * u * u;
    1073           0 :                 sumWtUV += wt * u * v;
    1074           0 :                 sumWtUW += wt * u * w;
    1075           0 :                 sumWtVV += wt * v * v;
    1076           0 :                 sumWtVW += wt * v * w;
    1077           0 :                 sumWtWW += wt * w * w;
    1078             :               }
    1079           0 :               sum += 1;
    1080           0 :               if(abs(u)>maxAbsUV) maxAbsUV=abs(u);
    1081           0 :               if(abs(v)>maxAbsUV) maxAbsUV=abs(v);
    1082           0 :               sumUU += u * u;
    1083           0 :               sumUV += u * v;
    1084           0 :               sumUW += u * w;
    1085           0 :               sumVV += v * v;
    1086           0 :               sumVW += v * w;
    1087           0 :               sumWW += w * w;
    1088             :             }
    1089             :           }
    1090             :         }
    1091             :       }
    1092             :     }
    1093             :     
    1094             : 
    1095           0 :     if(sumWt==0.0) {
    1096           0 :       os << LogIO::WARN << "Visibility data are not yet weighted: using unweighted values" << LogIO::POST;
    1097           0 :       sumWt = sum;
    1098             :     }
    1099             :     else {
    1100           0 :       sumUU = sumWtUU;
    1101           0 :       sumUV = sumWtUV;
    1102           0 :       sumUW = sumWtUW;
    1103           0 :       sumVV = sumWtVV;
    1104           0 :       sumVW = sumWtVW;
    1105           0 :       sumWW = sumWtWW;
    1106           0 :       maxAbsUV = maxWtAbsUV;
    1107             :     }
    1108             : 
    1109             :     // First find the cell size
    1110           0 :     if(maxAbsUV==0.0) {
    1111           0 :       this->unlock();
    1112           0 :       os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    1113           0 :       return false;
    1114             :     }
    1115             :     else {
    1116           0 :       cell=Quantity(0.5/maxAbsUV, "rad").get("arcsec");
    1117           0 :       os << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
    1118           0 :       os << "Recommended cell size < " << cell.get("arcsec").getValue()
    1119           0 :          << " arcsec" << LogIO::POST;
    1120             :     }
    1121             : 
    1122             :     // Now we can find the number of pixels for the specified field of view
    1123           0 :     pixels = 2*Int((fieldOfView.get("rad").getValue()/cell.get("rad").getValue())/2.0);
    1124             :     {
    1125           0 :       CompositeNumber cn(pixels);
    1126           0 :       pixels = (Int) (cn.nextLargerEven(pixels));
    1127           0 :     }
    1128           0 :     if(pixels < 64) pixels = 64;
    1129           0 :     os << "Recommended number of pixels = " << pixels << endl;
    1130             : 
    1131             :       // Rough rule for number of facets:
    1132             :       // For the specified facet size, the loss in amplitude
    1133             :       // due to the peeling of facets from the sphere should 
    1134             :       // be equal to the amplitude error.
    1135           0 :       Int worstCaseFacets=1;
    1136           0 :       if(sumWt<=0.0||sumUU<=0.0||(sumUU+sumVV)<=0.0) {
    1137           0 :         this->unlock();
    1138           0 :         os << LogIO::SEVERE << "Sum of imaging weights is zero" << LogIO::POST;
    1139           0 :         return false;
    1140             :       }
    1141             :       else {
    1142           0 :         Double rmsUV  = sqrt((sumUU + sumVV)/sumWt);
    1143           0 :         Double rmsW = sqrt(sumWW/sumWt);
    1144             :         os << "Dispersion in uv, w distance = " << rmsUV << ", "<< rmsW
    1145           0 :            << " wavelengths" << endl;
    1146           0 :         if(rmsW>0.0&&rmsUV>0.0&&amplitudeLoss>0.0) {
    1147           0 :           worstCaseFacets =
    1148           0 :             Int (pixels * (abs(cell.get("rad").getValue())*
    1149           0 :                                   sqrt(M_PI*rmsW/(sqrt(32.0*amplitudeLoss)))));
    1150             :         }
    1151             :         else {
    1152             :           os << LogIO::WARN << "Cannot calculate number of facets: using 1"
    1153           0 :              << LogIO::POST;
    1154           0 :           worstCaseFacets = 1;
    1155             :         }
    1156             :         // Solve for the parameters:
    1157           0 :         Double Determinant = sumUU * sumVV - square(sumUV);
    1158           0 :         Double rmsFittedW = rmsW;
    1159           0 :         if(Determinant > 0.0) {
    1160           0 :           Double a = ( sumVV * sumUW - sumUV * sumVW)/Determinant;
    1161           0 :           Double b = (-sumUV * sumUW + sumUU * sumVW)/Determinant;
    1162             :           os << "Best fitting plane is w = " << a << " * u + "
    1163           0 :              << b << " * v" << endl;
    1164             :           Double FittedWW =
    1165           0 :             sumWW  + square(a) * sumUU + square(b) * sumVV +
    1166           0 :             + 2.0 * a * b * sumUV - 2.0 * (a * sumUW + b * sumVW);
    1167           0 :           rmsFittedW  = sqrt(FittedWW/sumWt);
    1168             :           os << "Dispersion in fitted w = " << rmsFittedW
    1169           0 :              << " wavelengths" << endl;
    1170           0 :           facets = Int (pixels * (abs(cell.get("rad").getValue())*
    1171           0 :                                   sqrt(M_PI*rmsFittedW/(sqrt(32.0*amplitudeLoss)))));
    1172           0 :           if (facets<1) facets = 1;
    1173             :         }
    1174             :         else {
    1175           0 :           os << "Error in fitting plane to uvw data" << LogIO::POST;
    1176             :         }
    1177           0 :         if(worstCaseFacets<1) worstCaseFacets=1;
    1178           0 :         if(worstCaseFacets>1) {
    1179             :           os << "imager recommends that you use the wide field clean" << endl
    1180             :              << "For accurate positions, use " << worstCaseFacets
    1181             :              << " facets on each axis" << endl
    1182             :              << "For accurate removal of sources, you only need "
    1183           0 :              << facets << " facets on each axis" << LogIO::POST;
    1184             :         }
    1185             :         else {
    1186             :           os << "Wide field cleaning is not necessary"
    1187           0 :              << LogIO::POST;
    1188             :         }
    1189             :       }
    1190             : 
    1191           0 :     MSColumns msc(*mssel_p);
    1192           0 :     if(datafieldids_p.shape()!=0){
    1193             :       //If setdata has been used prior to this
    1194           0 :     phaseCenter=msc.field().phaseDirMeas(datafieldids_p(0));
    1195             :     }
    1196             :     else{
    1197           0 :     phaseCenter=msc.field().phaseDirMeas(fieldid_p);   
    1198             :     }
    1199             : 
    1200             :     
    1201             :     // Now we have set the image parameters
    1202           0 :     if(takeAdvice) {
    1203           0 :       os << "Using advised image properties" << LogIO::POST;
    1204           0 :       mcellx_p=cell;
    1205           0 :       mcelly_p=cell;
    1206           0 :       phaseCenter_p=phaseCenter;
    1207           0 :       setimaged_p=true;
    1208           0 :       beamValid_p=false;
    1209           0 :       facets_p=facets;
    1210           0 :       nx_p=ny_p=pixels;
    1211             :     }
    1212             :     
    1213           0 :     this->unlock();
    1214           0 :     return true;
    1215           0 :   } catch (AipsError x) {
    1216           0 :     this->unlock();
    1217             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1218           0 :        << LogIO::EXCEPTION;
    1219           0 :     return false;
    1220           0 :   } 
    1221             :   
    1222             :   return true;
    1223           0 : }
    1224             : 
    1225             : 
    1226             : 
    1227          15 : Bool Imager::setDataPerMS(const String& msname, const String& mode, 
    1228             :                           const Vector<Int>& nchan, 
    1229             :                           const Vector<Int>& start,
    1230             :                           const Vector<Int>& step,
    1231             :                           const Vector<Int>& spectralwindowids,
    1232             :                           const Vector<Int>& fieldids,
    1233             :                           const String& msSelect, const String& timerng,
    1234             :                           const String& fieldnames, 
    1235             :                           const Vector<Int>& antIndex,
    1236             :                           const String& antnames,
    1237             :                           const String& spwstring,
    1238             :                           const String& uvdist, const String& scan,
    1239             :                           const String& intent, const String& obs,
    1240             :                           const Bool useModelCol, const Bool /*readonly*/)
    1241             : {
    1242          30 :   LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
    1243          15 :   if(msname != ""){
    1244             : 
    1245           0 :     LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
    1246             :     os << LogIO::WARN
    1247             :        << "Ignoring that ms" << msname << "specified here"
    1248           0 :        << LogIO::POST;
    1249             :     os << LogIO::WARN
    1250             :        << "Imager was constructed with an ms "
    1251           0 :        << LogIO::POST;
    1252             :     os << LogIO::WARN
    1253             :        << "if multi-ms are to be used please construct imager without parameters and use setdata to specify the ms's and selection"
    1254           0 :        << LogIO::POST;
    1255             : 
    1256           0 :   }
    1257          15 :   MRadialVelocity dummy;
    1258             :   //Calling the old setdata
    1259          15 :   return   setdata(mode, nchan, start, step, dummy, dummy, spectralwindowids, 
    1260             :                    fieldids, msSelect, timerng, fieldnames, antIndex, 
    1261          30 :                    antnames, spwstring, uvdist, scan, intent, obs, useModelCol);
    1262             : 
    1263          15 : }
    1264             : 
    1265             : 
    1266          61 : Bool Imager::setdata(const String& mode, const Vector<Int>& nchan,
    1267             :                      const Vector<Int>& start, const Vector<Int>& step,
    1268             :                      const MRadialVelocity& mStart,
    1269             :                      const MRadialVelocity& mStep,
    1270             :                      const Vector<Int>& spectralwindowids,
    1271             :                      const Vector<Int>& fieldids,
    1272             :                      const String& msSelect, const String& timerng,
    1273             :                      const String& fieldnames, const Vector<Int>& antIndex,
    1274             :                      const String& antnames, const String& spwstring,
    1275             :                      const String& uvdist, const String& scan,
    1276             :                      const String& intent,
    1277             :                      const String& obs, 
    1278             :                      const Bool /*useModelCol*/,
    1279             :                      const Bool be_calm)
    1280             : {
    1281          61 :   logSink_p.clearLocally();
    1282         122 :   LogIO os(LogOrigin("imager", "data selection"), logSink_p);
    1283             : 
    1284          61 :   if(ms_p.null()) {
    1285             :     os << LogIO::SEVERE << "Program logic error: MeasurementSet pointer ms_p not yet set"
    1286           0 :        << LogIO::EXCEPTION;
    1287           0 :     nullSelect_p=true;
    1288           0 :     return false;
    1289             :   }
    1290             : 
    1291             :   os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1292             :      << "mode=" << mode << " nchan=" << nchan 
    1293          61 :      <<  " start=" << start << " step=" << step;
    1294          61 :   ostringstream clicom;
    1295          61 :   clicom <<  " mstart='" << mStart << "' mstep='" << mStep;
    1296          61 :   os << String(clicom) ;
    1297             :   os <<  "' spectralwindowids=" << spectralwindowids
    1298          61 :      << " fieldids=" << fieldids << " msselect=" << msSelect;
    1299             : 
    1300          61 :   nullSelect_p=false;
    1301          61 :   String local_spwstring(spwstring);
    1302          61 :   if (local_spwstring  == "") local_spwstring="*";
    1303             :   try {
    1304             :     
    1305          61 :     this->lock();
    1306          61 :     this->writeCommand(os);
    1307             : 
    1308             :     os << (be_calm ? LogIO::NORMAL2 : LogIO::NORMAL)
    1309         122 :        << "Performing selection on MeasurementSet : " << ms_p->tableName()
    1310          61 :        << LogIO::POST; // Loglevel PROGRESS
    1311             :     //Some MSSelection 
    1312          61 :     MSSelection thisSelection;
    1313             : 
    1314             :     // check that sorted table exists (it should), if not, make it now.
    1315             :     //this->makeVisSet(*ms_p);
    1316             :     
    1317             :     //MeasurementSet sorted=ms_p->keywordSet().asTable("SORTED_TABLE");
    1318             :     //MSSelection thisSelection (sorted, MSSelection::PARSE_NOW,timerng,antnames,
    1319             :     //                         fieldnames, local_spwstring,uvdist, msSelect,"",
    1320             :     //                         scan, obs); 
    1321             : 
    1322          61 :     datafieldids_p.resize(fieldids.nelements());
    1323          61 :     datafieldids_p = fieldids;
    1324          61 :     if(datafieldids_p.nelements() > 0){
    1325          46 :       thisSelection.setFieldExpr(MSSelection::indexExprStr(datafieldids_p));
    1326             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1327          46 :          << "Selecting on field ids : " << datafieldids_p <<  LogIO::POST;
    1328             :     }
    1329          61 :     if(fieldnames != ""){
    1330           1 :       thisSelection.setFieldExpr(fieldnames);
    1331             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1332           1 :          << "Selecting on fields : " << fieldnames << LogIO::POST;
    1333             :     }
    1334             :     
    1335          61 :     dataspectralwindowids_p.resize(spectralwindowids.nelements());
    1336          61 :     dataspectralwindowids_p = spectralwindowids;
    1337          61 :     if(dataspectralwindowids_p.nelements() > 0){
    1338          46 :       thisSelection.setSpwExpr(MSSelection::indexExprStr(dataspectralwindowids_p));
    1339             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1340          46 :          << "Selecting on spectral windows" << LogIO::POST;
    1341             :     }
    1342          15 :     else if(local_spwstring != ""){
    1343             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1344             :          << "Selecting on spectral windows expression : " << local_spwstring
    1345          15 :          << LogIO::POST;
    1346          15 :       thisSelection.setSpwExpr(local_spwstring);
    1347             :     }
    1348             :     
    1349          61 :     if(antIndex.nelements() >0){
    1350           0 :       thisSelection.setAntennaExpr( MSSelection::indexExprStr(antIndex));
    1351             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1352           0 :          << "Selecting on antenna ids : " << antIndex << LogIO::POST;       
    1353             :     }
    1354          61 :     if(antnames != ""){
    1355           0 :       Vector<String>antNames(1, antnames);
    1356             :       //       thisSelection.setAntennaExpr(MSSelection::nameExprStr(antNames));
    1357           0 :       thisSelection.setAntennaExpr(antnames);
    1358             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1359           0 :          << "Selecting on antenna names : " << antnames << LogIO::POST; 
    1360           0 :     } 
    1361             :                
    1362          61 :     if(timerng != ""){
    1363             :       //        Vector<String>timerange(1, timerng);
    1364           0 :         thisSelection.setTimeExpr(timerng);
    1365             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1366           0 :            << "Selecting on time range : " << timerng << LogIO::POST;       
    1367             :     }
    1368             :     
    1369          61 :     if(uvdist != ""){
    1370           0 :         thisSelection.setUvDistExpr(uvdist);
    1371             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1372           0 :            << "Selecting on uvdist : " << uvdist << LogIO::POST;    
    1373             :     }
    1374             :     
    1375          61 :     if(scan != ""){
    1376           0 :       thisSelection.setScanExpr(scan);
    1377             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1378           0 :            << "Selecting on scan : " << scan << LogIO::POST;        
    1379             :     }
    1380          61 :     if(intent != "") {
    1381           0 :       thisSelection.setStateExpr(intent);
    1382             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1383           0 :            << "Selecting on State Expr : " << intent  << LogIO::POST;       
    1384             :     }
    1385          61 :     if(obs != ""){
    1386           0 :       thisSelection.setObservationExpr(obs);
    1387             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1388           0 :            << "Selecting on Observation Expr : " << obs << LogIO::POST;     
    1389             :     }
    1390          61 :     if(msSelect != ""){
    1391           0 :       thisSelection.setTaQLExpr(msSelect);
    1392             :         os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1393           0 :            << "Selecting via TaQL : " << msSelect << LogIO::POST;   
    1394             :     }
    1395             :     
    1396             :     //***************
    1397          61 :     TableExprNode exprNode;
    1398             :     try{
    1399          61 :       exprNode = thisSelection.toTableExprNode(&(*ms_p));
    1400             :     }
    1401           0 :     catch(...){
    1402           0 :       nullSelect_p = true;
    1403           0 :       this->unlock();
    1404             :       // A "bad selection" warning message could be sent to the logger here,
    1405             :       // but it should be left to the calling function to do that.  For
    1406             :       // example, this function is called by setjy, and it would be a mistake
    1407             :       // to print a logger message for every spw that was not observed for the
    1408             :       // given field.
    1409           0 :       return false;
    1410           0 :     }
    1411             :     //TableExprNode exprNode=thisSelection.getTEN();
    1412             :     //if(exprNode.isNull()){
    1413             :       //      throw(AipsError("Selection failed...review ms and selection parameters"));
    1414             :     //}
    1415             : 
    1416             :     // Need to delete the ft machine as the channel flag may change
    1417          61 :     if(ft_p)
    1418          32 :       delete ft_p;
    1419          61 :     ft_p=0;
    1420          61 :     dataMode_p=mode;
    1421          61 :     dataNchan_p.resize();
    1422          61 :     dataStart_p.resize();
    1423          61 :     dataStep_p.resize();
    1424          61 :     dataNchan_p=nchan;
    1425          61 :     dataStart_p=start;
    1426          61 :     dataStep_p=step;
    1427          61 :     mDataStart_p=mStart;
    1428          61 :     mDataStep_p=mStep;
    1429             :     //    useModelCol_p=useModelCol;
    1430             :     
    1431          61 :     if(rvi_p)
    1432          61 :       delete rvi_p; 
    1433          61 :     rvi_p=0;
    1434          61 :     wvi_p=0;
    1435             :     // if(mssel_p) delete mssel_p; 
    1436          61 :     mssel_p=0;
    1437             :     
    1438          61 :     datafieldids_p.resize();
    1439          61 :     datafieldids_p=thisSelection.getFieldList();
    1440          61 :     if(datafieldids_p.nelements()==0){
    1441          14 :       Int nf=ms_p->field().nrow();
    1442          14 :       datafieldids_p.resize(nf);
    1443          14 :       indgen(datafieldids_p);
    1444             :     }
    1445             :     //Now lets see what was selected as spw and match it with datadesc
    1446             :     //
    1447             :     // getSpwList could return duplicated spw ids
    1448             :     // when multiple channel ranges are specified.
    1449             :     //dataspectralwindowids_p.resize();
    1450             :     //dataspectralwindowids_p=thisSelection.getSpwList();
    1451             :     //get channel selection in spw
    1452             :     // TT: Added sorting option in getChanList call 
    1453             :     //     to accomodate changes related CAS-2521
    1454          61 :     Matrix<Int> chansels=thisSelection.getChanList(NULL, 1, true);
    1455          61 :     mssChanSel_p.assign(chansels);
    1456          61 :     mssFreqSel_p.resize();
    1457          61 :     mssFreqSel_p=thisSelection.getChanFreqList(NULL, true);
    1458             : 
    1459             :     //cout<<"chansels="<<chansels<<endl;
    1460             :     //convert the selection into flag
    1461          61 :     uInt nms = 1;
    1462          61 :     uInt nrow = chansels.nrow();
    1463          61 :     dataspectralwindowids_p.resize();
    1464          61 :     const MSSpWindowColumns spwc(ms_p->spectralWindow());
    1465          61 :     uInt nspw = spwc.nrow();
    1466          61 :     const ScalarColumn<Int> spwNchans(spwc.numChan());
    1467          61 :     Vector<Int> nchanvec = spwNchans.getColumn();
    1468          61 :     Int maxnchan = 0;
    1469         672 :     for (uInt i=0;i<nchanvec.nelements();i++) {
    1470         611 :       maxnchan=max(nchanvec[i],maxnchan);
    1471             :     }
    1472             :     
    1473          61 :     spwchansels_p.resize(nms,nspw,maxnchan);
    1474          61 :     spwchansels_p.set(0);
    1475          61 :     uInt nselspw=0;
    1476          61 :     if (nrow==0) {
    1477             :       //no channel selection, select all channels
    1478           0 :       spwchansels_p=1;
    1479           0 :       dataspectralwindowids_p=thisSelection.getSpwList();
    1480             :     }
    1481             :     else {
    1482          61 :       spwchansels_p=0; //deselect
    1483          61 :       Int prvspwid=-1;
    1484          61 :       Vector<Int> selspw;
    1485         191 :       for (uInt i=0;i<nrow;i++) {
    1486         130 :         Vector<Int> sel = chansels.row(i);
    1487         130 :         Int spwid = sel[0];
    1488         130 :         if((sel[1] >= nchanvec[spwid]) || (sel[2] >=nchanvec[spwid]))
    1489           0 :           throw(AipsError("Unexpected selection  in spw selection of spwid "+String::toString(spwid)));
    1490         130 :         if (spwid != prvspwid){
    1491         130 :           nselspw++;
    1492         130 :           selspw.resize(nselspw,true);
    1493         130 :           selspw[nselspw-1]=spwid;
    1494             :         }
    1495         130 :         uInt minc= sel[1];
    1496         130 :         uInt maxc = sel[2];
    1497         130 :         uInt step = sel[3];
    1498             :         // step as the same context as in im.selectvis
    1499             :         // select channels 
    1500       45363 :         for (uInt k=minc;k<(maxc+1);k+=step) {
    1501       45233 :           spwchansels_p(0,spwid,k)=1;
    1502             :         }
    1503         130 :         prvspwid=spwid;
    1504         130 :       }
    1505          61 :       dataspectralwindowids_p=selspw;
    1506          61 :     }
    1507             :     
    1508             :     // Map the selected spectral window ids to data description ids
    1509          61 :     if(dataspectralwindowids_p.nelements()==0){
    1510           0 :       Int nspwinms=ms_p->spectralWindow().nrow();
    1511           0 :       dataspectralwindowids_p.resize(nspwinms);
    1512           0 :       indgen(dataspectralwindowids_p);
    1513             :     }
    1514          61 :     MSDataDescIndex msDatIndex(ms_p->dataDescription());
    1515          61 :     datadescids_p.resize(0);
    1516          61 :     datadescids_p=msDatIndex.matchSpwId(dataspectralwindowids_p);
    1517             :     
    1518          61 :     if (datafieldids_p.nelements() > 1) {
    1519           9 :       os << LogIO::NORMAL4<< "Multiple fields specified" << LogIO::POST;
    1520           9 :       multiFields_p = true;
    1521             :     }
    1522             :     
    1523             :     
    1524          61 :     if(mode=="none"){
    1525             :       // Now channel selection from spw already stored in chansel,
    1526             :       // no need for this- TT
    1527             :       //check if we can find channel selection in the spw string
    1528             :       //Matrix<Int> chanselmat=thisSelection.getChanList();
    1529             :       //
    1530             :       // This not correct for multiple channel ranges TT
    1531             :       //if(chanselmat.nrow()==dataspectralwindowids_p.nelements()){
    1532          24 :       if(nselspw==dataspectralwindowids_p.nelements()){
    1533             :         
    1534          24 :         dataMode_p="channel";
    1535          24 :         dataStep_p.resize(dataspectralwindowids_p.nelements());
    1536          24 :         dataStart_p.resize(dataspectralwindowids_p.nelements());
    1537          24 :         dataNchan_p.resize(dataspectralwindowids_p.nelements());
    1538          24 :         Cube<Int> spwchansels_tmp=spwchansels_p;
    1539             :         
    1540         117 :         for (uInt k =0 ; k < dataspectralwindowids_p.nelements(); ++k){
    1541          93 :           uInt curspwid=dataspectralwindowids_p[k];
    1542             :           //dataStep_p[k]=1;
    1543          93 :           if (nrow > 0) {
    1544          93 :             dataStep_p[k]=chansels.row(k)(3);
    1545             :           }
    1546             :           else {
    1547           0 :             dataStep_p[k]=1;
    1548             :           }
    1549             :           //dataStart_p[k]=chanselmat.row(k)(1);
    1550          93 :           dataStart_p[k]=0;
    1551          93 :           dataNchan_p[k]=nchanvec(curspwid);
    1552             :           //find start
    1553          93 :           Bool first =true;
    1554          93 :           uInt nchn = 0;
    1555          93 :           uInt lastchan = 0;
    1556       42963 :           for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++) {
    1557       42870 :             if (spwchansels_p(0,curspwid,j)==1) {
    1558       42870 :               if (first) {
    1559          93 :                 dataStart_p[k]=j;
    1560          93 :                 first = false;
    1561             :               }
    1562       42870 :               lastchan=j;
    1563       42870 :               nchn++;
    1564             :             }   
    1565             :           }
    1566          93 :           dataNchan_p[k]=Int(ceil(Double(lastchan-dataStart_p[k])/Double(dataStep_p[k])))+1;
    1567             :           //dataNchan_p[k]=Int(ceil(Double(chanselmat.row(k)(2)-dataStart_p[k])/Double(dataStep_p[k])))+1;
    1568             :           
    1569             :           //if(dataNchan_p[k]<1)
    1570             :           //  dataNchan_p[k]=1;   
    1571             :           
    1572             :           //cout<<"modified start="<<dataStart_p[k]<<endl;
    1573             :           //cout<<"modified nchan="<<dataNchan_p[k]<<endl;
    1574             :           //
    1575             :           //Since msselet will be applied to the data before flags from spwchansels_p
    1576             :           //are applied to the data in FTMachine, shift spwchansels_p by dataStart_p
    1577             :           //for (uInt j=0  ; j < nchanvec(k)-dataStart_p[k]; j++){
    1578       42963 :           for (uInt j=0  ; j < uInt(nchanvec(curspwid)); j++){
    1579       42870 :             if ( Int(j) < nchanvec(curspwid)-dataStart_p[k]) {
    1580       42870 :               spwchansels_tmp(0,curspwid,j) = spwchansels_p(0,curspwid,j+dataStart_p[k]);
    1581             :             }
    1582             :             else {
    1583           0 :               spwchansels_tmp(0,curspwid,j) = 0;
    1584             :             }
    1585             :           }
    1586             :         }
    1587          24 :         spwchansels_p = spwchansels_tmp;
    1588          24 :       }
    1589             :     }
    1590          61 :     if(!(exprNode.isNull())){
    1591          61 :       mssel_p = new MeasurementSet((*ms_p)(exprNode), &* ms_p);
    1592             :     }
    1593             :     else{
    1594             :       // Null take all the ms ...setdata() blank means that
    1595           0 :       mssel_p = new MeasurementSet(*ms_p);
    1596             :     }
    1597             : 
    1598          61 :     AlwaysAssert(!mssel_p.null(), AipsError);
    1599          61 :     if(mssel_p->nrow()==0) {
    1600             :       //delete mssel_p; 
    1601           2 :       mssel_p=0;
    1602             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::WARN)
    1603             :          << "Selection is empty: reverting to sorted MeasurementSet"
    1604           2 :          << LogIO::POST;
    1605           2 :       mssel_p=new MeasurementSet(*ms_p);
    1606           2 :       nullSelect_p=true;
    1607             :     }
    1608             :     else {
    1609          59 :       mssel_p->flush();
    1610          59 :       nullSelect_p=false;
    1611             :     }
    1612          61 :     if (nullSelect_p) {
    1613           2 :       if ((mssel_p->field()).nrow() > 1) {
    1614           2 :         os << LogIO::NORMAL4 << "Multiple fields selected" << LogIO::POST;
    1615           2 :         multiFields_p = true;
    1616             :       } else {
    1617           0 :         os << LogIO::NORMAL4 << "Single field selected" << LogIO::POST;
    1618           0 :         multiFields_p = false;
    1619             :       }
    1620             :     }
    1621             :     
    1622          61 :     uInt nvis_all = ms_p->nrow();
    1623             :     
    1624             :     // Now create the VisSet
    1625          61 :     this->makeVisSet(*mssel_p); 
    1626          61 :     AlwaysAssert(rvi_p, AipsError);
    1627          61 :     uInt nvis_sel = mssel_p->nrow();
    1628             :     
    1629          61 :     if(nvis_sel != nvis_all) {
    1630             :       os << LogIO::NORMAL // Loglevel INFO
    1631             :          << "Selected " << nvis_sel << " out of "
    1632             :          << nvis_all << " rows."
    1633          44 :          << LogIO::POST;
    1634             :     }
    1635             :     else {
    1636             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1637          17 :          << "Selected all " << nvis_sel << " rows" << LogIO::POST; // Loglevel INFO
    1638             :     }
    1639             :     //    }
    1640             : 
    1641             :     // Tell the user how many channels have been selected.
    1642             :     // NOTE : This code is replicated in ImagerMultiMS.cc.
    1643          61 :     Vector<Int> chancounts(dataspectralwindowids_p.nelements());
    1644          61 :     chancounts=0;
    1645             :     //    if( local_spwstring == "" ) os << "Selected all spws and channels" << LogIO::POST;
    1646             :     //else os << "Channel selection : " << local_spwstring << LogIO::POST;
    1647          61 :     os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL) << "Selected:";
    1648         191 :     for(uInt k=0;k<dataspectralwindowids_p.nelements();k++)
    1649             :       {
    1650       45363 :         for(uInt ch=0;ch<uInt(nchanvec(dataspectralwindowids_p[k]));ch++) 
    1651       45233 :           {if(spwchansels_p(0,dataspectralwindowids_p[k],ch)) chancounts[k]++; }
    1652         130 :         os << " [" << chancounts[k] << " chans in spw " << dataspectralwindowids_p[k] << "]";
    1653             :         //      os << "Selected " << chancounts[k] << " channels in spw " 
    1654             :         //  << dataspectralwindowids_p[k] << LogIO::POST;
    1655             :       }
    1656          61 :     os << LogIO::POST;
    1657             : 
    1658             :     // Now we do a selection to cut down the amount of information
    1659             :     // passed around.
    1660             :   
    1661          61 :     this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
    1662          61 :                             dataNchan_p, dataStart_p, dataStep_p,
    1663          61 :                             mDataStart_p, mDataStep_p);
    1664             :     ///Tell iterator to use on the fly imaging weights if scratch columns is
    1665             :     ///not in use
    1666          61 :     imwgt_p=VisImagingWeight("natural");
    1667          61 :     rvi_p->useImagingWeight(imwgt_p);
    1668             :     
    1669             :     // Guess that the beam is no longer valid
    1670          61 :     beamValid_p=false;
    1671          61 :     destroySkyEquation();
    1672          61 :     if(!valid()){ 
    1673           0 :       this->unlock();
    1674             :       os << LogIO::SEVERE << "Check your data selection or Measurement set "
    1675           0 :          << LogIO::EXCEPTION;
    1676           0 :       return false;
    1677             :     }
    1678          61 :     this->unlock();
    1679          61 :     return !nullSelect_p;
    1680          61 :   } catch (AipsError x) {
    1681           0 :     this->unlock();
    1682           0 :     throw(x);
    1683             :    
    1684             :     return false;
    1685           0 :   } 
    1686             :   return !nullSelect_p;
    1687          61 : }
    1688             : 
    1689             : 
    1690           0 : Bool Imager::setmfcontrol(const Float cyclefactor,
    1691             :                           const Float cyclespeedup,
    1692             :                           const Float cyclemaxpsffraction, 
    1693             :                           const Int stoplargenegatives, 
    1694             :                           const Int stoppointmode,
    1695             :                           const String& scaleType,
    1696             :                           const Float minPB,
    1697             :                           const Float constPB,
    1698             :                           const Vector<String>& fluxscale,
    1699             :                           const Bool flatnoise)
    1700             : {  
    1701           0 :   cyclefactor_p = cyclefactor;
    1702           0 :   cyclespeedup_p =  cyclespeedup;
    1703           0 :   cyclemaxpsffraction_p = cyclemaxpsffraction;
    1704           0 :   stoplargenegatives_p = stoplargenegatives;
    1705           0 :   stoppointmode_p = stoppointmode;
    1706           0 :   fluxscale_p.resize( fluxscale.nelements() );
    1707           0 :   fluxscale_p = fluxscale;
    1708           0 :   scaleType_p = scaleType;
    1709           0 :   minPB_p = minPB;
    1710           0 :   flatnoise_p=flatnoise;
    1711             : 
    1712           0 :   constPB_p = constPB;
    1713           0 :   return true;
    1714             : }  
    1715             : 
    1716             : 
    1717          13 : Bool Imager::setvp(const Bool dovp,
    1718             :                    const Bool doDefaultVPs,
    1719             :                    const String& vpTable,
    1720             :                    const Bool doSquint,
    1721             :                    const Quantity &parAngleInc,
    1722             :                    const Quantity &skyPosThreshold,
    1723             :                    String defaultTel,
    1724             :                    const Bool verbose)
    1725             : {
    1726             : 
    1727          26 :   LogIO os(LogOrigin("Imager", "setvp()", WHERE));
    1728             :   
    1729          13 :   os << LogIO::NORMAL << "Setting voltage pattern parameters" << LogIO::POST; // Loglevel PROGRESS
    1730             :   
    1731          13 :   if(!dovp && !vp_p)
    1732           0 :     delete vp_p;
    1733          13 :   vp_p=0;
    1734          13 :   doVP_p=dovp;
    1735          13 :   doDefaultVP_p = doDefaultVPs;
    1736          13 :   vpTableStr_p = vpTable;
    1737          13 :   telescope_p= defaultTel;
    1738          13 :   if (doSquint) {
    1739           0 :     squintType_p = BeamSquint::GOFIGURE;
    1740             :   } else {
    1741          13 :     squintType_p = BeamSquint::NONE;
    1742             :   }
    1743             : 
    1744          13 :   parAngleInc_p = parAngleInc;
    1745             : 
    1746          13 :   skyPosThreshold_p = skyPosThreshold;
    1747             :   os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1748             :      <<"Sky position tolerance is "<<skyPosThreshold_p.getValue("deg")
    1749          13 :      << " degrees" << LogIO::POST;
    1750             : 
    1751          13 :   if (doDefaultVP_p) {
    1752             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1753          13 :        << "Using system default voltage patterns for each telescope" << LogIO::POST;
    1754             :   } else {
    1755             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1756             :        << "Using user defined voltage patterns in Table "
    1757           0 :        <<  vpTableStr_p << LogIO::POST;
    1758             :   }
    1759          13 :   if (doSquint) {
    1760             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1761           0 :        << "Beam Squint will be included in the VP model" <<  LogIO::POST;
    1762             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1763             :        << "and the Parallactic Angle increment is "  // Loglevel INFO
    1764           0 :        << parAngleInc_p.getValue("deg") << " degrees"  << LogIO::POST;
    1765             :   }
    1766             : 
    1767             :   // muddled with the state of SkyEquation..so redo it
    1768          13 :   destroySkyEquation();
    1769          13 :   return true;
    1770          13 : }
    1771             : 
    1772           0 : Bool Imager::setoptions(const String& ftmachine, const Long cache, const Int tile,
    1773             :                         const String& gridfunction, const MPosition& mLocation,
    1774             :                         const Float padding,
    1775             :                         const Int wprojplanes,
    1776             :                         const String& epJTableName,
    1777             :                         const Bool applyPointingOffsets,
    1778             :                         const Bool doPointingCorrection,
    1779             :                         const String& cfCacheDirName,
    1780             :                         const Float& rotPAStep, 
    1781             :                         const Float& computePAStep, 
    1782             :                         const Float& pbLimit, const String& interpMeth, const Int imageTileVol,
    1783             :                         const Bool singprec,
    1784             :                         const Int numthreads,
    1785             :                         const Bool psTermOn,
    1786             :                         const Bool aTermOn,
    1787             :                         const Bool mTermOn,
    1788             :                         const Bool wbawp,
    1789             :                         const Bool conjBeams)
    1790             : {
    1791           0 :   if(!valid()) 
    1792             :     {
    1793           0 :       return false;
    1794             :     }
    1795           0 :   if(!assertDefinedImageParameters())
    1796             :     {
    1797           0 :       return false;
    1798             :     }
    1799           0 :   LogIO os(LogOrigin("imager", "setoptions()", WHERE));
    1800             :   
    1801           0 :   os << LogIO::NORMAL << "Setting processing options" << LogIO::POST; // Loglevel PROGRESS
    1802             : 
    1803           0 :   ftmachine_p=downcase(ftmachine);
    1804           0 :   if(ftmachine_p=="gridft") {
    1805             :     os << LogIO::WARN
    1806             :        << "FT machine gridft is now called ft - please use the new name in future"
    1807           0 :        << LogIO::POST;
    1808           0 :     ftmachine_p="ft";
    1809             :   }
    1810             : 
    1811           0 :   if(ftmachine_p=="wfmemoryft"){
    1812           0 :     wfGridding_p=true;
    1813           0 :     ftmachine_p="ft";
    1814             :   }
    1815             : 
    1816           0 :   wprojPlanes_p=wprojplanes;
    1817           0 :   epJTableName_p = epJTableName;
    1818           0 :   cfCacheDirName_p = cfCacheDirName;
    1819           0 :   rotPAStep_p = rotPAStep;
    1820           0 :   computePAStep_p = computePAStep;
    1821           0 :   pbLimit_p = pbLimit;
    1822           0 :   psTermOn_p=psTermOn;
    1823           0 :   aTermOn_p=aTermOn;
    1824           0 :   mTermOn_p=mTermOn;
    1825           0 :   wbAWP_p=wbawp;
    1826           0 :   conjBeams_p=conjBeams;
    1827           0 :   freqInterpMethod_p=interpMeth;
    1828           0 :   imageTileVol_p=imageTileVol;
    1829           0 :   if(imageTileVol_p <= 0){
    1830           0 :     avoidTempLatt_p=true;
    1831           0 :     imageTileVol_p=-1*imageTileVol_p;
    1832             :   }
    1833             :  
    1834             :   
    1835           0 :   singlePrec_p=singprec;
    1836             : 
    1837           0 :   if(cache>0) cache_p=cache;
    1838           0 :   if(tile>0) tile_p=tile;
    1839           0 :   gridfunction_p=downcase(gridfunction);
    1840           0 :   mLocation_p=mLocation;
    1841           0 :   if(padding>=1.0) {
    1842           0 :     padding_p=padding;
    1843             :   }
    1844             : 
    1845             :   // Check if gridfunction is set to gauss or gjinc for non single dish imaging
    1846           0 :   if (ftmachine_p!="sd" 
    1847           0 :       && (gridfunction_p=="gauss" || gridfunction_p=="gjinc")) {
    1848             :     os << LogIO::SEVERE
    1849           0 :        << "Grid function " << gridfunction << " is available only for single dish imaging" << LogIO::EXCEPTION;
    1850             :   }
    1851             : 
    1852             :   // Destroy the FTMachine
    1853           0 :   if(ft_p) {delete ft_p; ft_p=0;}
    1854           0 :   if(gvp_p) {delete gvp_p; gvp_p=0;}
    1855           0 :   if(cft_p) {delete cft_p; cft_p=0;}
    1856             : 
    1857           0 :   doPointing = applyPointingOffsets;
    1858           0 :   doPBCorr = doPointingCorrection;
    1859             : ////The set below does not seemed to be remembered later in the process it 
    1860             : /// under some compiler version so setting a private variable to be used
    1861             : /// a negative number means use all that is available
    1862           0 :   numthreads_p= numthreads;
    1863             : #ifdef _OPENMP
    1864           0 :   if(numthreads > 0){
    1865           0 :     if(numthreads <= omp_get_max_threads()){
    1866           0 :       omp_set_num_threads(numthreads);
    1867             :     }
    1868             :   }
    1869             : #endif
    1870           0 :   return true;
    1871           0 : }
    1872             : 
    1873          13 : Bool Imager::setsdoptions(const Float scale, const Float weight, 
    1874             :                           const Int convsupport, String pointCol,
    1875             :                           const Quantity truncate,
    1876             :                           const Quantity gwidth, const Quantity jwidth,
    1877             :                           const Float minweight, const Bool clipminmax,
    1878             :                           const Bool enablecache,
    1879             :                           const String & convertfirst)
    1880             : {
    1881          26 :   LogIO os(LogOrigin("imager", "setsdoptions()", WHERE));
    1882             :   
    1883          13 :   os << LogIO::NORMAL << "Setting single dish processing options" << LogIO::POST; // Loglevel PROGRESS
    1884             :   
    1885          13 :   sdScale_p=scale;
    1886          13 :   sdWeight_p=weight;
    1887             : 
    1888             :   
    1889          13 :   sdConvSupport_p=convsupport;
    1890          13 :   pointingDirCol_p=pointCol;
    1891          13 :   pointingDirCol_p.upcase();
    1892          13 :   if( (pointingDirCol_p != "DIRECTION") &&(pointingDirCol_p != "TARGET") && (pointingDirCol_p != "ENCODER") && (pointingDirCol_p != "POINTING_OFFSET") && (pointingDirCol_p != "SOURCE_OFFSET")){
    1893             :     os << LogIO::SEVERE
    1894           0 :        << "No such direction column as "<< pointingDirCol_p
    1895           0 :        << " in pointing table "<< LogIO::EXCEPTION;
    1896             :   }
    1897          13 :   qtruncate_p=truncate;
    1898          13 :   qgwidth_p=gwidth;
    1899          13 :   qjwidth_p=jwidth;
    1900          13 :   minWeight_p = minweight;
    1901          13 :   clipminmax_p = clipminmax;
    1902          13 :   enablecache_p = enablecache;
    1903          13 :   convertfirst_p = convertfirst;
    1904          13 :   convertfirst_p.upcase();
    1905             : 
    1906             : 
    1907             :   // Destroy the FTMachine
    1908          13 :   if(ft_p) {delete ft_p; ft_p=0;}
    1909          13 :   if(gvp_p) {delete gvp_p; gvp_p=0;}
    1910          13 :   if(cft_p) {delete cft_p; cft_p=0;}
    1911             : 
    1912          13 :   return true;
    1913          13 : }
    1914             : 
    1915           0 : Bool Imager::mask(const String& mask, const String& image,
    1916             :                   const Quantity& threshold) 
    1917             : {
    1918             :   //if(!valid()) return false;
    1919           0 :   LogIO os(LogOrigin("imager", "mask()", WHERE));
    1920             :   //if(!assertDefinedImageParameters()) return false;
    1921             :   
    1922             :   try {
    1923             :     //this->lock();
    1924           0 :     if(image=="") {
    1925             :       //this->unlock();
    1926           0 :       os << LogIO::SEVERE << "Need name for template image" << LogIO::EXCEPTION;
    1927           0 :       return false;
    1928             :     }
    1929           0 :     String maskName(mask);
    1930           0 :     if(maskName=="") {
    1931           0 :       maskName=image+".mask";
    1932             :     }
    1933           0 :     if(!clone(image, maskName)) return false;
    1934           0 :     PagedImage<Float> maskImage(maskName);
    1935           0 :     maskImage.table().markForDelete();
    1936           0 :     PagedImage<Float> imageImage(image);
    1937             : 
    1938           0 :     if(threshold.check(UnitVal(1.0, "Jy"))){
    1939             :       os << LogIO::NORMAL // Loglevel INFO
    1940             :          << "Making mask image " << maskName << ", applying threshold "
    1941           0 :          << threshold.get("Jy").getValue() << "Jy, " << endl
    1942           0 :          << "to template image " << image << LogIO::POST;
    1943             :     
    1944           0 :       StokesImageUtil::MaskFrom(maskImage, imageImage, threshold);
    1945             :     }
    1946             :     else{
    1947             :       os << LogIO::NORMAL // Loglevel INFO
    1948             :          << "Making mask image " << maskName << ", applying threshold "
    1949           0 :          << threshold.getValue() << " " << threshold.getUnit() << endl
    1950           0 :          << "to template image " << image << LogIO::POST;
    1951             :     
    1952           0 :       StokesImageUtil::MaskFrom(maskImage, imageImage, threshold.getValue());
    1953             :     }
    1954           0 :     maskImage.table().unmarkForDelete();
    1955             : 
    1956             :     //this->lock();
    1957           0 :     return true;
    1958           0 :   } catch (AipsError x) {
    1959             :     //this->unlock();
    1960             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1961           0 :        << LogIO::EXCEPTION;
    1962           0 :     return false;
    1963           0 :   } 
    1964             :   //this->unlock();
    1965             :   return true;
    1966           0 : }
    1967             : 
    1968           0 : Bool Imager::boxmask(const String& mask, const Vector<Int>& blc,
    1969             :                   const Vector<Int>& trc, const Float value) 
    1970             : {
    1971           0 :   if(!valid()) return false;
    1972             :   
    1973           0 :   LogIO os(LogOrigin("imager", "boxmask()", WHERE));
    1974             :   
    1975             :   try {
    1976             :     
    1977           0 :     if(!assertDefinedImageParameters()) return false;
    1978             :     
    1979           0 :     if(mask=="") {
    1980           0 :       os << LogIO::SEVERE << "Need name for mask image" << LogIO::EXCEPTION;
    1981           0 :       return false;
    1982             :     }
    1983           0 :     if(!Table::isWritable(mask)) {
    1984           0 :       make(mask);
    1985           0 :       this->lock();
    1986             :     }
    1987           0 :     PagedImage<Float> maskImage(mask);
    1988           0 :     maskImage.table().markForDelete();
    1989             :     
    1990             : 
    1991           0 :     IPosition iblc(blc);
    1992           0 :     IPosition itrc(trc);
    1993           0 :     IPosition iinc(iblc.nelements(), 1);
    1994           0 :     LCBox::verify(iblc, itrc, iinc, maskImage.shape());
    1995             :     
    1996             :     os << LogIO::DEBUG1
    1997             :        << "Setting '" << mask << "' blc=" << iblc
    1998           0 :        << " trc=" << itrc << " to " << value << LogIO::POST;
    1999             :     
    2000           0 :     StokesImageUtil::BoxMask(maskImage, iblc, itrc, value);
    2001             :     
    2002           0 :     maskImage.table().unmarkForDelete();
    2003             : 
    2004           0 :     this->unlock();
    2005           0 :     return true;
    2006           0 :   } catch (AipsError x) {
    2007           0 :     this->unlock();
    2008             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2009           0 :        << LogIO::EXCEPTION;
    2010           0 :     return false;
    2011           0 :   } 
    2012             :   return true;
    2013           0 : }
    2014             : 
    2015           0 :   Bool Imager::regionmask(const String& maskimage, Record* imageRegRec, 
    2016             :                           Matrix<Quantity>& blctrcs, Matrix<Float>& circles, 
    2017             :                           const Float& value){
    2018             : 
    2019             :   //This function does not modify ms(s) so no need of lock 
    2020           0 :   LogIO os(LogOrigin("imager", "regionmask()", WHERE));
    2021           0 :   if(!Table::isWritable(maskimage)) {
    2022           0 :     make(maskimage);
    2023             :   }
    2024           0 :   return Imager::regionToImageMask(maskimage, imageRegRec, blctrcs, circles, value);
    2025             : 
    2026           0 : }
    2027             : 
    2028           0 :   Bool Imager::regionToImageMask(const String& maskimage, Record* imageRegRec, Matrix<Quantity>& blctrcs, Matrix<Float>& circles, const Float& value){
    2029           0 :   PagedImage<Float> maskImage(maskimage);
    2030           0 :   CoordinateSystem cSys=maskImage.coordinates();
    2031           0 :   maskImage.table().markForDelete();
    2032           0 :   ImageRegion *boxregions=0;
    2033           0 :   ImageRegion *circleregions=0;
    2034           0 :   RegionManager regMan;
    2035           0 :   regMan.setcoordsys(cSys);
    2036           0 :   Vector<Quantum<Double> > blc(2);
    2037           0 :   Vector<Quantum<Double> > trc(2);
    2038           0 :   if(blctrcs.nelements() !=0){
    2039           0 :     if(blctrcs.shape()(1) != 4)
    2040           0 :       throw(AipsError("Need a list of 4 elements to define a box"));
    2041           0 :     Int nrow=blctrcs.shape()(0);
    2042           0 :     Vector<Int> absRel(2, RegionType::Abs); 
    2043           0 :     PtrBlock<const WCRegion *> lesbox(nrow);
    2044           0 :     for (Int k=0; k < nrow; ++k){
    2045           0 :       blc(0) = blctrcs(k,0);
    2046           0 :       blc(1) = blctrcs(k,1);
    2047           0 :       trc(0) = blctrcs(k,2);
    2048           0 :       trc(1) = blctrcs(k,3); 
    2049           0 :       lesbox[k]= new WCBox (blc, trc, cSys, absRel);
    2050             :     }
    2051           0 :     boxregions=regMan.doUnion(lesbox);
    2052           0 :     for (Int k=0; k < nrow; ++k){
    2053           0 :       delete lesbox[k];
    2054             :     }
    2055           0 :   }
    2056           0 :   if((circles.nelements()) > 0){
    2057           0 :     if(circles.shape()(1) != 3)
    2058           0 :       throw(AipsError("Need a list of 3 elements to define a circle"));
    2059           0 :     Int nrow=circles.shape()(0);
    2060           0 :     Vector<Float> cent(2); 
    2061           0 :     cent(0)=circles(0,1); cent(1)=circles(0,2);
    2062           0 :     Float radius=circles(0,0);
    2063           0 :     IPosition xyshape(2,maskImage.shape()(0),maskImage.shape()(1));
    2064           0 :     LCEllipsoid *circ= new LCEllipsoid(cent, radius, xyshape);
    2065             :     //Tell LCUnion to delete the pointers
    2066           0 :     LCUnion *elunion= new LCUnion(true, circ);
    2067             :     //now lets do the remainder
    2068           0 :     for (Int k=1; k < nrow; ++k){
    2069           0 :       cent(0)=circles(k,1); cent(1)=circles(k,2);
    2070           0 :       radius=circles(k,0);
    2071           0 :       circ= new LCEllipsoid(cent, radius, xyshape); 
    2072           0 :       elunion=new LCUnion(true, elunion, circ);
    2073             :     }
    2074             :     //now lets extend that to the whole image
    2075           0 :     IPosition trc(2);
    2076           0 :     trc(0)=maskImage.shape()(2)-1;
    2077           0 :     trc(1)=maskImage.shape()(3)-1;
    2078           0 :     LCBox lbox(IPosition(2,0,0), trc, 
    2079           0 :                IPosition(2,maskImage.shape()(2),maskImage.shape()(3)) );
    2080           0 :     LCExtension linter(*elunion, IPosition(2,2,3),lbox);
    2081           0 :     circleregions=new ImageRegion(linter);
    2082           0 :     delete elunion;
    2083           0 :   }
    2084             : 
    2085             : 
    2086           0 :   ImageRegion* recordRegion=0;
    2087           0 :   if(imageRegRec !=0){
    2088           0 :     TableRecord rec1;
    2089           0 :     rec1.assign(*imageRegRec);
    2090           0 :     recordRegion=ImageRegion::fromRecord(rec1,"");    
    2091           0 :   }
    2092           0 :   ImageRegion *unionReg=0;
    2093           0 :   if(boxregions!=0 && recordRegion!=0){
    2094           0 :     unionReg=regMan.doUnion(*boxregions, *recordRegion);
    2095           0 :     delete boxregions; boxregions=0;
    2096           0 :     delete recordRegion; recordRegion=0;
    2097             :   }
    2098           0 :   else if(boxregions !=0){
    2099           0 :     unionReg=boxregions;
    2100             :   }
    2101           0 :   else if(recordRegion !=0){
    2102           0 :     unionReg=recordRegion;
    2103             :   }
    2104             :       
    2105             : 
    2106             :  
    2107             :   
    2108           0 :   if(unionReg !=0){
    2109           0 :     regionToMask(maskImage, *unionReg, value);
    2110           0 :     delete unionReg; unionReg=0;
    2111             :   }
    2112             :   //As i can't unionize LCRegions and WCRegions;  do circles seperately
    2113           0 :   if(circleregions !=0){
    2114           0 :     regionToMask(maskImage, *circleregions, value);
    2115           0 :     delete circleregions;
    2116           0 :     circleregions=0;
    2117             :   }
    2118           0 :   maskImage.table().unmarkForDelete();
    2119           0 :   return true;
    2120             : 
    2121           0 : }
    2122             : 
    2123             : 
    2124           0 : Bool Imager::regionToMask(ImageInterface<Float>& maskImage, ImageRegion& imagreg, const Float& value){
    2125             : 
    2126             :   
    2127           0 :   SubImage<Float> partToMask(maskImage, imagreg, true);
    2128           0 :   LatticeRegion latReg=imagreg.toLatticeRegion(maskImage.coordinates(), maskImage.shape());
    2129           0 :   ArrayLattice<Bool> pixmask(latReg.get());
    2130           0 :   LatticeExpr<Float> myexpr(iif(pixmask, value, partToMask) );
    2131           0 :   partToMask.copyData(myexpr);
    2132             : 
    2133           0 :   return true;
    2134           0 : }
    2135             : 
    2136             : 
    2137           0 : Bool Imager::clipimage(const String& image, const Quantity& threshold)
    2138             : {
    2139           0 :   if(!valid()) return false;
    2140             :   
    2141           0 :   LogIO os(LogOrigin("imager", "clipimage()", WHERE));
    2142             :   
    2143           0 :   this->lock();
    2144             :   try {
    2145             :     
    2146           0 :     if(!assertDefinedImageParameters()) return false;
    2147             :     
    2148           0 :     if(image=="") {
    2149           0 :       this->unlock();
    2150           0 :       os << LogIO::SEVERE << "Need name for image" << LogIO::EXCEPTION;
    2151           0 :       return false;
    2152             :     }
    2153           0 :     PagedImage<Float> imageImage(image);
    2154             :     os << LogIO::NORMAL // Loglevel PROGRESS
    2155             :        << "Zeroing " << image << ", for all pixels where Stokes I < threshold "
    2156           0 :        << threshold.get("Jy").getValue() << "Jy " << LogIO::POST;
    2157             :     
    2158           0 :     StokesImageUtil::MaskOnStokesI(imageImage, threshold);
    2159           0 :     this->unlock();
    2160           0 :     return true;
    2161           0 :   } catch (AipsError x) {
    2162           0 :     this->unlock();
    2163             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2164           0 :        << LogIO::EXCEPTION;
    2165           0 :     return false;
    2166           0 :   } 
    2167             :   
    2168             :   return true;
    2169           0 : }
    2170             : 
    2171             : // Add together low and high resolution images in the Fourier plane
    2172          13 : Bool Imager::feather(const String& image, const String& highRes,
    2173             :                      const String& lowRes, const String& lowPSF, const Float effDishDiam, const Bool lowPassFilterSD)
    2174             : {
    2175             :   
    2176          13 :   Float effDiam=effDishDiam;
    2177          13 :   LoggerHolder lh (false);
    2178          13 :   LogIO os = lh.logio();
    2179          13 :   os << LogOrigin("imager", "feather()");
    2180             :   
    2181             :   try {
    2182          13 :     Bool noStokes=false;
    2183          13 :     String outLowRes=lowRes;
    2184          13 :     String outHighRes=highRes;
    2185             :     {
    2186          13 :       if ( ! doVP_p ) {
    2187           0 :         this->unlock();
    2188             :         os << LogIO::SEVERE << 
    2189             :           "Must invoke setvp() first in order to apply the primary beam" 
    2190           0 :            << LogIO::EXCEPTION;
    2191           0 :         return false;
    2192             :       }
    2193             :       
    2194             :       os << LogIO::NORMAL // Loglevel PROGRESS
    2195          13 :          << "\nFeathering together high and low resolution images...\n" << LogIO::POST;
    2196             :       
    2197             :      
    2198             :       // Get initial images
    2199             :       /*{ //Drat lets deal with images that don't have stokes.
    2200             :         PagedImage<Float> hightemp(highRes);
    2201             :         PagedImage<Float> lowtemp(lowRes);
    2202             :         if(hightemp.shape().nelements() != lowtemp.shape().nelements()){
    2203             :           this->unlock();
    2204             :           os << LogIO::SEVERE << 
    2205             :             "High res. image and low res. image donot have same number of axes" 
    2206             :              << LogIO::EXCEPTION;
    2207             :           return false;
    2208             :           
    2209             :         }
    2210             :         if ( (hightemp.coordinates().findCoordinate(Coordinate::STOKES) < 0) &&
    2211             :              (lowtemp.coordinates().findCoordinate(Coordinate::STOKES) < 0)){
    2212             :           noStokes=true;
    2213             :           os << LogIO::NORMAL // Loglevel PROGRESS
    2214             :              << "Making some temporary images as the inputs have no Stokes axis.\n" 
    2215             :              << LogIO::POST;
    2216             :           std::unique_ptr<ImageInterface<Float> > outImage1;
    2217             :           outHighRes= highRes+"_stokes";
    2218             :           ImageUtilities::addDegenerateAxes (os, outImage1, hightemp, outHighRes,
    2219             :                                              false, false,
    2220             :                                              "I", false, false,
    2221             :                                              false);
    2222             : 
    2223             :           std::unique_ptr<ImageInterface<Float> > outImage2;
    2224             :           outLowRes= lowRes+"_stokes";
    2225             :           ImageUtilities::addDegenerateAxes (os, outImage2, lowtemp, outLowRes,
    2226             :                                              false, false,
    2227             :                                              "I", false, false,
    2228             :                                              false);
    2229             :           
    2230             :                                              }
    2231             :       }*/
    2232             : 
    2233             : 
    2234             :       
    2235          13 :       PagedImage<Float> high(outHighRes);
    2236          13 :       PagedImage<Float> low0(outLowRes);
    2237          26 :       PagedImage<Float> featherImage(high.shape(), high.coordinates(), image );
    2238             : 
    2239             :       //Check if either the high or low res cubes have per-plane beams. 
    2240          13 :       ImageBeamSet highbeam = high.imageInfo().getBeamSet();
    2241          13 :       ImageBeamSet lowbeam = low0.imageInfo().getBeamSet();
    2242             : 
    2243          13 :       IPosition shp = high.shape();
    2244          13 :       if(highbeam.hasMultiBeam() || lowbeam.hasMultiBeam())
    2245             :         {
    2246           2 :           os << "One or both of the input images has per-plane restoring beams. Calling feather in a loop, per plane." << LogIO::POST;
    2247           2 :           IPosition blc (shp.nelements(),0);
    2248           2 :           IPosition trc = shp - 1;
    2249             :           //Assuming that the spatial axes are 0 and 1
    2250           8 :           for(uInt chan=0;chan<shp[3];++chan)
    2251             :             {
    2252           6 :               blc[3]=chan;
    2253           6 :               trc[3]=chan;
    2254          12 :               for(uInt pol=0;pol<shp[2];++pol)
    2255             :                 {
    2256           6 :                   blc[2]=pol;
    2257           6 :                   trc[2]=pol;
    2258           6 :                   Slicer aslice( blc, trc, Slicer::endIsLast );
    2259           6 :                   SubImage<Float> imageplane( featherImage, aslice, true );
    2260           6 :                   SubImage<Float> highplane( high, aslice, true );
    2261           6 :                   SubImage<Float> low0plane( low0, aslice, true );
    2262           6 :                   Feather::feather(imageplane, highplane, low0plane, sdScale_p, lowPSF, doDefaultVP_p, vpTableStr_p, effDiam, lowPassFilterSD);
    2263           6 :                 }
    2264             :             }
    2265           2 :         }
    2266             :       else  // Neither image has multi beams. 
    2267             :         {
    2268          11 :           os << "Each input image has a single restoring beam." << LogIO::POST;
    2269             :           // Assumes one plane, or one restoring beam. 
    2270          11 :           Feather::feather(featherImage, high, low0, sdScale_p, lowPSF, doDefaultVP_p, vpTableStr_p, effDiam, lowPassFilterSD);
    2271             :         }    
    2272          18 :     }
    2273             :     
    2274          12 :     if(noStokes){
    2275           0 :       TableUtil::deleteTable(outHighRes);
    2276           0 :       TableUtil::deleteTable(outLowRes);
    2277             :     }
    2278          12 :     return true;
    2279          15 :   } catch (AipsError x) {
    2280             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2281           1 :        << LogIO::EXCEPTION;
    2282           0 :     return false;
    2283           2 :   } 
    2284             :   
    2285             :   return true;
    2286          14 : }
    2287             : 
    2288             : 
    2289             : 
    2290           0 : Bool Imager::linearmosaic(const String& mosaic,
    2291             :                           const String& fluxscale,
    2292             :                           const String& sensitivity,
    2293             :                           const Vector<String>& images,
    2294             :                           const Vector<Int>& fieldids)
    2295             : 
    2296             : {
    2297           0 :   if(!valid()) return false;
    2298           0 :   LogIO os(LogOrigin("imager", "linearmosaic()", WHERE));
    2299             :   try{
    2300           0 :     if(mosaic=="") {
    2301           0 :       os << LogIO::SEVERE << "Need name for mosaic image" << LogIO::POST;
    2302           0 :       return false;
    2303             :     }
    2304           0 :     if(!Table::isWritable( mosaic )) {
    2305           0 :       make( mosaic );
    2306             :     }
    2307           0 :     if (images.nelements() == 0) {
    2308           0 :       os << LogIO::SEVERE << "Need names of images to mosaic" << LogIO::POST;
    2309           0 :       return false;
    2310             :     }
    2311           0 :     if (images.nelements() != fieldids.nelements()) {
    2312             :       os << LogIO::SEVERE << "number of fieldids doesn\'t match the" 
    2313           0 :          << " number of images" << LogIO::POST;
    2314           0 :       return false;
    2315             :     }
    2316             :     
    2317           0 :     Double meminMB=Double(HostInfo::memoryTotal(true))/1024.0;
    2318           0 :     PagedImage<Float> mosaicImage( mosaic );
    2319           0 :     CoordinateSystem cs=mosaicImage.coordinates();
    2320           0 :     String err;
    2321             :     //for some reason subimages below  fail if they are in some frames like BARY
    2322           0 :     if(cs.setSpectralConversion(err, "LSRK")){
    2323           0 :       mosaicImage.setCoordinateInfo(cs);
    2324             :     }
    2325           0 :     mosaicImage.set(0.0);
    2326           0 :     TempImage<Float>  numerator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
    2327           0 :     numerator.set(0.0);
    2328           0 :     TempImage<Float>  denominator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
    2329           0 :     denominator.set(0.0);
    2330           0 :     ImageRegrid<Float> regridder;
    2331             :     
    2332           0 :     MSColumns msc(*ms_p);
    2333           0 :     for (uInt i=0; i < images.nelements(); ++i) {
    2334           0 :       if(!Table::isReadable(images(i))) {   
    2335             :         os << LogIO::SEVERE << "Image " << images(i) << 
    2336           0 :           " is not readable" << LogIO::POST;
    2337           0 :         return false;
    2338             :       }
    2339             :       
    2340           0 :       PagedImage<Float> smallImagedisk( images(i) );
    2341           0 :       cs=smallImagedisk.coordinates();
    2342             :       //for some reason subimages below  fail if they are in some frames like BARY
    2343           0 :       if(!cs.setSpectralConversion(err, "LSRK")){
    2344           0 :         cs=smallImagedisk.coordinates();
    2345             :       }
    2346             :       
    2347           0 :       TempImage<Float> smallImage(smallImagedisk.shape(), cs, meminMB/8.0);
    2348           0 :       smallImage.copyData(smallImagedisk);
    2349           0 :       IPosition iblc(smallImage.shape().nelements(),0);
    2350           0 :       IPosition itrc(smallImage.shape());
    2351           0 :       itrc=itrc-Int(1);
    2352             :       
    2353           0 :       LCBox lbox(iblc, itrc, smallImage.shape());
    2354           0 :       ImageRegion imagreg(WCBox(lbox, cs) );
    2355             :       try{
    2356             :         // accumulate the images
    2357           0 :         SubImage<Float> subNum;
    2358           0 :         SubImage<Float> subDen;
    2359             :         try{
    2360           0 :           subNum=SubImage<Float>(numerator, imagreg, true);
    2361           0 :           subDen=SubImage<Float>(denominator, imagreg, true);
    2362             :         }
    2363           0 :         catch(...){
    2364             :           //Failed to make a subimage let us use the full image
    2365           0 :           subNum=SubImage<Float>(numerator, true);
    2366           0 :           subDen=SubImage<Float>(denominator, true);
    2367             :           
    2368           0 :         }
    2369             :         
    2370             :         
    2371             :         
    2372           0 :         TempImage<Float> fullImage(subNum.shape(), subNum.coordinates(), meminMB/8.0);
    2373             :         
    2374           0 :         os  << "Processing Image " << images(i)  << LogIO::POST;
    2375             :         
    2376           0 :         regridder.regrid( fullImage, Interpolate2D::LINEAR,
    2377           0 :                           IPosition(2,0,1), smallImage );
    2378             :         
    2379           0 :         TempImage<Float>  PB( subNum.shape(), subNum.coordinates(), meminMB/8.0);
    2380           0 :         PB.set(1.0);
    2381             :         
    2382           0 :         MDirection pointingDirection = msc.field().phaseDirMeas( fieldids(i) );
    2383             :         
    2384           0 :         Quantity pa(0.0, "deg");
    2385           0 :         pbguts ( PB, PB, pointingDirection, pa);
    2386             :         
    2387           0 :         fullImage.copyData( (LatticeExpr<Float>) (fullImage *  PB ) );
    2388           0 :         subNum.copyData( (LatticeExpr<Float>) (subNum + fullImage) );
    2389           0 :         subDen.copyData( (LatticeExpr<Float>) (subDen + (PB*PB)) );
    2390             :         
    2391           0 :       }
    2392           0 :       catch (AipsError x) {
    2393             :         os << LogIO::WARN<< "Caught exception while processing  " << images(i) 
    2394             :            << "\n"<< x.getMesg()
    2395           0 :            << LogIO::POST;
    2396           0 :         continue;
    2397           0 :       } 
    2398           0 :       catch(...){
    2399           0 :         os << LogIO::WARN << "Unknown error processing " << images(i) << LogIO::POST; 
    2400           0 :         continue;
    2401           0 :       }
    2402           0 :     }
    2403             :     
    2404           0 :     LatticeExprNode LEN = max( denominator );
    2405           0 :     Float dMax =  LEN.getFloat();
    2406             :     
    2407             :     
    2408           0 :     if (scaleType_p == "SAULT") {
    2409             :       
    2410             :       // truncate denominator at ggSMin1
    2411           0 :       denominator.copyData( (LatticeExpr<Float>) 
    2412           0 :                             (iif(denominator < (dMax * constPB_p), dMax, 
    2413             :                                  denominator) ) );
    2414             :       
    2415           0 :       if (fluxscale != "") {
    2416           0 :         clone( mosaic, fluxscale );
    2417             :         
    2418           0 :         PagedImage<Float> fluxscaleImage( fluxscale );
    2419           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>) 
    2420           0 :                                  (iif(denominator < (dMax*minPB_p), 0.0,
    2421           0 :                                       (dMax*minPB_p)/(denominator) )) );
    2422           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>) 
    2423           0 :                                  (iif(denominator > (dMax*constPB_p), 1.0,
    2424             :                                       (fluxscaleImage) )) );
    2425           0 :         mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
    2426           0 :                                                        (numerator/denominator), 0)) );
    2427           0 :       }
    2428             :     } else {
    2429           0 :       mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
    2430           0 :                                                      (numerator/denominator), 0)) );
    2431           0 :       if (fluxscale != "") {
    2432           0 :         clone(mosaic, fluxscale );
    2433           0 :         PagedImage<Float> fluxscaleImage( fluxscale );
    2434           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>)( 1.0 ) );
    2435           0 :       }
    2436             :     }
    2437           0 :     if (sensitivity != "") {
    2438           0 :       clone(mosaic, sensitivity);
    2439           0 :       PagedImage<Float> sensitivityImage( sensitivity );
    2440           0 :       sensitivityImage.copyData( (LatticeExpr<Float>)( denominator/dMax ));
    2441           0 :     }
    2442           0 :   }
    2443           0 :   catch (AipsError x) {
    2444             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2445           0 :        << LogIO::POST;
    2446           0 :     return false;
    2447           0 :   } 
    2448           0 :   return true;
    2449           0 : }
    2450             : 
    2451             : // Weight the MeasurementSet
    2452           0 : Bool Imager::weight(const String& type, const String& crmode,
    2453             :                  const Quantity& noise, const Double robust,
    2454             :                  const Quantity& fieldofview,
    2455             :                     const Int npixels, const Bool multiField)
    2456             : {
    2457           0 :   if(!valid()) return false;
    2458           0 :   logSink_p.clearLocally();
    2459           0 :   LogIO os(LogOrigin("imager", "weight()"),logSink_p);
    2460             :   
    2461           0 :   this->lock();
    2462             :   try {
    2463             :     
    2464           0 :     String rmode=crmode; // can change it 
    2465             : 
    2466             : 
    2467             :     os << LogIO::NORMAL // Loglevel INFO
    2468           0 :        << "Weighting MS: Imaging weights will be changed" << LogIO::POST;
    2469             :     
    2470           0 :     if (type=="natural") {
    2471             :       os << LogIO::NORMAL // Loglevel INFO
    2472           0 :          << "Natural weighting" << LogIO::POST;
    2473           0 :       imwgt_p=VisImagingWeight("natural");
    2474             :     }
    2475           0 :     else if(type=="superuniform"){
    2476           0 :       if(!assertDefinedImageParameters()) return false;
    2477             :       ///making usage of npixels consistent with uniform, briggs
    2478             :       /// don't know why this was done seperately which is kind of redundant in the code
    2479             :       /// one achieves superuniform with  just uniform with npixels or fieldofview 
    2480             :       /// set to non-defaults in the section below
    2481           0 :       Int actualNpix=npixels/2;
    2482           0 :       if(actualNpix <=0)
    2483           0 :         actualNpix=3;
    2484             :       os << LogIO::NORMAL // Loglevel INFO
    2485             :          << "SuperUniform weighting over a square cell spanning [" 
    2486             :          << -actualNpix 
    2487           0 :          << ", " << actualNpix << "] in the uv plane" << LogIO::POST;
    2488           0 :       imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, nx_p, 
    2489           0 :                                ny_p, mcellx_p, mcelly_p, actualNpix, 
    2490           0 :                                actualNpix, multiField);
    2491             :     }
    2492           0 :     else if ((type=="robust")||(type=="uniform")||(type=="briggs")) {
    2493           0 :       if(!assertDefinedImageParameters()) return false;
    2494           0 :       Quantity actualFieldOfView(fieldofview);
    2495           0 :       Int actualNPixels(npixels);
    2496           0 :       String wtype;
    2497           0 :       if(type=="briggs") {
    2498             :         //The user really meant to use Brigg's weighting and forgot to set norm or abs
    2499             :         // guessing it should be norm
    2500           0 :         if(rmode=="none")
    2501           0 :           rmode="norm";
    2502           0 :         wtype = "Briggs";
    2503             :       }
    2504             :       else {
    2505           0 :         wtype = "Uniform";
    2506             :       }
    2507           0 :       if(actualFieldOfView.get().getValue()==0.0&&actualNPixels==0) {
    2508           0 :         actualNPixels=nx_p;
    2509           0 :         actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
    2510           0 :                                                                    "rad");
    2511             :         os << LogIO::NORMAL // Loglevel INFO
    2512             :            << wtype
    2513             :            << " weighting: sidelobes will be suppressed over full image"
    2514           0 :            << LogIO::POST;
    2515             :       }
    2516           0 :       else if(actualFieldOfView.get().getValue()>0.0&&actualNPixels==0) {
    2517           0 :         actualNPixels=Int(actualFieldOfView.get("rad").getValue()/mcellx_p.get("rad").getValue());
    2518             :         os << LogIO::NORMAL // Loglevel INFO
    2519             :            << wtype
    2520             :            << " weighting: sidelobes will be suppressed over specified field of view: "
    2521           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2522             :       }
    2523           0 :       else if(actualFieldOfView.get().getValue()==0.0&&actualNPixels>0) {
    2524           0 :         actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
    2525           0 :                                                                    "rad");
    2526             :         os << LogIO::NORMAL // Loglevel INFO
    2527             :            << wtype
    2528             :            << " weighting: sidelobes will be suppressed over full image field of view: "
    2529           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2530             :       }
    2531             :       else {
    2532             :         os << LogIO::NORMAL // Loglevel INFO
    2533             :            << wtype
    2534             :            << " weighting: sidelobes will be suppressed over specified field of view: "
    2535           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2536             :       }
    2537             :       os << LogIO::DEBUG1
    2538             :          << "Weighting used " << actualNPixels << " uv pixels."
    2539           0 :          << LogIO::POST;
    2540           0 :       Quantity actualCellSize(actualFieldOfView.get("rad").getValue()/actualNPixels, "rad");
    2541             : 
    2542           0 :       imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, 
    2543             :                                actualNPixels, actualNPixels, actualCellSize, 
    2544           0 :                                actualCellSize, 0, 0, multiField);
    2545             :       
    2546           0 :     }
    2547           0 :     else if (type=="radial") {
    2548           0 :       os << "Radial weighting" << LogIO::POST;
    2549           0 :       imwgt_p=VisImagingWeight("radial");
    2550             :     }
    2551             :     else {
    2552           0 :       this->unlock();
    2553             :       os << LogIO::SEVERE << "Unknown weighting " << type
    2554           0 :          << LogIO::EXCEPTION;    
    2555           0 :       return false;
    2556             :     }
    2557             :     
    2558           0 :       rvi_p->useImagingWeight(imwgt_p);
    2559             :     
    2560             :     // Beam is no longer valid
    2561           0 :     beamValid_p=false;
    2562           0 :     destroySkyEquation();
    2563           0 :     this->writeHistory(os);
    2564           0 :     this->unlock();
    2565           0 :     return true;
    2566           0 :   } catch (AipsError x) {
    2567           0 :     this->unlock();
    2568             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2569           0 :        << LogIO::EXCEPTION;
    2570           0 :     return false;
    2571           0 :   } 
    2572             :   
    2573             :   return true;
    2574           0 : }
    2575             : 
    2576             : 
    2577           0 : Bool Imager::getWeightGrid(Block<Matrix<Float> >&weightgrid, const String& type, const Vector<String>&imagenames){
    2578             : 
    2579           0 :   if(type=="imaging"){
    2580           0 :     weightgrid.resize(0, true, false);
    2581           0 :     if(imwgt_p.getType()!="uniform")
    2582           0 :       return false;
    2583           0 :     imwgt_p.getWeightDensity(weightgrid);
    2584           0 :     return true;
    2585             :   }
    2586           0 :   if((type=="ftweight") && (sm_p) && (Int(imagenames.nelements())== sm_p->numberOfModels())){
    2587           0 :     for (Int model=0; model < sm_p->numberOfModels(); ++model){
    2588           0 :       PagedImage<Float> wgtImage(sm_p->image(model).shape(),
    2589           0 :                                    (sm_p->image(model)).coordinates(),
    2590           0 :                                    imagenames(model));
    2591           0 :       se_p->getWeightImage(model, wgtImage);
    2592             :       
    2593             : 
    2594           0 :     }
    2595           0 :     return true;
    2596             :   } 
    2597             :         
    2598           0 :   return false;
    2599             : }
    2600             : 
    2601           0 : Bool Imager::setWeightGrid(const Block<Matrix<Float> >& weightgrid, const String& type){
    2602             : 
    2603           0 :   if(type=="imaging"){
    2604           0 :     if(imwgt_p.getType()!="uniform")
    2605           0 :       return false;
    2606           0 :     imwgt_p.setWeightDensity(weightgrid);
    2607           0 :     rvi_p->useImagingWeight(imwgt_p);
    2608             :   }
    2609             : 
    2610           0 :   return true;
    2611             : }
    2612             : 
    2613             : // Filter the MeasurementSet
    2614           0 : Bool Imager::filter(const String& type, const Quantity& bmaj,
    2615             :                  const Quantity& bmin, const Quantity& bpa)
    2616             : {
    2617           0 :   if(!valid()) return false;
    2618           0 :   logSink_p.clearLocally();
    2619           0 :   LogIO os(LogOrigin("imager", "filter()"),logSink_p);
    2620             :   
    2621           0 :   this->lock();
    2622             :   try {
    2623             :       
    2624             :     os << LogIO::NORMAL // Loglevel INFO
    2625           0 :        << "Imaging weights will be tapered" << LogIO::POST;
    2626           0 :     imwgt_p.setFilter(type, bmaj, bmin, bpa);
    2627           0 :     rvi_p->useImagingWeight(imwgt_p);
    2628             :       
    2629             :     // Beam is no longer valid
    2630           0 :     beamValid_p=false;
    2631           0 :     destroySkyEquation();
    2632           0 :     this->writeHistory(os);
    2633           0 :     this->unlock();
    2634           0 :     return true;
    2635           0 :   } catch (AipsError x) {
    2636           0 :     this->unlock();
    2637           0 :     throw(x);
    2638             :     return false;
    2639           0 :   } 
    2640             :   
    2641             :   return true;
    2642           0 : }
    2643             : 
    2644             : 
    2645             : // Implement a uv range
    2646           0 : Bool Imager::uvrange(const Double& uvmin, const Double& uvmax)
    2647             : {
    2648           0 :   if(!valid()) return false;
    2649           0 :   logSink_p.clearLocally();
    2650           0 :   LogIO os(LogOrigin("imager", "uvrange()"),logSink_p);
    2651             :   
    2652             :   try {
    2653             :     os << LogIO::NORMAL // Loglevel INFO
    2654             :        << "Selecting data according to  uvrange: setdata will reset this selection"
    2655           0 :        << LogIO::POST;
    2656             : 
    2657           0 :     Double auvmin(uvmin);
    2658           0 :     Double auvmax(uvmax);
    2659             : 
    2660           0 :     if(auvmax<=0.0) auvmax=1e10;
    2661           0 :     if(auvmax>auvmin&&(auvmin>=0.0)) {
    2662             :       os << LogIO::NORMAL // Loglevel INFO
    2663             :          << "Allowed uv range: " << auvmin << " to " << auvmax
    2664           0 :          << " wavelengths" << LogIO::POST;
    2665             :     }
    2666             :     else {
    2667             :       os << LogIO::SEVERE << "Invalid uvmin and uvmax: "
    2668             :          << auvmin << ", " << auvmax
    2669           0 :          << LogIO::EXCEPTION;
    2670           0 :       return false;
    2671             :     }
    2672           0 :     Vector<Double> freq;
    2673           0 :     ostringstream strUVmax, strUVmin, ostrInvLambda;
    2674             : 
    2675           0 :     this->lock();
    2676             :       
    2677           0 :     if(mssel_p.null()){ os << "Please setdata first before using uvrange " << LogIO::POST; return false; }
    2678             : 
    2679             : 
    2680             :      // use the average wavelength for the selected windows to convert
    2681             :      // uv-distance from lambda to meters
    2682           0 :      ostringstream spwsel;
    2683           0 :      spwsel << "select from $1 where ROWID() IN [";
    2684           0 :      for(uInt i=0; i < dataspectralwindowids_p.nelements(); ++i) {
    2685           0 :          if (i > 0) spwsel << ", ";
    2686           0 :          spwsel << dataspectralwindowids_p(i);
    2687             :      }
    2688           0 :      spwsel << "]";
    2689             : 
    2690           0 :      MSSpectralWindow msspw(tableCommand(spwsel.str(), 
    2691           0 :                                          mssel_p->spectralWindow()).table());
    2692           0 :      MSSpWindowColumns spwc(msspw);
    2693             : 
    2694             :      // This averaging scheme will work even if the spectral windows are
    2695             :      // of different sizes.  Note, however, that using an average wavelength
    2696             :      // may not be a good choice when the total range in frequency is 
    2697             :      // large (e.g. mfs across double sidebands).
    2698           0 :      uInt nrows = msspw.nrow();
    2699           0 :      Double ftot = 0.0;
    2700           0 :      Int nchan = 0;
    2701           0 :      for(uInt i=0; i < nrows; ++i) {
    2702           0 :          nchan += (spwc.numChan())(i);
    2703           0 :          ftot += sum((spwc.chanFreq())(i));
    2704             :      }
    2705           0 :      Double invLambda=ftot/(nchan*C::c);
    2706             : 
    2707             :      // This is message may not be helpful as mfs is set with setimage()
    2708             :      // which may sometimes get called after uvrange()
    2709           0 :      if (nrows > 1 && imageMode_p=="MFS") {
    2710             :          os << LogIO::WARN 
    2711             :             << "When using mfs over a broad range of frequencies, It is more "
    2712             :             << "accurate to " << endl 
    2713             :             << "constrain uv-ranges using setdata(); try: " << endl 
    2714             :             << "  msselect='(SQUARE(UVW[1]) + SQUARE(UVW[2])) > uvmin && "
    2715             :             << "(SQUARE(UVW[1]) + SQUARE(UVW[2])) < uvmax'" << endl
    2716             :             << "where [uvmin, uvmax] is the range given in meters." 
    2717           0 :             << LogIO::POST;
    2718             :      }
    2719             : 
    2720           0 :      invLambda=invLambda*invLambda;
    2721           0 :      auvmax=auvmax*auvmax;
    2722           0 :      auvmin=auvmin*auvmin;
    2723           0 :      strUVmax << auvmax; 
    2724           0 :      strUVmin << auvmin;
    2725           0 :      ostrInvLambda << invLambda; 
    2726           0 :      String strInvLambda=ostrInvLambda;
    2727             :      MeasurementSet* mssel_p2;
    2728             : 
    2729             :      // Apply the TAQL selection string, to remake the selected MS
    2730           0 :      String parseString="select from $1 where (SQUARE(UVW[1]) + SQUARE(UVW[2]))*" + (string) strInvLambda + " > " + strUVmin.str( ) + " &&  (SQUARE(UVW[1]) + SQUARE(UVW[2]))*" + (string) strInvLambda + " < " + strUVmax.str( );
    2731             : 
    2732           0 :      mssel_p2=new MeasurementSet(tableCommand(parseString,*mssel_p).table());
    2733           0 :      AlwaysAssert(mssel_p2, AipsError);
    2734             :      // Rename the selected MS as */SELECTED_UVRANGE
    2735             :      //mssel_p2->rename(msname_p+"/SELECTED_UVRANGE", Table::Scratch);
    2736             :       
    2737           0 :      if (mssel_p2->nrow()==0) {
    2738             :          os << LogIO::WARN
    2739             :             << "Selection string results in empty MS: "
    2740             :             << "reverting to sorted MeasurementSet"
    2741           0 :             << LogIO::POST;
    2742           0 :          delete mssel_p2;
    2743             :      } else {
    2744           0 :        if (!mssel_p.null()) {
    2745             :              os << LogIO::NORMAL // Loglevel INFO
    2746             :                 << "By UVRANGE selection previously selected number of rows "
    2747           0 :                 << mssel_p->nrow() << "  are now reduced to "
    2748           0 :                 << mssel_p2->nrow() << LogIO::POST; 
    2749             :              //delete mssel_p; 
    2750           0 :              mssel_p=mssel_p2;
    2751           0 :              mssel_p->flush();
    2752             :          }
    2753             :      }
    2754             :       
    2755             :      
    2756           0 :      this->makeVisSet(*mssel_p);
    2757           0 :      AlwaysAssert(rvi_p, AipsError);
    2758             : 
    2759             :      // NOW WE HAVE TO REDO THE VELOCITY INFO FOR visiter AS IN SETDATA
    2760             : 
    2761           0 :      this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
    2762           0 :                              dataNchan_p, dataStart_p, dataStep_p,
    2763           0 :                              mDataStart_p, mDataStep_p);
    2764             : 
    2765           0 :      this->writeHistory(os);
    2766           0 :      this->unlock();
    2767             :      
    2768             :      // Beam is no longer valid
    2769           0 :      beamValid_p=false;
    2770           0 :      return true;    
    2771           0 :   } catch (AipsError x) {
    2772           0 :     this->unlock();
    2773           0 :     throw(x);
    2774             :     return false;
    2775           0 :   } 
    2776             :   return true;
    2777           0 : }
    2778             : 
    2779             : // Find the sensitivity
    2780           0 : Bool Imager::sensitivity(Quantity& pointsourcesens, Double& relativesens,
    2781             :                          Double& sumwt,
    2782             :                          Double& effectiveBandwidth,
    2783             :                          Double& effectiveIntegration,
    2784             :                          Int& nBaselines,
    2785             :                          Matrix<Int>& mssChanSel,
    2786             :                          Vector<Vector<Int> >& nData,
    2787             :                          Vector<Vector<Double> >& sumwtChan,
    2788             :                          Vector<Vector<Double> >& sumwtsqChan,
    2789             :                          Vector<Vector<Double> >& sumInverseVarianceChan)
    2790             : {
    2791           0 :   if(!valid()) return false;
    2792           0 :   LogIO os(LogOrigin("imager", "sensitivity()", WHERE));
    2793             :   
    2794             :   try {
    2795             :     
    2796             :     os << LogIO::NORMAL // Loglevel INFO
    2797             :        << "Calculating sensitivity from imaging weights and from effective bandwidth and integration time"
    2798           0 :        << LogIO::POST;
    2799             :     
    2800           0 :     this->lock();
    2801           0 :     mssChanSel.assign(mssChanSel_p);
    2802             : 
    2803           0 :     VisSetUtil::Sensitivity(*rvi_p, mssFreqSel_p, mssChanSel, pointsourcesens, relativesens, sumwt,
    2804             :                             effectiveBandwidth, effectiveIntegration, nBaselines,nData, sumwtChan, 
    2805             :                             sumwtsqChan, sumInverseVarianceChan);
    2806             :     os << LogIO::NORMAL << "RMS Point source sensitivity  : " // Loglevel INFO
    2807           0 :        << pointsourcesens.get("Jy").getValue() << " Jy.m2/K"
    2808           0 :        << LogIO::POST;
    2809             :     os << LogIO::NORMAL // Loglevel INFO
    2810           0 :        << "Relative to natural weighting : " << relativesens << LogIO::POST;
    2811             :     os << LogIO::NORMAL // Loglevel INFO
    2812           0 :        << "Sum of weights                : " << sumwt << LogIO::POST;
    2813           0 :     this->unlock();
    2814           0 :     return true;
    2815           0 :   } catch (AipsError x) {
    2816           0 :     this->unlock();
    2817           0 :     throw(x);
    2818             :     return false;
    2819           0 :   } 
    2820             :   return true;
    2821           0 : }
    2822             : 
    2823           0 : Bool Imager::apparentSensitivity(Double& effSensitivity,
    2824             :                                  Double& relToNat) {
    2825           0 :   if(!valid()) return false;
    2826           0 :   LogIO os(LogOrigin("imager", "apparentSensitivity()", WHERE));
    2827             :   
    2828             :   try {
    2829             : 
    2830             :     os << LogIO::NORMAL // Loglevel INFO
    2831             :        << "Calculating apparent sensitivity from MS weights, as modified by gridding weight function"
    2832           0 :        << LogIO::POST;
    2833             :     os << LogIO::NORMAL // Loglevel INFO
    2834             :        << "(assuming that MS weights have correct scale and units)"
    2835           0 :        << LogIO::POST;
    2836             :     
    2837           0 :     this->lock();
    2838             :     
    2839           0 :     Double sumNatWt=0.0;
    2840           0 :     Double sumGridWt=0.0;
    2841           0 :     Double sumGridWt2OverNatWt=0.0;
    2842             :     
    2843           0 :     Float iNatWt(0.0),iGridWt(0.0);
    2844             :     
    2845           0 :     ROVisibilityIterator& vi(*rvi_p);
    2846           0 :     VisBuffer vb(vi);
    2847             :     //Bool doWtSp=vb.existsWeightSpectrum();
    2848           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    2849           0 :       for (vi.origin();vi.more();vi++) {
    2850           0 :         Int nRow=vb.nRow();
    2851           0 :         Vector<Bool> rowFlags=vb.flagRow();
    2852           0 :         Matrix<Bool> flag = vb.flag();
    2853             :         
    2854           0 :         Vector<Int>& a1(vb.antenna1()), a2(vb.antenna2());
    2855             :         
    2856           0 :         for (Int row=0; row<nRow; row++) {
    2857           0 :           if (!rowFlags(row) && a1(row)!=a2(row)) {  // exclude ACs
    2858           0 :             iNatWt=2.0f*vb.weight()(row);
    2859           0 :             for (Int ich=0;ich<vb.nChannel();++ich) {
    2860           0 :               if(!flag(ich,row)&&(iNatWt>0.0)) {
    2861           0 :                 iGridWt=2.0f*vb.imagingWeight()(ich,row);
    2862           0 :                 sumNatWt+=(iNatWt);
    2863           0 :                 sumGridWt+=(iGridWt);
    2864           0 :                 sumGridWt2OverNatWt+=(iGridWt*iGridWt/iNatWt);
    2865             :               }
    2866             :             }
    2867             :           }
    2868             :         }
    2869           0 :       }
    2870             :     }
    2871             :     
    2872           0 :     if (sumNatWt==0.0) {
    2873           0 :       os << "Cannot calculate sensitivity: sum of selected natural weights is zero" << LogIO::EXCEPTION;
    2874             :     }
    2875           0 :     if (sumGridWt==0.0) {
    2876           0 :       os << "Cannot calculate sensitivity: sum of gridded weights is zero" << LogIO::EXCEPTION;
    2877             :     }
    2878             : 
    2879           0 :     effSensitivity = sqrt(sumGridWt2OverNatWt)/sumGridWt;
    2880           0 :     Double natSensitivity = 1.0/sqrt(sumNatWt);
    2881           0 :     relToNat=effSensitivity/natSensitivity;
    2882             : 
    2883             :     os << LogIO::NORMAL << "RMS Point source sensitivity  : " // Loglevel INFO
    2884             :        << effSensitivity      //  << " Jy/beam"       // actually, units are arbitrary
    2885           0 :        << LogIO::POST;
    2886             :     os << LogIO::NORMAL // Loglevel INFO
    2887           0 :        << "Relative to natural weighting : " << relToNat << LogIO::POST;
    2888             : 
    2889           0 :     this->unlock();
    2890           0 :     return true;
    2891           0 :   } catch (AipsError x) {
    2892           0 :     this->unlock();
    2893           0 :     throw(x);
    2894             :     return false;
    2895           0 :   } 
    2896             :   return true;
    2897             :     
    2898           0 : }
    2899             : 
    2900             : 
    2901             : 
    2902             : 
    2903             : 
    2904             : // Calculate various sorts of image. Only one image
    2905             : // can be calculated at a time. The complex Image make
    2906             : // be retained if a name is given. This does not use
    2907             : // the SkyEquation.
    2908           0 : Bool Imager::makeimage(const String& type, const String& image,
    2909             :                        const String& compleximage, const Bool verbose)
    2910             : {
    2911           0 :   if(!valid()) 
    2912             :     {
    2913           0 :       return false;
    2914             :     }
    2915           0 :   LogIO os(LogOrigin("imager", "makeimage()", WHERE));
    2916             :   
    2917           0 :   this->lock();
    2918             :   try {
    2919           0 :     if(!assertDefinedImageParameters())
    2920             :       {
    2921           0 :         return false;
    2922             :       }
    2923             :     
    2924             :     os << LogIO::NORMAL // Loglevel INFO
    2925           0 :        << "Calculating image (without full skyequation)" << LogIO::POST;
    2926             :     
    2927           0 :     FTMachine::Type seType(FTMachine::OBSERVED);
    2928           0 :     Bool doSD(false);
    2929             : 
    2930           0 :     if(type=="observed") {
    2931           0 :       seType=FTMachine::OBSERVED;
    2932             :       os << LogIO::NORMAL // Loglevel INFO
    2933             :          << "Making dirty image from " << type << " data "
    2934           0 :          << LogIO::POST;
    2935             :     }
    2936           0 :     else if (type=="model") {
    2937           0 :       seType=FTMachine::MODEL;
    2938             :       os << LogIO::NORMAL // Loglevel INFO
    2939             :          << "Making dirty image from " << type << " data "
    2940           0 :          << LogIO::POST;
    2941             :     }
    2942           0 :     else if (type=="corrected") {
    2943           0 :       seType=FTMachine::CORRECTED;
    2944             :       os << LogIO::NORMAL // Loglevel INFO
    2945             :          << "Making dirty image from " << type << " data "
    2946           0 :          << LogIO::POST;
    2947             :     }
    2948           0 :     else if (type=="psf") {
    2949           0 :       seType=FTMachine::PSF;
    2950             :       os << "Making point spread function "
    2951           0 :          << LogIO::POST;
    2952             :     }
    2953           0 :     else if (type=="residual") {
    2954           0 :       seType=FTMachine::RESIDUAL;
    2955             :       os << LogIO::NORMAL // Loglevel INFO
    2956             :          << "Making dirty image from " << type << " data "
    2957           0 :          << LogIO::POST;
    2958             :     }
    2959           0 :     else if (type=="singledish-observed") {
    2960           0 :       doSD = true;
    2961           0 :       seType=FTMachine::OBSERVED;
    2962             :       os << LogIO::NORMAL // Loglevel INFO
    2963           0 :          << "Making single dish image from observed data" << LogIO::POST;
    2964             :     }
    2965           0 :     else if (type=="singledish") {
    2966           0 :       doSD = true;
    2967           0 :       seType=FTMachine::CORRECTED;
    2968             :       os << LogIO::NORMAL // Loglevel INFO
    2969           0 :          << "Making single dish image from corrected data" << LogIO::POST;
    2970             :     }
    2971           0 :     else if (type=="coverage") {
    2972           0 :       doSD = true;
    2973           0 :       seType=FTMachine::COVERAGE;
    2974             :       os << LogIO::NORMAL // Loglevel PROGRESS
    2975             :          << "Making single dish coverage function "
    2976           0 :          << LogIO::POST;
    2977             :     }
    2978           0 :     else if (type=="holography") {
    2979           0 :       doSD = true;
    2980           0 :       seType=FTMachine::CORRECTED;
    2981             :       os << LogIO::NORMAL // Loglevel INFO
    2982             :          << "Making complex holographic image from corrected data "
    2983           0 :          << LogIO::POST;
    2984             :     }
    2985           0 :     else if (type=="holography-observed") {
    2986           0 :       doSD = true;
    2987           0 :       seType=FTMachine::OBSERVED;
    2988             :       os << LogIO::NORMAL // Loglevel INFO
    2989             :          << "Making complex holographic image from observed data "
    2990           0 :          << LogIO::POST;
    2991             :     }
    2992           0 :     else if (type=="pb"){
    2993           0 :       if ( ! doVP_p ) {
    2994           0 :         if( ftmachine_p == "pbwproject" ){
    2995           0 :            os << LogIO::WARN << "Using pb from ft-machines" << LogIO::POST;
    2996             :         }
    2997             :         else{
    2998           0 :           this->unlock();
    2999             :           os << LogIO::SEVERE << 
    3000             :             "Must invoke setvp() first in order to make its image" 
    3001           0 :              << LogIO::EXCEPTION;
    3002           0 :           return false;
    3003             :         }
    3004             :       }
    3005           0 :       CoordinateSystem coordsys;
    3006             :       //imagecoordinates(coordsys, verbose);
    3007           0 :       imagecoordinates2(coordsys, verbose);
    3008           0 :       if (doDefaultVP_p) {
    3009           0 :         if(telescope_p!=""){
    3010           0 :           ObsInfo myobsinfo=this->latestObsInfo();
    3011           0 :           myobsinfo.setTelescope(telescope_p);
    3012           0 :           coordsys.setObsInfo(myobsinfo);
    3013             :           
    3014           0 :         }
    3015             :         else{
    3016           0 :           telescope_p=coordsys.obsInfo().telescope();
    3017             :         }
    3018           0 :         this->unlock();
    3019           0 :         MSAntennaColumns ac(ms_p->antenna());
    3020           0 :         Double dishDiam=ac.dishDiameter()(0);
    3021           0 :         if(!allEQ(ac.dishDiameter().getColumn(), dishDiam))
    3022             :           os << LogIO::WARN
    3023             :          << "The MS has multiple antenna diameters ..PB could be wrong "
    3024           0 :          << LogIO::POST;
    3025           0 :         return this->makePBImage(coordsys, telescope_p, image, false, dishDiam);
    3026           0 :       }
    3027             :       else{
    3028           0 :         Table vpTable(vpTableStr_p);
    3029           0 :         this->unlock();
    3030           0 :         return this->makePBImage(coordsys, vpTable, image);  
    3031           0 :       }
    3032             : 
    3033           0 :     }
    3034             :     else {
    3035           0 :       this->unlock();
    3036           0 :       os << LogIO::SEVERE << "Unknown image type " << type << LogIO::EXCEPTION;
    3037             : 
    3038           0 :       return false;
    3039             :     }
    3040             : 
    3041           0 :     if(doSD && (ftmachine_p == "ft")){
    3042             :       os << LogIO::SEVERE
    3043             :          << "To make single dish images, ftmachine in setoptions must be set to either sd or both"
    3044           0 :          << LogIO::EXCEPTION;
    3045             :     }
    3046             :     
    3047             :     // Now make the images. If we didn't specify the names then
    3048             :     // delete on exit.
    3049           0 :     String imageName(image);
    3050           0 :     if(image=="") {
    3051           0 :       imageName=Imager::imageName()+".image";
    3052             :     }
    3053           0 :     os << LogIO::NORMAL << "Image is : " << imageName << LogIO::POST; // Loglevel INFO
    3054           0 :     Bool keepImage=(image!="");
    3055           0 :     Bool keepComplexImage=(compleximage!="")||(type=="holography")||(type=="holography-observed");
    3056           0 :     String cImageName(compleximage);
    3057             : 
    3058           0 :     if(compleximage=="") {
    3059           0 :       cImageName=imageName+".compleximage";
    3060             :     }
    3061             : 
    3062           0 :     if(keepComplexImage) {
    3063           0 :       os << "Retaining complex image: " << compleximage << LogIO::POST;
    3064             :     }
    3065             : 
    3066           0 :     CoordinateSystem imagecoords;
    3067             :     //if(!imagecoordinates(imagecoords, false))
    3068           0 :     if(!imagecoordinates2(imagecoords, false))
    3069             :       {
    3070           0 :         return false;
    3071             :       }
    3072           0 :     make(imageName);
    3073           0 :     PagedImage<Float> imageImage(imageName);
    3074           0 :     imageImage.set(0.0);
    3075           0 :     imageImage.table().markForDelete();
    3076             :     
    3077             :     // Now set up the tile size, here we guess only
    3078           0 :     IPosition cimageShape(imageshape());
    3079           0 :     Int tilex=32;
    3080           0 :     if(imageTileVol_p >0){
    3081           0 :       tilex=static_cast<Int>(ceil(sqrt(imageTileVol_p/min(4,
    3082           0 :                                                           cimageShape(2))/min(32,
    3083           0 :                                                                               cimageShape(3)))));
    3084           0 :       if(tilex >0){
    3085           0 :         if(tilex > min(Int(cimageShape(0)), Int(cimageShape(1))))
    3086           0 :           tilex=min(Int(cimageShape(0)), Int(cimageShape(1)));
    3087             :         else
    3088           0 :           tilex=cimageShape(0)/Int(cimageShape(0)/tilex);
    3089             :       }
    3090             :       //Not too small in x-y tile
    3091           0 :       if(tilex < 10)
    3092           0 :         tilex=10;
    3093             :    
    3094             :     }
    3095           0 :     IPosition tileShape(4, min(tilex, cimageShape(0)), min(tilex, cimageShape(1)),
    3096           0 :                         min(4, cimageShape(2)), min(32, cimageShape(3)));
    3097           0 :     CoordinateSystem cimagecoords;
    3098             :     //if(!imagecoordinates(cimagecoords, false))
    3099           0 :     if(!imagecoordinates2(cimagecoords, false))
    3100             :       {
    3101           0 :         return false;
    3102             :       }
    3103             : 
    3104             : 
    3105             :     
    3106           0 :     PagedImage<Complex> cImageImage(TiledShape(cimageShape, tileShape),
    3107             :                                     cimagecoords,
    3108           0 :                                     cImageName);
    3109           0 :     cImageImage.set(Complex(0.0));
    3110           0 :     cImageImage.setMaximumCacheSize(cache_p/2);
    3111           0 :     cImageImage.table().markForDelete();
    3112             :     //
    3113             :     // Add the distance to the object: this is not nice. We should define the
    3114             :     // coordinates properly.
    3115             :     //
    3116           0 :     Record info(imageImage.miscInfo());
    3117           0 :     info.define("distance", distance_p.get("m").getValue());
    3118           0 :     cImageImage.setMiscInfo(info);
    3119             : 
    3120             :     
    3121           0 :     String ftmachine(ftmachine_p);
    3122           0 :     if (!ft_p)
    3123           0 :       createFTMachine();
    3124             :     
    3125             :     os << LogIO::DEBUG1 << "FTMachine is : " << ftmachine 
    3126           0 :        << " (" << ft_p << ")" << LogIO::POST;
    3127             :     
    3128             :     
    3129             :     // Now make the required image
    3130           0 :     Matrix<Float> weight;
    3131           0 :     ft_p->makeImage(seType, *rvi_p, cImageImage, weight);
    3132           0 :     StokesImageUtil::To(imageImage, cImageImage);
    3133             :     //
    3134             :     // Dirty way to set the proper unit to SD image
    3135             :     //
    3136           0 :     String msunit("");
    3137           0 :     String imunit;
    3138           0 :     if ( ms_p->tableDesc().isColumn("DATA") ){
    3139           0 :       msunit = ms_p->columnUnit(MS::DATA);
    3140           0 :       if (msunit == String("")) {
    3141           0 :         ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("DATA"));
    3142           0 :         if (dataColDesc.keywordSet().isDefined("UNIT"))
    3143           0 :           msunit = dataColDesc.keywordSet().asString("UNIT");
    3144           0 :       }
    3145           0 :     } else if ( ms_p->tableDesc().isColumn("FLOAT_DATA")) {
    3146           0 :       msunit = ms_p->columnUnit(MS::FLOAT_DATA);
    3147           0 :       if (msunit == String("")) {
    3148           0 :         ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("FLOAT_DATA"));
    3149           0 :         if (dataColDesc.keywordSet().isDefined("UNIT"))
    3150           0 :           msunit = dataColDesc.keywordSet().asString("UNIT");
    3151           0 :       }
    3152             :     }
    3153           0 :     msunit.upcase();
    3154           0 :     if (msunit == String("K"))
    3155           0 :       imunit = "K";
    3156             :     else
    3157           0 :       imunit = "Jy/beam";
    3158           0 :     imageImage.setUnits(Unit(imunit));
    3159           0 :     cImageImage.setUnits(Unit(imunit));
    3160             : //     imageImage.setUnits(Unit("Jy/beam"));
    3161             : //     cImageImage.setUnits(Unit("Jy/beam"));
    3162             : 
    3163           0 :     if(keepImage) {
    3164           0 :       imageImage.table().unmarkForDelete();
    3165             :     }
    3166           0 :     if(keepComplexImage) {
    3167           0 :       cImageImage.table().unmarkForDelete();
    3168             :     }
    3169           0 :     this->unlock();
    3170           0 :     return true;
    3171           0 :   } catch (AipsError x) {
    3172           0 :     this->unlock();
    3173           0 :     throw(x);
    3174             :     return false;
    3175           0 :   }
    3176           0 :   catch(...){
    3177             :     //Unknown exception...
    3178           0 :     throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    3179           0 :   }
    3180             :   this->unlock();
    3181             : 
    3182             :   return true;
    3183           0 : }  
    3184             : 
    3185             : // Restore: at least one model must be supplied
    3186           0 : Bool Imager::restore(const Vector<String>& model,
    3187             :                      const String& complist,
    3188             :                      const Vector<String>& image,
    3189             :                      const Vector<String>& residual)
    3190             : {
    3191             :   
    3192           0 :   if(!valid()) return false;
    3193           0 :   LogIO os(LogOrigin("imager", "restore()", WHERE));
    3194             :   
    3195           0 :   this->lock();
    3196             :   try {
    3197           0 :     if(!assertDefinedImageParameters()) return false;
    3198             :     
    3199           0 :     if(image.nelements()>model.nelements()) {
    3200           0 :       this->unlock();
    3201             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3202           0 :          << LogIO::EXCEPTION;
    3203           0 :       return false;
    3204             :     }
    3205             :     else {
    3206             :       os << LogIO::NORMAL // Loglevel PROGRESS
    3207           0 :          << "Restoring " << model.nelements() << " models" << LogIO::POST;
    3208             :     }
    3209             : 
    3210             :     ///if the skymodel is already set...no need to get rid of the psf and ftmachine state
    3211             :     //as long as the images match
    3212           0 :     if(!redoSkyModel_p){
    3213           0 :       Bool coordMatch=true; 
    3214           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3215           0 :         CoordinateSystem cs=(sm_p->image(thismodel)).coordinates();
    3216           0 :         coordMatch= coordMatch || checkCoord(cs, model(thismodel));
    3217           0 :       }
    3218           0 :       if(!coordMatch)
    3219           0 :         destroySkyEquation();
    3220             :     }
    3221             :     
    3222           0 :     if(redoSkyModel_p){
    3223           0 :       Vector<String> imageNames(image);
    3224           0 :       if(image.nelements()<model.nelements()) {
    3225           0 :         imageNames.resize(model.nelements());
    3226           0 :         for(Int i=0;i<Int(model.nelements()); ++i) {
    3227           0 :           imageNames(i)="";
    3228             :         }
    3229             :       }
    3230             :       
    3231           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3232           0 :         if(imageNames(thismodel)=="") {
    3233           0 :           imageNames(thismodel)=model(thismodel)+".restored";
    3234             :         }
    3235           0 :         removeTable(imageNames(thismodel));
    3236           0 :         if(imageNames(thismodel)=="") {
    3237           0 :           this->unlock();
    3238             :           os << LogIO::SEVERE << "Illegal name for output image "
    3239           0 :              << imageNames(thismodel) << LogIO::EXCEPTION;
    3240           0 :           return false;
    3241             :         }
    3242           0 :         if(!clone(model(thismodel), imageNames(thismodel))) return false;
    3243             :       }
    3244             :       
    3245           0 :       Vector<String> residualNames(residual);
    3246           0 :       if(residual.nelements()<model.nelements()) {
    3247           0 :         residualNames.resize(model.nelements());
    3248           0 :         for(Int i=0;i<Int(model.nelements());++i) {
    3249           0 :           residualNames(i)="";
    3250             :         }
    3251             :       }
    3252             : 
    3253           0 :       for (Int thismodel=0;thismodel<Int(model.nelements()); ++thismodel) {
    3254           0 :         if(residualNames(thismodel)=="")
    3255           0 :           residualNames(thismodel)=model(thismodel)+".residual";
    3256           0 :         removeTable(residualNames(thismodel));
    3257           0 :         if(residualNames(thismodel)=="") {
    3258           0 :           this->unlock();
    3259             :           os << LogIO::SEVERE << "Illegal name for output residual "
    3260           0 :              << residualNames(thismodel) << LogIO::EXCEPTION;
    3261           0 :           return false;
    3262             :         }
    3263           0 :         if(!clone(model(thismodel), residualNames(thismodel))) return false;
    3264             :       }
    3265             :     
    3266           0 :       if(beamValid_p) {
    3267           0 :         os << LogIO::NORMAL << "Using previous beam fit" << LogIO::POST; // Loglevel INFO
    3268             :       }
    3269             :       else {
    3270             :         os << LogIO::NORMAL // Loglevel INFO
    3271           0 :            << "Calculating PSF using current parameters" << LogIO::POST;
    3272           0 :         String psf;
    3273           0 :         psf=imageNames(0)+".psf";
    3274           0 :         if(!clone(imageNames(0), psf)) return false;
    3275           0 :         Imager::makeimage("psf", psf);
    3276           0 :         fitpsf(psf, beam_p);
    3277           0 :         beamValid_p=true;
    3278           0 :       }
    3279             : 
    3280             :       //      if (!se_p)
    3281           0 :       if(!createSkyEquation(model, complist)) return false;
    3282             :       
    3283           0 :       addResiduals(residualNames);
    3284           0 :     }
    3285           0 :     sm_p->solveResiduals(*se_p);
    3286           0 :     for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3287           0 :       residuals_p[k]->copyData(sm_p->getResidual(k));
    3288             :     }
    3289           0 :     restoreImages(image);
    3290             :     
    3291           0 :     this->unlock();
    3292           0 :     return true;
    3293           0 :   } catch (AipsError x) {
    3294           0 :     this->unlock();
    3295           0 :     throw(x);
    3296             :     return false;
    3297           0 :   } 
    3298             :   this->unlock();
    3299             :   return true;
    3300           0 : }
    3301             : 
    3302           0 : Bool Imager::updateresidual(const Vector<String>& model,
    3303             :                      const String& complist,
    3304             :                      const Vector<String>& image,
    3305             :                      const Vector<String>& residual)
    3306             : {
    3307             :   
    3308           0 :   if(!valid()) return false;
    3309           0 :   LogIO os(LogOrigin("imager", "updateresidual()", WHERE));
    3310             :   
    3311           0 :   this->lock();
    3312             :   try {
    3313           0 :     if(!assertDefinedImageParameters()) return false;
    3314             :     
    3315           0 :     if(image.nelements()>model.nelements()) {
    3316           0 :       this->unlock();
    3317             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3318           0 :          << LogIO::EXCEPTION;
    3319           0 :       return false;
    3320             :     }
    3321             :     else {
    3322             :       os << LogIO::NORMAL // Loglevel PROGRESS
    3323           0 :          << "updating and restoring " << model.nelements() << " models" << LogIO::POST;
    3324             :     }
    3325             : 
    3326           0 :     if(redoSkyModel_p)
    3327           0 :       throw(AipsError("use restore instead of updateresidual"));
    3328           0 :     if(!updateSkyModel(model, complist))
    3329           0 :         throw(AipsError("Could not do an updateresidual please use restore"));      
    3330           0 :     addResiduals(residual);
    3331           0 :     for (Int thismodel=0;thismodel<Int(residuals_p.nelements());++thismodel) {
    3332           0 :       if(!residuals_p[thismodel].null()) 
    3333           0 :         sm_p->addResidual(thismodel, *residuals_p[thismodel]);   
    3334             :     }
    3335           0 :     sm_p->solveResiduals(*se_p);
    3336             :     /*for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3337             :       residuals_p[k]->copyData(sm_p->getResidual(k));
    3338             :     }
    3339             :     */
    3340           0 :     restoreImages(image);
    3341             :     
    3342             : 
    3343           0 :     this->unlock();
    3344           0 :     return true;
    3345           0 :   } catch (AipsError x) {
    3346           0 :     this->unlock();
    3347           0 :     throw(x);
    3348             :     return false;
    3349           0 :   } 
    3350             :   this->unlock();
    3351             :   return true;
    3352           0 : }
    3353             : 
    3354             : // Residual
    3355           0 : Bool Imager::residual(const Vector<String>& model,
    3356             :                       const String& complist,
    3357             :                       const Vector<String>& image)
    3358             : {
    3359             :   
    3360           0 :   if(!valid()) return false;
    3361           0 :   LogIO os(LogOrigin("imager", "residual()", WHERE));
    3362             :   
    3363           0 :   this->lock();
    3364             :   try {
    3365           0 :     if(!assertDefinedImageParameters()) return false;
    3366             :     os << LogIO::NORMAL // Loglevel INFO
    3367           0 :        << "Calculating residual image using full sky equation" << LogIO::POST;
    3368           0 :     Vector<String> theModels=model;
    3369             : 
    3370           0 :     Bool deleteModel=false;
    3371             : 
    3372           0 :     if(model.nelements()==1 && model[0]=="" && complist != "" 
    3373           0 :        && image.nelements()==1){
    3374             : 
    3375             :       //      A component list with no model passed...
    3376           0 :       theModels.resize(1);
    3377           0 :       theModels[0]="Imager_Scratch_model";
    3378           0 :       make(theModels[0]);
    3379           0 :       deleteModel=true;
    3380             :     }
    3381             : 
    3382           0 :     if(image.nelements()>theModels.nelements()) {
    3383           0 :       this->unlock();
    3384             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3385           0 :          << LogIO::EXCEPTION;
    3386           0 :       return false;
    3387             :     }
    3388             :     else {
    3389             :       os << LogIO::NORMAL << "Finding residuals for " << theModels.nelements() // Loglevel INFO
    3390           0 :          << " models" << LogIO::POST;
    3391             :     }
    3392             :     
    3393           0 :     Vector<String> imageNames(image);
    3394           0 :     if(image.nelements()<theModels.nelements()) {
    3395           0 :       imageNames.resize(model.nelements());
    3396           0 :       for(Int i=Int(image.nelements());i<Int(theModels.nelements());++i) {
    3397           0 :         imageNames(i)="";
    3398             :       }
    3399             :     }
    3400             : 
    3401           0 :     for (Int thismodel=0;thismodel<Int(theModels.nelements()); ++thismodel) {
    3402           0 :       if(imageNames(thismodel)=="")
    3403           0 :         imageNames(thismodel)=model(thismodel)+".residual";
    3404           0 :       removeTable(imageNames(thismodel));
    3405           0 :       if(imageNames(thismodel)=="") {
    3406           0 :         this->unlock();
    3407             :         os << LogIO::SEVERE << "Illegal name for output image "
    3408           0 :            << imageNames(thismodel) << LogIO::EXCEPTION;
    3409           0 :         return false;
    3410             :       }
    3411           0 :       if(!clone(theModels(thismodel), imageNames(thismodel))) return false;
    3412             :     }
    3413           0 :     destroySkyEquation();
    3414           0 :     if(!createSkyEquation(theModels, complist)) return false;
    3415             :     
    3416           0 :     addResidualsToSkyEquation(imageNames);
    3417             :     
    3418           0 :     sm_p->solveResiduals(*se_p);
    3419           0 :     destroySkyEquation();
    3420           0 :     if(deleteModel) 
    3421           0 :       removeTable(theModels[0]);
    3422           0 :     this->unlock();
    3423           0 :     return true;
    3424           0 :   } catch (AipsError x) {
    3425           0 :     this->unlock();
    3426           0 :     throw(x);
    3427             :     return false;
    3428           0 :   } 
    3429             :   this->unlock();
    3430             :   return true;
    3431           0 : }
    3432             : 
    3433             : // Residual
    3434           0 : Bool Imager::approximatepsf(const String& psf)
    3435             : {
    3436             :   
    3437           0 :   if(!valid()) return false;
    3438           0 :   LogIO os(LogOrigin("imager", "approximatepsfs()", WHERE));
    3439             :   
    3440           0 :   this->lock();
    3441             :   try {
    3442           0 :     if(!assertDefinedImageParameters()) return false;
    3443             :     os << LogIO::NORMAL // Loglevel INFO
    3444           0 :        << "Calculating approximate PSFs using full sky equation" << LogIO::POST;
    3445             :     
    3446             :  
    3447           0 :     if(psf==""){
    3448           0 :       this->unlock();
    3449             :       os << LogIO::SEVERE << "Illegal name for output psf "
    3450           0 :          << psf << LogIO::EXCEPTION;
    3451           0 :       return false;
    3452             :     } 
    3453           0 :     removeTable(psf);
    3454           0 :     make(psf);
    3455             :     
    3456           0 :     Vector<String>onepsf(1,psf);
    3457             :     // Previous SkyEquation if they exist is not useful
    3458           0 :     destroySkyEquation();
    3459             :     //    if (!se_p)
    3460             :     // As we are not going to make any use of a useful model and to economize 
    3461             :     // temporary image...using the psf itself as model...
    3462             :     // need to change this if you donot destroy the skyequation after you're done.
    3463           0 :     if(!createSkyEquation(onepsf)) return false;
    3464             :     
    3465           0 :     sm_p->makeApproxPSFs(*se_p);
    3466             :     
    3467             : 
    3468           0 :     PagedImage<Float> elpsf(psf);
    3469           0 :     elpsf.copyData(sm_p->PSF(0));
    3470           0 :     ImageBeamSet mbeam;
    3471           0 :     StokesImageUtil::FitGaussianPSF(elpsf, mbeam);
    3472           0 :     LatticeExprNode sumPSF = sum(elpsf);
    3473           0 :     Float volume=sumPSF.getFloat();
    3474           0 :     GaussianBeam elbeam=mbeam(0,0);
    3475             :     os << LogIO::NORMAL << "Approximate PSF  "  << ": size " // Loglevel INFO
    3476             :        << elbeam.getMajor("arcsec") << " by "
    3477             :        << elbeam.getMinor("arcsec") << " (arcsec) at pa "
    3478           0 :        << elbeam.getPA(Unit("deg")) << " (deg)" << endl
    3479           0 :        << "and volume = " << volume << " pixels " << LogIO::POST;
    3480             :     
    3481             :     
    3482           0 :     destroySkyEquation();
    3483           0 :     if(ft_p)
    3484           0 :       delete ft_p;
    3485           0 :     ft_p=0;
    3486             : 
    3487           0 :     this->unlock();
    3488           0 :     return true;
    3489           0 :   } catch (AipsError x) {
    3490           0 :     this->unlock();
    3491           0 :     throw(x);
    3492             :     return false;
    3493           0 :   } 
    3494             :   this->unlock();
    3495             :   return true;
    3496           0 : }
    3497             : 
    3498           0 : Bool Imager::smooth(const Vector<String>& model, 
    3499             :                     const Vector<String>& image, Bool usefit, 
    3500             :                     ImageBeamSet& mbeam,
    3501             :                     Bool normalizeVolume)
    3502             : {
    3503           0 :   if(!valid()) return false;
    3504           0 :   LogIO os(LogOrigin("imager", "smooth()", WHERE));
    3505             :   
    3506           0 :   this->lock();
    3507             :   try {
    3508           0 :     if(!assertDefinedImageParameters()) return false;
    3509             :     
    3510           0 :     os << LogIO::NORMAL << "Smoothing image" << LogIO::POST; // Loglevel PROGRESS
    3511             :     
    3512           0 :     if(model.nelements()>0) {
    3513           0 :       for ( uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
    3514           0 :         if(model(thismodel)=="") {
    3515           0 :           this->unlock();
    3516           0 :           os << LogIO::SEVERE << "Need a name for model " << thismodel << LogIO::POST;
    3517           0 :           return false;
    3518             :         }
    3519             :       }
    3520             :     }
    3521             :     
    3522           0 :     if(image.nelements()>model.nelements()) {
    3523           0 :       this->unlock();
    3524           0 :       os << LogIO::SEVERE << "Cannot specify more output images than models" << LogIO::POST;
    3525           0 :       return false;
    3526             :     }
    3527             :     
    3528           0 :     if(usefit) {
    3529           0 :       if(beamValid_p) {
    3530           0 :         os << LogIO::NORMAL << "Using previous beam" << LogIO::POST; // Loglevel INFO
    3531           0 :         mbeam = beam_p;
    3532             : 
    3533             :       }
    3534             :       else {
    3535             :         os << LogIO::NORMAL // Loglevel INFO
    3536           0 :            << "Calculating PSF using current parameters" << LogIO::POST;
    3537           0 :         String psf;
    3538           0 :         psf=model(0)+".psf";
    3539           0 :         if(!clone(model(0), psf)) return false;
    3540           0 :         Imager::makeimage("psf", psf);
    3541           0 :         fitpsf(psf, mbeam);
    3542           0 :         beam_p = mbeam;
    3543           0 :         beamValid_p=true;
    3544           0 :       }
    3545             :     }
    3546             :     
    3547             :     // Smooth all the images
    3548           0 :     Vector<String> imageNames(image);
    3549           0 :     for (Int thismodel=0;thismodel<Int(image.nelements()); ++thismodel) {
    3550           0 :       if(imageNames(thismodel)=="") {
    3551           0 :         imageNames(thismodel)=model(thismodel)+".smoothed";
    3552             :       }
    3553           0 :       PagedImage<Float> modelImage(model(thismodel));
    3554           0 :       PagedImage<Float> imageImage(TiledShape(modelImage.shape(), 
    3555           0 :                                               modelImage.niceCursorShape()),
    3556             :                                    modelImage.coordinates(),
    3557           0 :                                    imageNames(thismodel));
    3558           0 :       imageImage.table().markForDelete();
    3559           0 :       imageImage.copyData(modelImage);
    3560           0 :       StokesImageUtil::Convolve(imageImage, mbeam,
    3561             :                                 normalizeVolume);
    3562             :       
    3563           0 :       ImageInfo ii = imageImage.imageInfo();
    3564             :       //ii.setRestoringBeam(mbeam);
    3565           0 :       ii.setBeams(mbeam);
    3566           0 :       imageImage.setImageInfo(ii);
    3567           0 :       imageImage.setUnits(Unit("Jy/beam"));
    3568           0 :       imageImage.table().unmarkForDelete();
    3569           0 :     }
    3570             :     
    3571           0 :     this->unlock();
    3572           0 :     return true;
    3573           0 :   } catch (AipsError x) {
    3574           0 :     this->unlock();
    3575           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    3576           0 :     return false;
    3577           0 :   } 
    3578             :   this->unlock();
    3579             :   return true;
    3580           0 : }
    3581             : 
    3582             : // Clean algorithm
    3583           0 : Record Imager::clean(const String& algorithm,
    3584             :                    const Int niter, 
    3585             :                    const Float gain,
    3586             :                    const Quantity& threshold, 
    3587             :                    const Bool /*displayProgress*/,
    3588             :                    const Vector<String>& model, const Vector<Bool>& fixed,
    3589             :                    const String& complist,
    3590             :                    const Vector<String>& mask,
    3591             :                    const Vector<String>& image,
    3592             :                    const Vector<String>& residual,
    3593             :                    const Vector<String>& psfnames,
    3594             :                    const Bool firstrun)
    3595             : {
    3596             :   ////////////////////////
    3597             :   //Double wtime0=omp_get_wtime();
    3598             :   //////////////////////
    3599             : 
    3600             : 
    3601           0 :   Record retval;
    3602           0 :   Bool converged=true;
    3603           0 :   retval.define("converged", false);
    3604           0 :   retval.define("iterations", Int(0));
    3605           0 :   retval.define("maxresidual", Float(0.0));
    3606             :   
    3607             : 
    3608             : 
    3609             :   //ROVisibilityIterator::AsyncEnabler enabler (rvi_p);
    3610             : 
    3611           0 :   if(!valid())
    3612             :     {
    3613           0 :       return retval;
    3614             :     }
    3615           0 :   logSink_p.clearLocally();
    3616           0 :   LogIO os(LogOrigin("imager", "clean()"),logSink_p);
    3617             :   
    3618           0 :   this->lock();
    3619             :   try {
    3620           0 :     if(!assertDefinedImageParameters()) 
    3621             :       {
    3622           0 :         return retval;
    3623             :       }
    3624             :     
    3625           0 :     Int nmodels=model.nelements();
    3626             :     os << LogIO::DEBUG1
    3627           0 :        << "Found " << nmodels << " specified model images" << LogIO::POST;
    3628             :     
    3629           0 :     if(model.nelements()>0) {
    3630           0 :       for (uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
    3631           0 :         if(model(thismodel)=="") {
    3632           0 :           this->unlock();
    3633             :           os << LogIO::SEVERE << "Need a name for model "
    3634           0 :              << thismodel << LogIO::POST;
    3635             : 
    3636           0 :           return retval;
    3637             :         }
    3638             :       }
    3639             :     }
    3640             :     
    3641           0 :     Vector<String> modelNames=model;
    3642             :     // Make first image with the required shape and coordinates only if
    3643             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    3644           0 :     if(modelNames(0)=="") modelNames(0)=imageName()+".clean";
    3645           0 :     if(!Table::isWritable(modelNames(0))) {
    3646           0 :       make(modelNames(0));
    3647             :     }
    3648             :     else{
    3649           0 :       Bool coordMatch=false;
    3650           0 :       CoordinateSystem coordsys;
    3651             :       //imagecoordinates(coordsys, firstrun);
    3652           0 :       imagecoordinates2(coordsys, firstrun);
    3653           0 :       for (uInt modelNum=0; modelNum < modelNames.nelements(); ++modelNum){
    3654           0 :         if(Table::isWritable(modelNames(modelNum))){
    3655           0 :           coordMatch= coordMatch || 
    3656           0 :             (this->checkCoord(coordsys, modelNames(modelNum)));
    3657             :                                      
    3658             :         }
    3659             :           
    3660             :       } 
    3661           0 :       if(!coordMatch){
    3662             :         os << LogIO::WARN << "The model(s) image exists on disk " 
    3663           0 :            << LogIO::POST;
    3664             :         os << LogIO::WARN 
    3665             :            << "The coordinates or shape were found not to match the one "
    3666             :            << "defined by setimage " 
    3667           0 :            << LogIO::POST;
    3668             : 
    3669             :         os << LogIO::WARN 
    3670             :            << "Cleaning process is going to ignore setimage parameters and "
    3671             :            << "continue cleaning from from model on disk " 
    3672           0 :            << LogIO::POST;
    3673             :       }
    3674           0 :     }
    3675           0 :     Vector<String> maskNames(nmodels);
    3676           0 :     if(Int(mask.nelements())==nmodels) {
    3677           0 :       maskNames=mask;
    3678             :     }
    3679             :     else {
    3680             :       /* For msmfs, the one input mask PER FIELD must be replicated for all 
    3681             :          Taylor-planes PER FIELD */
    3682           0 :       if(algorithm=="msmfs" && (Int(mask.nelements())>=(nmodels/ntaylor_p)) ){
    3683           0 :        for(Int tay=0;tay<nmodels;tay++)
    3684             :          {
    3685           0 :            maskNames[tay] = mask[ tay%(nmodels/ntaylor_p)  ];
    3686             :          }
    3687             :       }
    3688             :       else {
    3689             :          /* No mask */
    3690           0 :          maskNames="";
    3691             :       }
    3692             :     }
    3693             : 
    3694           0 :     if(sm_p){
    3695           0 :       if( sm_p->getAlgorithm() != "clean") destroySkyEquation();
    3696           0 :       if(images_p.nelements() != uInt(nmodels)){
    3697           0 :         destroySkyEquation();
    3698             :       }
    3699             :       else{
    3700           0 :         for (Int k=0; k < nmodels ; ++k){
    3701           0 :           if(!(images_p[k]->name().contains(modelNames[k]))) destroySkyEquation();
    3702             :         }
    3703             :       }
    3704             :     }
    3705             : 
    3706             :     // Always fill in the residual images
    3707           0 :     Vector<String> residualNames(nmodels);
    3708           0 :     if(Int(residual.nelements())==nmodels) {
    3709           0 :         residualNames=residual;
    3710             :     }
    3711             :     else {
    3712           0 :       residualNames="";       
    3713             :     }
    3714           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3715           0 :       if(residualNames[thismodel]=="")
    3716           0 :         residualNames(thismodel)=modelNames(thismodel)+".residual";
    3717             :     }
    3718           0 :     if(redoSkyModel_p){
    3719           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3720           0 :         removeTable(residualNames(thismodel));
    3721           0 :         if(!clone(model(thismodel), residualNames(thismodel)))
    3722             :           {
    3723           0 :             return retval;
    3724             :           }
    3725             :       }
    3726             :     }
    3727             : 
    3728             :     
    3729             :     // Make an ImageSkyModel with the specified polarization representation
    3730             :     // (i.e. circular or linear)
    3731             : 
    3732           0 :     if( redoSkyModel_p || !sm_p){
    3733           0 :       if(sm_p) delete sm_p;
    3734           0 :       if(algorithm.substr(0,5)=="clark") {
    3735             :         // Support serial and parallel specializations
    3736           0 :         setClarkCleanImageSkyModel();
    3737           0 :         if(algorithm.contains("stokes"))
    3738           0 :           sm_p->setJointStokesClean(false);
    3739             :         os << LogIO::NORMAL // Loglevel INFO.        Stating the algo is more for
    3740           0 :            << "Using Clark clean" << LogIO::POST; // the logfile than the window.
    3741             :       }
    3742           0 :       else if (algorithm=="hogbom") {
    3743           0 :         sm_p = new HogbomCleanImageSkyModel();
    3744             :         os << LogIO::NORMAL // Loglevel INFO.         Stating the algo is more for
    3745           0 :            << "Using Hogbom clean" << LogIO::POST; // the logfile than the window.
    3746             :       }
    3747           0 :       else if (algorithm=="wfhogbom") {
    3748           0 :         setWFCleanImageSkyModel();
    3749           0 :         sm_p->setSubAlgorithm("hogbom");
    3750           0 :         doMultiFields_p = true;
    3751           0 :         doMultiFields_p = false;
    3752             :         os << LogIO::NORMAL // Loglevel INFO
    3753           0 :            << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
    3754             :       }
    3755           0 :       else if (algorithm=="multiscale") {
    3756           0 :         if (!scaleInfoValid_p) {
    3757           0 :           this->unlock();
    3758           0 :           os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
    3759           0 :           return retval;
    3760             :         }
    3761           0 :         if (scaleMethod_p=="uservector") {    
    3762           0 :           sm_p = new MSCleanImageSkyModel(userScaleSizes_p, stoplargenegatives_p, 
    3763           0 :                                             stoppointmode_p, smallScaleBias_p);
    3764             :         } else {
    3765           0 :           sm_p = new MSCleanImageSkyModel(nscales_p, stoplargenegatives_p, 
    3766           0 :                                             stoppointmode_p, smallScaleBias_p);
    3767             :         }
    3768           0 :         if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    3769           0 :           sm_p->setSubAlgorithm("full");
    3770             :         os << LogIO::NORMAL // Loglevel INFO.             Stating the algo is more for
    3771           0 :            << "Using multiscale clean" << LogIO::POST; // the logfile than the window.
    3772             :       }
    3773           0 :       else if (algorithm.substr(0,7)=="mfclark" || algorithm=="mf") {
    3774           0 :         sm_p = new MFCleanImageSkyModel();
    3775           0 :         sm_p->setSubAlgorithm("clark");
    3776           0 :         if(algorithm.contains("stokes"))
    3777           0 :           sm_p->setJointStokesClean(false);
    3778             : 
    3779           0 :         doMultiFields_p = true;
    3780           0 :         os << LogIO::NORMAL << "Using multifield Clark clean" << LogIO::POST; // Loglevel INFO
    3781             :       }
    3782           0 :       else if (algorithm=="csclean" || algorithm=="cs") {
    3783           0 :         sm_p = new CSCleanImageSkyModel();
    3784           0 :         doMultiFields_p = true;
    3785           0 :         os << LogIO::NORMAL << "Using Cotton-Schwab Clean" << LogIO::POST; // Loglevel INFO
    3786             :       }
    3787           0 :       else if (algorithm=="csfast" || algorithm=="csf") {
    3788           0 :         sm_p = new CSCleanImageSkyModel();
    3789           0 :         sm_p->setSubAlgorithm("fast");
    3790           0 :         doMultiFields_p = true;
    3791             :         os << LogIO::NORMAL // Loglevel INFO
    3792           0 :            << "Using Cotton-Schwab Clean (optimized)" << LogIO::POST;
    3793             :       }
    3794           0 :       else if (algorithm=="mfhogbom") {
    3795           0 :         sm_p = new MFCleanImageSkyModel();
    3796           0 :         sm_p->setSubAlgorithm("hogbom");
    3797           0 :         doMultiFields_p = true;
    3798           0 :         os << LogIO::NORMAL << "Using multifield Hogbom clean" << LogIO::POST; // Loglevel INFO
    3799             :       }
    3800           0 :       else if (algorithm=="mfmultiscale") {
    3801           0 :         if (!scaleInfoValid_p) {
    3802           0 :           this->unlock();
    3803           0 :           os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
    3804           0 :           return retval;
    3805             :         }
    3806           0 :         if (scaleMethod_p=="uservector") {
    3807           0 :           sm_p = new MFMSCleanImageSkyModel(userScaleSizes_p, 
    3808             :                                             stoplargenegatives_p, 
    3809             :                                             stoppointmode_p,
    3810           0 :                                             smallScaleBias_p);
    3811             :         } else {
    3812           0 :           sm_p = new MFMSCleanImageSkyModel(nscales_p, 
    3813             :                                             stoplargenegatives_p, 
    3814             :                                             stoppointmode_p,
    3815           0 :                                             smallScaleBias_p);
    3816             :         }
    3817             :         //      if(ftmachine_p=="mosaic"|| ftmachine_p=="wproject")
    3818             :         // For some reason  this does not seem to work without full
    3819           0 :         sm_p->setSubAlgorithm("full");
    3820             : 
    3821           0 :         doMultiFields_p = true;
    3822             :         os << LogIO::NORMAL << "Using multifield multi-scale clean"  // Loglevel INFO
    3823           0 :            << LogIO::POST;
    3824             :       } 
    3825           0 :       else if (algorithm=="wfclark" || algorithm=="wf") {
    3826             :         // Support serial and parallel specializations
    3827           0 :         setWFCleanImageSkyModel();
    3828           0 :         sm_p->setSubAlgorithm("clark");
    3829           0 :         doMultiFields_p = false;
    3830             :         os << LogIO::NORMAL // Loglevel INFO
    3831           0 :            << "Using wide-field algorithm with Clark clean" << LogIO::POST;
    3832             :       }
    3833           0 :       else if (algorithm=="wfhogbom") {
    3834             :         // Support serial and parallel specializations
    3835           0 :         setWFCleanImageSkyModel();
    3836           0 :         sm_p->setSubAlgorithm("hogbom");
    3837           0 :         doMultiFields_p = false;
    3838             :         os << LogIO::NORMAL // Loglevel INFO
    3839           0 :            << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
    3840             :       }
    3841           0 :       else if (algorithm=="msmfs") {
    3842           0 :         doMultiFields_p = false;
    3843           0 :         doWideBand_p = true;
    3844             : 
    3845             :         // check for wrong ftmachine specs.
    3846           0 :         if ( (ftmachine_p != "ft") && (ftmachine_p != "wproject") && 
    3847           0 :              (ftmachine_p != "wbawp") && (ftmachine_p != "nift") &&
    3848           0 :              (ftmachine_p != "mosaic") && (ftmachine_p != "awproject") ) {
    3849             :           os << LogIO::SEVERE
    3850             :              << "Multi-scale Multi-frequency Clean currently works only with ft, wproject and mosaic (and wbawp,nift,awproject)"
    3851           0 :              << LogIO::POST;
    3852           0 :           return retval;
    3853             :         }
    3854             :         
    3855           0 :         useNewMTFT_p=false;
    3856           0 :         if( ftmachine_p == "awproject" ) { useNewMTFT_p=true; }
    3857             : 
    3858             : 
    3859           0 :         if (!scaleInfoValid_p) {
    3860           0 :           this->unlock();
    3861           0 :           os << LogIO::WARN << "Scales not yet set, using power law" << LogIO::POST;
    3862           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p, 1 ,reffreq_p);
    3863             :         }
    3864           0 :         if (scaleMethod_p=="uservector") {    
    3865           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p,userScaleSizes_p,reffreq_p);
    3866             :         } else {
    3867           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p,nscales_p,reffreq_p);
    3868             :         }
    3869             :         os << LogIO::NORMAL // Loglevel INFO
    3870           0 :            << "Using multi frequency synthesis algorithm" << LogIO::POST;
    3871           0 :         ((WBCleanImageSkyModel*)sm_p)->imageNames = Vector<String>(image);
    3872             :         /* Check masks. Should be only one per field. Duplicate the name ntaylor_p times 
    3873             :            Note : To store taylor-coefficients, msmfs uses the same data structure as for
    3874             :                   multi-field imaging. In the case of multifield and msmfs, the list of 
    3875             :                   images is nested and follows a field-major ordering.
    3876             :                   All taylor-coeffs for a single field should have the same mask (for now).
    3877             :            For now, since only single-field is allowed for msmfs, we have the following.*/
    3878             :       }
    3879             :       else {
    3880           0 :         this->unlock();
    3881             :         os << LogIO::SEVERE << "Unknown algorithm: " << algorithm 
    3882           0 :            << LogIO::POST;
    3883             :         
    3884           0 :         return retval;
    3885             :       }
    3886             :    
    3887           0 :       AlwaysAssert(sm_p, AipsError);
    3888           0 :       sm_p->setAlgorithm("clean");
    3889             : 
    3890             :       //    if (!se_p)
    3891           0 :       if(!createSkyEquation(modelNames, fixed, maskNames, complist)) 
    3892             :         {
    3893             :         
    3894           0 :           return retval;
    3895             :         }
    3896           0 :       os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
    3897           0 :     }
    3898             :     else{
    3899             :       //adding or modifying mask associated with skyModel
    3900           0 :       addMasksToSkyEquation(maskNames,fixed);
    3901             :     }
    3902             :     //No need to add residuals will let sm_p use tmpimage ones and we'll copy them in restore 
    3903           0 :     if(!addResiduals(residualNames))
    3904           0 :        throw(AipsError("Problem in attaching to residual images")); 
    3905             :     // The old plot that showed how much flux was being incorporated in each
    3906             :     // scale.   No longer available, slated for removal.
    3907             :     // if (displayProgress) {
    3908             :     //   sm_p->setDisplayProgress(true);
    3909             :     //   sm_p->setPGPlotter( getPGPlotter() );
    3910             :     // }
    3911             : 
    3912             : 
    3913             : 
    3914           0 :     sm_p->setGain(gain);
    3915           0 :     sm_p->setNumberIterations(niter);
    3916           0 :     sm_p->setThreshold(threshold.get("Jy").getValue());
    3917           0 :     sm_p->setCycleFactor(cyclefactor_p);
    3918           0 :     sm_p->setCycleSpeedup(cyclespeedup_p);
    3919           0 :     sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p);
    3920             :     {
    3921           0 :       ostringstream oos;
    3922           0 :       oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
    3923           0 :           << threshold;
    3924           0 :       os << LogIO::NORMAL << String(oos) << LogIO::POST; // More for the
    3925             :                                                          // logfile than the
    3926             :                                                          // log window.
    3927           0 :     }
    3928             : 
    3929             :     os << LogIO::NORMAL << (firstrun ? "Start" : "Continu")
    3930           0 :        << "ing deconvolution" << LogIO::POST; // Loglevel PROGRESS
    3931           0 :     if(se_p->solveSkyModel()) {
    3932             :       os << LogIO::NORMAL
    3933             :          << (niter == 0 ? "Image OK" : "Successfully deconvolved image")
    3934           0 :          << LogIO::POST; // Loglevel PROGRESS
    3935             :     }
    3936             :     else {
    3937           0 :       converged=false;
    3938           0 :       os << LogIO::NORMAL << "Threshhold not reached yet." << LogIO::POST; // Loglevel PROGRESS
    3939             :     }
    3940             :     
    3941             : 
    3942           0 :     printbeam(sm_p, os, firstrun);
    3943             :     
    3944           0 :     if(((algorithm.substr(0,5)=="clark") || algorithm=="hogbom" ||
    3945           0 :         algorithm=="multiscale") && (niter != 0))
    3946             :       //write the model visibility to ms for now 
    3947           0 :       sm_p->solveResiduals(*se_p, true);
    3948             :     
    3949           0 :     for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3950           0 :       (residuals_p[k])->copyData(sm_p->getResidual(k));
    3951             :     }
    3952             :     /////////////
    3953             : 
    3954             :     //cerr << "Time taken " << omp_get_wtime()-wtime0 << endl;
    3955             :     ////////////
    3956           0 :     retval.define("maxresidual", (sm_p->threshold()));
    3957           0 :     retval.define("iterations", (sm_p->numberIterations()));
    3958           0 :     retval.define("converged", converged);
    3959           0 :     savePSF(psfnames);
    3960           0 :     redoSkyModel_p=false;
    3961           0 :     writeFluxScales(fluxscale_p);
    3962             :     // restoreImages(image); // Moved to iClean so that it happens only once.
    3963             :     
    3964             :     
    3965           0 :     this->unlock();
    3966             : 
    3967           0 :     return retval;
    3968           0 :   }
    3969           0 :   catch (PSFZero&  x)
    3970             :     {
    3971             :       //os << LogIO::WARN << x.what() << LogIO::POST;
    3972           0 :       savePSF(psfnames);
    3973           0 :       this->unlock();
    3974           0 :       throw(AipsError(String("PSFZero  ")+ x.getMesg() + String(" : Please check that the required data exists and is not flagged.")));
    3975             :       return retval;
    3976           0 :     }  
    3977           0 :   catch (exception &x) { 
    3978           0 :     this->unlock();
    3979           0 :     destroySkyEquation();
    3980           0 :     throw(AipsError(x.what()));
    3981             : 
    3982             :     return retval;
    3983           0 :   } 
    3984             : 
    3985           0 :   catch(...){
    3986           0 :     this->unlock();
    3987           0 :     destroySkyEquation();
    3988             :     //Unknown exception...
    3989           0 :     throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    3990           0 :   }
    3991             :   this->unlock();
    3992             : 
    3993             :   os << LogIO::NORMAL << "Exiting Imager::clean" << LogIO::POST; // Loglevel PROGRESS
    3994             :   return retval;
    3995           0 : }
    3996             : 
    3997             : // Mem algorithm
    3998           0 : Bool Imager::mem(const String& algorithm,
    3999             :                  const Int niter, 
    4000             :                  const Quantity& sigma, 
    4001             :                  const Quantity& targetFlux,
    4002             :                  const Bool constrainFlux,
    4003             :                  const Bool displayProgress, 
    4004             :                  const Vector<String>& model, 
    4005             :                  const Vector<Bool>& fixed,
    4006             :                  const String& complist,
    4007             :                  const Vector<String>& prior,
    4008             :                  const Vector<String>& mask,
    4009             :                  const Vector<String>& image,
    4010             :                  const Vector<String>& residual)
    4011             : {
    4012           0 :    if(!valid())
    4013             :     {
    4014           0 :       return false;
    4015             :     }
    4016           0 :    logSink_p.clearLocally();
    4017           0 :    LogIO os(LogOrigin("imager", "mem()"), logSink_p);
    4018             :   
    4019           0 :   this->lock();
    4020             :   try {
    4021           0 :     if(!assertDefinedImageParameters()) 
    4022             :       {
    4023           0 :         return false;
    4024             :       }
    4025           0 :     os << LogIO::NORMAL << "Deconvolving images with MEM" << LogIO::POST; // Loglevel PROGRESS
    4026             :     
    4027           0 :     Int nmodels=model.nelements();
    4028             :     os << LogIO::NORMAL  // Loglevel INFO
    4029           0 :        << "Found " << nmodels << " specified model images" << LogIO::POST;
    4030             :     
    4031           0 :     if(model.nelements()>0) {
    4032           0 :       for (uInt thismodel=0;thismodel<model.nelements();++thismodel) {
    4033           0 :         if(model(thismodel)=="") {
    4034           0 :           this->unlock();
    4035             :           os << LogIO::SEVERE << "Need a name for model "
    4036           0 :              << thismodel << LogIO::POST;
    4037           0 :           return false;
    4038             :         }
    4039             :       }
    4040             :     }
    4041             :     
    4042           0 :     Vector<String> modelNames=model;
    4043             :     // Make first image with the required shape and coordinates only if
    4044             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    4045           0 :     if(modelNames(0)=="") modelNames(0)=imageName()+".mem";
    4046           0 :     if(!Table::isWritable(modelNames(0))) {
    4047           0 :       make(modelNames(0));
    4048             :     }
    4049             :     
    4050           0 :     Vector<String> maskNames(nmodels);
    4051           0 :     if(Int(mask.nelements())==nmodels) {
    4052           0 :       maskNames=mask;
    4053           0 :       for(Int k=0; k < nmodels; ++k){
    4054           0 :         if(mask(k)!=""&& !Table::isReadable(mask(k))) {
    4055             :           os << LogIO::WARN 
    4056             :              << "Mask" << mask(k) 
    4057             :              << " is unreadable; ignoring masks altogether " 
    4058           0 :              << LogIO::POST;
    4059           0 :           maskNames.resize(1);
    4060           0 :           maskNames(0)="";
    4061             :         }
    4062             :       }
    4063             :     }
    4064             :     else {
    4065           0 :       maskNames.resize(1);
    4066           0 :       maskNames(0)="";
    4067             :     }
    4068             :     
    4069             :     // Always fill in the residual images
    4070           0 :     Vector<String> residualNames(nmodels);
    4071           0 :     if(Int(residual.nelements())==nmodels) {
    4072           0 :       residualNames=residual;
    4073             :     }
    4074             :     else {
    4075           0 :       residualNames="";
    4076             :     }
    4077           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4078           0 :       if(residualNames(thismodel)=="") {
    4079           0 :         residualNames(thismodel)=modelNames(thismodel)+".residual";
    4080             :       }
    4081           0 :       removeTable(residualNames(thismodel));
    4082           0 :       if(!clone(model(thismodel), residualNames(thismodel)))
    4083             :         {
    4084           0 :           return false;
    4085             :         }
    4086             :     }
    4087             :     
    4088             :     // Make an ImageSkyModel with the specified polarization representation
    4089             :     // (i.e. circular or linear)
    4090           0 :     if(algorithm=="entropy") {
    4091           0 :       sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
    4092           0 :                                     targetFlux.get("Jy").getValue(),
    4093             :                                     constrainFlux,
    4094             :                                     prior,
    4095           0 :                                     algorithm);
    4096             :       os << LogIO::NORMAL // Loglevel INFO
    4097           0 :          << "Using single-field algorithm with Maximum Entropy" << LogIO::POST;
    4098           0 :       if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4099           0 :         sm_p->setSubAlgorithm("full");
    4100             :     }
    4101           0 :     else if (algorithm=="emptiness") {
    4102           0 :       sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
    4103           0 :                                     targetFlux.get("Jy").getValue(),
    4104             :                                     constrainFlux,
    4105             :                                     prior,
    4106           0 :                                     algorithm);
    4107             :       os << LogIO::NORMAL // Loglevel INFO
    4108           0 :          << "Using single-field algorithm with Maximum Emptiness" << LogIO::POST;
    4109           0 :       if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4110           0 :         sm_p->setSubAlgorithm("full");
    4111             :     }
    4112           0 :     else if (algorithm=="mfentropy") {
    4113           0 :       sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
    4114           0 :                                       targetFlux.get("Jy").getValue(),
    4115             :                                       constrainFlux,
    4116             :                                       prior,
    4117           0 :                                       algorithm);
    4118           0 :       doMultiFields_p = true;
    4119           0 :       os << LogIO::NORMAL << "Using Maximum Entropy" << LogIO::POST; // Loglevel INFO
    4120             :       //   if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4121           0 :       sm_p->setSubAlgorithm("full");
    4122           0 :     } else if (algorithm=="mfemptiness") {
    4123           0 :       sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
    4124           0 :                                       targetFlux.get("Jy").getValue(),
    4125             :                                       constrainFlux,
    4126             :                                       prior,
    4127           0 :                                       algorithm);
    4128           0 :       doMultiFields_p = true;
    4129           0 :       os << LogIO::NORMAL << "Using Maximum Emptiness" << LogIO::POST; // Loglevel INFO
    4130             :       // if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4131           0 :       sm_p->setSubAlgorithm("full");
    4132             :     } else {
    4133           0 :       this->unlock();
    4134           0 :       os << LogIO::SEVERE << "Unknown algorithm: " << algorithm << LogIO::POST;
    4135           0 :       return false;
    4136             :     }
    4137           0 :     AlwaysAssert(sm_p, AipsError);
    4138           0 :     sm_p->setAlgorithm("mem");
    4139           0 :     if (displayProgress) {
    4140           0 :       sm_p->setDisplayProgress(true);
    4141             :     }
    4142           0 :     sm_p->setNumberIterations(niter);
    4143           0 :     sm_p->setCycleFactor(cyclefactor_p);   // used by mf algs
    4144           0 :     sm_p->setCycleSpeedup(cyclespeedup_p); // used by mf algs
    4145           0 :     sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p); // used by mf algs
    4146             : 
    4147             :     {
    4148           0 :       ostringstream oos;
    4149           0 :       oos << "MEM algorithm = " <<algorithm<<", Niter = "<<niter<<", Sigma = "
    4150           0 :           <<sigma << ", Target Flux = " << targetFlux;
    4151           0 :       os << LogIO::DEBUG1 << String(oos) << LogIO::POST;
    4152           0 :     }
    4153             :  
    4154             :     //    if (!se_p)
    4155           0 :     if(!createSkyEquation(modelNames, fixed, maskNames, complist)) 
    4156             :       {
    4157           0 :         return false;
    4158             :       }
    4159           0 :     os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
    4160             :     
    4161           0 :     addResidualsToSkyEquation(residualNames);
    4162             : 
    4163           0 :     os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4164           0 :     if(se_p->solveSkyModel()) {
    4165           0 :       os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
    4166             :     }
    4167             :     else {
    4168           0 :       os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
    4169             :     }
    4170             : 
    4171             :     // Get the PSF fit while we are here
    4172           0 :     if(!beamValid_p){
    4173           0 :       ImageBeamSet beam=sm_p->beam(0);
    4174           0 :       if(beam.nelements() > 0){
    4175             :         /*beam_p.setMajorMinor(
    4176             :                         Quantity(abs(beam(0)), "arcsec"), Quantity(abs(beam(1)), "arcsec")
    4177             :                 );
    4178             :           beam_p.setPA(Quantity(beam(2), "deg"));
    4179             :         */
    4180           0 :         beam_p=beam;
    4181           0 :         beamValid_p=true;
    4182             :       }
    4183           0 :     }
    4184           0 :     if(algorithm=="entropy" || algorithm=="emptiness" )
    4185           0 :       sm_p->solveResiduals(*se_p, true);
    4186           0 :     writeFluxScales(fluxscale_p); 
    4187           0 :     restoreImages(image);
    4188           0 :     destroySkyEquation();  
    4189           0 :     this->writeHistory(os);
    4190             :     try{
    4191             :       { // write data processing history into image logtable
    4192           0 :         LoggerHolder imagelog (false);
    4193           0 :         LogSink& sink = imagelog.sink();
    4194           0 :         LogOrigin lor( String("imager"), String("mem()") );
    4195           0 :         LogMessage msg(lor);
    4196           0 :         sink.postLocally(msg);
    4197           0 :         MSHistoryColumns msHis(ms_p->history());
    4198           0 :         transferHistory(imagelog, msHis);
    4199           0 :         for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4200             :           PagedImage<Float> restoredImage(image(thismodel),
    4201           0 :                                           TableLock(TableLock::UserLocking));
    4202           0 :           LoggerHolder& log = restoredImage.logger();
    4203           0 :           log.append(imagelog);
    4204           0 :           log.flush();
    4205           0 :         }
    4206           0 :       }
    4207             :     }
    4208           0 :     catch(exception& x){
    4209             :       
    4210           0 :       os << LogIO::WARN << "Caught exception: " << x.what()
    4211           0 :          << LogIO::POST;
    4212             :       os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
    4213           0 :          <<LogIO::POST; 
    4214             :       //continue and wrap up this function as normal
    4215             :       
    4216           0 :     }
    4217           0 :     catch(...){
    4218             :       //Unknown exception...
    4219           0 :       throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    4220           0 :     }
    4221             :     
    4222           0 :     this->unlock();
    4223             : 
    4224           0 :     return true;
    4225           0 :   } catch (exception& x) {
    4226           0 :     this->unlock();
    4227           0 :     throw(AipsError(x.what()));
    4228             : 
    4229             :     return false;
    4230           0 :   } 
    4231             :   this->unlock();
    4232             :   return true;
    4233             : 
    4234           0 : }
    4235             : 
    4236             :     
    4237             : // NNLS algorithm
    4238           0 : Bool Imager::nnls(const String&,  const Int niter, const Float tolerance, 
    4239             :                   const Vector<String>& model, const Vector<Bool>& fixed,
    4240             :                   const String& complist,
    4241             :                   const Vector<String>& fluxMask,
    4242             :                   const Vector<String>& dataMask,
    4243             :                   const Vector<String>& residual,
    4244             :                   const Vector<String>& image)
    4245             : {
    4246           0 :   if(!valid()) return false;
    4247           0 :   LogIO os(LogOrigin("imager", "nnls()", WHERE));
    4248             :   
    4249           0 :   this->lock();
    4250             :   try {
    4251           0 :     if(!assertDefinedImageParameters()) return false;
    4252             :     
    4253           0 :     os << LogIO::NORMAL << "Performing NNLS deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4254             :     
    4255           0 :     if(niter<0) {
    4256           0 :       this->unlock();
    4257           0 :       os << LogIO::SEVERE << "Number of iterations must be positive" << LogIO::POST;
    4258           0 :       return false;
    4259             :     }
    4260           0 :     if(tolerance<0.0) {
    4261           0 :       this->unlock();
    4262           0 :       os << LogIO::SEVERE << LogIO::SEVERE << "Tolerance must be positive" << LogIO::POST;
    4263           0 :       return false;
    4264             :     }
    4265             :     
    4266             :     // Add the images to the ImageSkyModel
    4267           0 :     Int nmodels=model.nelements();
    4268           0 :     if(nmodels>1) os<< "Can only process one model" << LogIO::POST;
    4269             :     
    4270           0 :     if(model(0)=="") {
    4271           0 :       this->unlock();
    4272           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    4273           0 :       return false;
    4274             :     }
    4275             :     
    4276           0 :     if(!Table::isWritable(model(0))) {
    4277           0 :       make(model(0));
    4278           0 :       this->lock();
    4279             :     }
    4280             :     
    4281             :     // Always fill in the residual images
    4282           0 :     Vector<String> residualNames(nmodels);
    4283           0 :     if(Int(residual.nelements())==nmodels) {
    4284           0 :       residualNames=residual;
    4285             :     }
    4286             :     else {
    4287           0 :       residualNames="";
    4288             :     }
    4289           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4290           0 :       if(residualNames(thismodel)=="") {
    4291           0 :         residualNames(thismodel)=model(thismodel)+".residual";
    4292             :       }
    4293           0 :       removeTable(residualNames(thismodel));
    4294           0 :       if(!clone(model(thismodel), residualNames(thismodel))) return false;
    4295             :     }
    4296             :     
    4297             :     // Now make the NNLS ImageSkyModel
    4298           0 :     sm_p= new NNLSImageSkyModel();
    4299           0 :     sm_p->setNumberIterations(niter);
    4300           0 :     sm_p->setTolerance(tolerance);
    4301           0 :     sm_p->setAlgorithm("nnls");
    4302             :     os << LogIO::DEBUG1
    4303           0 :        << "NNLS Niter = " << niter << ", Tolerance = " << tolerance << LogIO::POST;
    4304             : 
    4305             :     //    if (!se_p)
    4306           0 :     if(!createSkyEquation(model, fixed, dataMask, fluxMask, complist)) return false;
    4307             : 
    4308           0 :     addResidualsToSkyEquation(residualNames);
    4309             :     
    4310           0 :     os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4311             : 
    4312           0 :     if(se_p->solveSkyModel()) {
    4313           0 :       os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
    4314             :     }
    4315             :     else {
    4316           0 :       os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
    4317             :     }
    4318             :     
    4319             :     // Get the PSF fit while we are here
    4320           0 :     StokesImageUtil::FitGaussianPSF(sm_p->PSF(0), beam_p);
    4321           0 :     beamValid_p=true;
    4322             :    
    4323             :     
    4324             :     // Restore the image
    4325           0 :     restoreImages(image);
    4326             : 
    4327           0 :     destroySkyEquation();
    4328           0 :     this->unlock();
    4329           0 :     return true;
    4330           0 :   } catch (AipsError x) {
    4331           0 :     this->unlock();
    4332           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4333           0 :     return false;
    4334           0 :   } 
    4335             :   this->unlock();
    4336             :   return true;
    4337           0 : }
    4338             : 
    4339             : // Fourier transform the model and componentlist
    4340          52 : Bool Imager::ft(const Vector<String>& model, const String& complist,
    4341             :                 const Bool incremental, const Double phaseCenTime)
    4342             : {
    4343          52 :   if(!valid()) return false;
    4344             :   
    4345         104 :   LogIO os(LogOrigin("imager", "ft()", WHERE));
    4346             : 
    4347          52 :   if (wvi_p==NULL)
    4348           0 :     os << LogIO::WARN << "Please make sure MS is writable when using Imager::ft" << LogIO::EXCEPTION;
    4349             :   
    4350          52 :   this->lock();
    4351             :   try {
    4352             :     
    4353          52 :     if(!redoSkyModel_p){
    4354             :       //let us try to update the sm_p then
    4355             :       //so as to keep the state and psf's etc if they have been calculated
    4356             :       //useful when cleaning, modify/clip model then predict, selfcal and clean again
    4357           0 :       if(!updateSkyModel(model, complist))
    4358           0 :         destroySkyEquation();
    4359             :     }
    4360             : 
    4361             :     os << LogIO::NORMAL // Loglevel INFO
    4362         104 :        << String("Fourier transforming: ") + 
    4363         208 :       (incremental ? String("adding to "): String("replacing "))+ 
    4364         156 :       (useModelCol_p ? String("MODEL_DATA column") : String("visibility model header")) << LogIO::POST;
    4365             :    
    4366          52 :     if (redoSkyModel_p){
    4367          52 :       if(!createSkyEquation(model, complist)) return false;
    4368             :     }
    4369          52 :     if(incremental){
    4370           2 :       for (Int mod=0; mod < (sm_p->numberOfModels()); ++mod){
    4371           1 :         (sm_p->deltaImage(mod)).copyData(sm_p->image(mod));
    4372             :       }
    4373             :     }
    4374          52 :     se_p->setPhaseCenterTime(phaseCenTime);
    4375          52 :     se_p->predict(incremental);
    4376             :     
    4377             :     // destroySkyEquation();
    4378             :     
    4379          52 :     this->unlock();
    4380          52 :     return true;
    4381           0 :   } catch (AipsError x) {
    4382           0 :     this->unlock();
    4383           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4384           0 :     return false;
    4385           0 :   } 
    4386             :   this->unlock();
    4387             :   return true;
    4388          52 : }
    4389             : 
    4390           0 : Bool Imager::setjy(const Int fieldid, 
    4391             :                    const Int spectralwindowid,
    4392             :                    const Vector<Double>& fluxDensity, const String& standard)
    4393             : {
    4394             :   // the old interface to new interface
    4395           0 :   String fieldnames="";
    4396           0 :   String spwstring="";
    4397           0 :   Vector<Int>fldids(1,fieldid);
    4398           0 :   Vector<Int>spwids(1,spectralwindowid);
    4399           0 :   return setjy(fldids, spwids, fieldnames, spwstring, fluxDensity, standard);
    4400             : 
    4401           0 : }
    4402             : 
    4403           0 : Bool Imager::setjy(const Vector<Int>& /*fieldid*/,
    4404             :                    const Vector<Int>& /*spectralwindowid*/,
    4405             :                    const String& fieldnames, const String& spwstring,
    4406             :                    const Vector<Double>& fluxDensity, const String& standard)
    4407             : {
    4408           0 :   if(!valid()) return false;
    4409           0 :   logSink_p.clearLocally();
    4410           0 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    4411           0 :   this->lock();
    4412             : 
    4413           0 :   String tempCL;
    4414             :   try {
    4415           0 :     Bool precompute=(fluxDensity(0) <= 0);
    4416             : 
    4417             :     // Figure out which fields/spws to treat
    4418           0 :     Record selrec=ms_p->msseltoindex(spwstring, fieldnames);
    4419           0 :     Vector<Int> fldids(selrec.asArrayInt("field"));
    4420           0 :     Vector<Int> spwids(selrec.asArrayInt("spw"));
    4421             : 
    4422           0 :     expand_blank_sel(spwids, ms_p->spectralWindow().nrow());
    4423           0 :     expand_blank_sel(fldids, ms_p->field().nrow());
    4424             : 
    4425             :     // Loop over field id. and spectral window id.
    4426           0 :     Vector<Double> fluxUsed(4);
    4427           0 :     String fluxScaleName;
    4428           0 :     Bool matchedScale=false;
    4429             :     Int spwid, fldid;
    4430           0 :     MSColumns msc(*ms_p);
    4431           0 :     ConstantSpectrum cspectrum;
    4432             :     // TT
    4433           0 :     Double meantime = msc.time()(0);
    4434           0 :     meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    4435           0 :     MEpoch mtime(msc.timeMeas()(0));
    4436           0 :     mtime.set(Quantity(meantime, "s"));
    4437             : 
    4438             : 
    4439           0 :     for (uInt kk=0; kk<fldids.nelements(); ++kk) {
    4440           0 :       fldid=fldids[kk];
    4441             :       // Extract field name and field center position 
    4442           0 :       MDirection position=msc.field().phaseDirMeas(fldid, meantime);
    4443           0 :       String fieldName=msc.field().name()(fldid);
    4444             : 
    4445           0 :       for (uInt jj=0; jj< spwids.nelements(); ++jj) {
    4446           0 :         spwid=spwids[jj];
    4447             : 
    4448             :         // Determine spectral window center frequency
    4449           0 :         IPosition ipos(1,0);
    4450           0 :         MFrequency mfreq=msc.spectralWindow().chanFreqMeas()(spwid)(ipos);
    4451           0 :         Array<Double> freqArray;
    4452           0 :         msc.spectralWindow().chanFreq().get(spwid, freqArray, true);
    4453           0 :         Double medianFreq=median(freqArray);
    4454           0 :         mfreq.set(MVFrequency(medianFreq));
    4455             : 
    4456           0 :         fluxUsed=fluxDensity;
    4457           0 :         fluxScaleName="user-specified";
    4458           0 :         if (precompute) {
    4459             :           // Pre-compute flux density for standard sources if not specified
    4460             :           // using the specified flux scale standard or catalog.
    4461             : 
    4462             : 
    4463             :           FluxStandard::FluxScale fluxScaleEnum;
    4464           0 :           matchedScale=FluxStandard::matchStandard(standard, fluxScaleEnum, 
    4465             :                                                    fluxScaleName);
    4466             :           (void)matchedScale;
    4467           0 :           FluxStandard fluxStd(fluxScaleEnum);
    4468           0 :           Flux<Double> returnFlux, returnFluxErr;
    4469             : 
    4470           0 :           if (fluxStd.compute(fieldName, position, mfreq, mtime, returnFlux, returnFluxErr)) {
    4471             :             // Standard reference source identified
    4472           0 :             returnFlux.value(fluxUsed);
    4473             :           } 
    4474             : 
    4475             :           // dgoscha, NCSA, 02 May, 2002
    4476             :           // this else condtion is to handle the case where the user
    4477             :           // specifies standard='SOURCE' in the setjy argument.  This will
    4478             :           // then look into the SOURCE_MODEL column of the SOURCE subtable
    4479             :           // for a table-record entry that points to a component list with the
    4480             :           // model information in it.
    4481             : 
    4482             : 
    4483           0 :           else if (standard==String("SOURCE")) {
    4484             :                 // Look in the SOURCE_MODEL column of the SOURCE subtable for 
    4485             :                 // the name of the CL which contains the model.
    4486             : 
    4487             :                 // First test to make sure the SOURCE_MODEL column exists.
    4488           0 :                 if (ms_p->source().tableDesc().isColumn("SOURCE_MODEL")) {
    4489           0 :                         TableRecord modelRecord;
    4490           0 :                         msc.source().sourceModel().get(0, modelRecord);
    4491             :         
    4492             :                         // Get the name of the model component list from the table record
    4493             :                         Table modelRecordTable = 
    4494           0 :                                 modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
    4495           0 :                         String modelCLName = modelRecordTable.tableName();
    4496           0 :                         modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
    4497             : 
    4498             :                         // Now grab the flux from the model component list and use.
    4499           0 :                         ComponentList modelCL = ComponentList(Path(modelCLName), true);
    4500           0 :                         SkyComponent fluxComponent = modelCL.component(fldid);
    4501             : 
    4502           0 :                         fluxUsed = 0;
    4503           0 :                         fluxUsed = real(fluxComponent.flux().value());
    4504           0 :                         fluxScaleName = modelCLName;
    4505           0 :                 }
    4506             :                 else {
    4507             :                         os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
    4508             :                            << LogIO::SEVERE << "Using default, I=1.0"
    4509           0 :                            << LogIO::POST;
    4510           0 :                         fluxUsed = 0;
    4511           0 :                         fluxUsed(0) = 1.0;
    4512             :                 }
    4513             :           }
    4514             : 
    4515             :           else {
    4516             :             // Source not found; use Stokes I=1.0 Jy for now
    4517           0 :             fluxUsed=0;
    4518           0 :             fluxUsed(0)=1.0;
    4519           0 :             fluxScaleName="default";
    4520             :           };
    4521           0 :         }
    4522             : 
    4523             :         // Set the component flux density
    4524           0 :         Flux<Double> fluxval;
    4525           0 :         fluxval.setValue(fluxUsed);
    4526             : 
    4527             :         // Create a point component at the field center
    4528             :         // with the specified flux density
    4529           0 :         PointShape point(position);
    4530           0 :         SkyComponent skycomp(fluxval, point, cspectrum);
    4531             : 
    4532             :         // Create a component list containing this entry
    4533           0 :         String baseString=msname_p + "." + fieldName + ".spw" +
    4534           0 :           String::toString(spwid);
    4535           0 :         tempCL=baseString + ".tempcl";
    4536             : 
    4537             :         // Force a call to the ComponentList destructor
    4538             :         // using scoping rules.
    4539             :         { 
    4540           0 :           ComponentList cl;
    4541           0 :           cl.add(skycomp);
    4542           0 :           cl.rename(tempCL, Table::New);
    4543           0 :         }
    4544             : 
    4545             :         // Select the uv-data for this field and spw. id.;
    4546             :         // all frequency channels selected.
    4547           0 :         Vector<Int> selectSpw(1), selectField(1);
    4548           0 :         selectSpw(0)=spwid;
    4549           0 :         selectField(0)=fldid;
    4550           0 :         String msSelectString = "";
    4551           0 :         Vector<Int> numDeChan(1);
    4552           0 :         numDeChan[0]=0;
    4553           0 :         Vector<Int> begin(1);
    4554           0 :         begin[0]=0;
    4555           0 :         Vector<Int> stepsize(1);
    4556           0 :         stepsize[0]=1;
    4557           0 :         setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(), 
    4558           0 :                 MRadialVelocity(),
    4559           0 :                 selectSpw, selectField, msSelectString, "", "", Vector<Int>(), 
    4560             :                 "", "", "", "", "", "",true);
    4561             : 
    4562           0 :         if (!nullSelect_p) {
    4563             : 
    4564             :           // Transform the component model table
    4565           0 :           Vector<String> model;
    4566           0 :           ft(model, tempCL, false);
    4567             : 
    4568             :           // Log flux density used for this field and spectral window
    4569           0 :           os.output().width(12);
    4570           0 :           os << fieldName << "  spwid=";
    4571           0 :           os.output().width(3);
    4572           0 :           os << (spwid) << "  ";
    4573           0 :           os.output().width(0);
    4574           0 :           os.output().precision(4);
    4575           0 :           os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    4576           0 :           os << "Q=" << fluxUsed(1) << ", ";
    4577           0 :           os << "U=" << fluxUsed(2) << ", ";
    4578           0 :           os << "V=" << fluxUsed(3) << "] Jy, ";
    4579           0 :           os << ("(" + fluxScaleName + ")") << LogIO::POST;
    4580           0 :         };
    4581             :           
    4582             :         // Delete the temporary component list and image tables
    4583           0 :         TableUtil::deleteTable(tempCL);
    4584             : 
    4585           0 :       }
    4586           0 :     }
    4587           0 :     this->writeHistory(os);
    4588           0 :     this->unlock();
    4589           0 :     return true;
    4590             : 
    4591           0 :   } catch (AipsError x) {
    4592           0 :     this->unlock();
    4593           0 :     if(TableUtil::canDeleteTable(tempCL)) TableUtil::deleteTable(tempCL);
    4594           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4595           0 :     return false;
    4596           0 :   } 
    4597             :   return true;
    4598           0 : }
    4599             : 
    4600             : // This is the one used by im.setjy() (because it has a model arg).
    4601             : // CURRENT SETJY CODE
    4602           7 : Record Imager::setjy(const Vector<Int>& /*fieldid*/,
    4603             :                    const Vector<Int>& /*spectralwindowid*/,
    4604             :                    const String& fieldnames, const String& spwstring,
    4605             :                    const String& model,
    4606             :                    const Vector<Double>& fluxDensity, 
    4607             :                    const String& standard, const Bool chanDep,
    4608             :                    //const Double spix, const MFrequency& reffreq,
    4609             :                    const Vector<Double>& spix, const MFrequency& reffreq,
    4610             :                    const Vector<Double>& pipars,const Vector<Double>& papars, 
    4611             :                    const Double& rotMeas,
    4612             :                    const String& timerange, const String& scanstr,
    4613             :                    const String& intentstr, const String& obsidstr,
    4614             :                    const String& interpolation)
    4615             : {
    4616             :   //if(!valid())
    4617             :     //return false;
    4618             : 
    4619             :   //Bool didAnything = false;
    4620             :   
    4621           7 :   Record retval;
    4622           7 :   if(!valid()) {
    4623           0 :     retval.define("process",false);
    4624           0 :     return retval;
    4625             :   }
    4626             : 
    4627           7 :   logSink_p.clearLocally();
    4628          14 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    4629           7 :   this->lock();
    4630             : 
    4631             :   // user specified flux densities (IQUV), global to the spws and fields
    4632           7 :   Vector<Double> fluxdens = fluxDensity;
    4633           7 :   if(fluxDensity.nelements() < 4){
    4634           7 :     fluxdens.resize(4,true);
    4635          28 :     for(Int i = fluxDensity.nelements(); i < 4; ++i)
    4636          21 :       fluxdens[i] = 0.0;
    4637             :   }
    4638             : 
    4639           7 :   Vector<String> tempCLs;
    4640           7 :   TempImage<Float> *tmodimage(NULL);
    4641             : 
    4642             :   try{
    4643           7 :     Bool precompute = fluxdens[0] < 0.0;
    4644             : 
    4645             :     // Figure out which fields/spws to treat
    4646             :     // including intent info 
    4647           7 :     MSSelection mssel;
    4648           7 :     mssel.setFieldExpr(fieldnames);
    4649           7 :     mssel.setSpwExpr(spwstring);
    4650           7 :     mssel.setStateExpr(intentstr);
    4651           7 :     TableExprNode exprNode = mssel.toTableExprNode(&(*ms_p));
    4652             :     //Vector<Int> fldids;
    4653           7 :     Vector<Int> fldids(mssel.getFieldList());
    4654           7 :     Vector<Int> selToRawSpwIds(mssel.getSpwList());
    4655             :     // if intent is given try to do AND with fieldIds
    4656           7 :     if (intentstr!="") {
    4657           0 :       mssel_p = new MeasurementSet((*ms_p)(exprNode), &(*ms_p));
    4658           0 :       MSColumns tmpmsc(*mssel_p);
    4659           0 :       Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
    4660           0 :       if (fldidv.nelements()==0) 
    4661           0 :         throw(AipsError("No field ids were selected, please check input parameters"));
    4662           0 :       std::set<Int> ufldids(fldidv.begin(),fldidv.end());
    4663           0 :       std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
    4664           0 :       fldids.resize(tmpv.size());
    4665           0 :       uInt count=0;
    4666           0 :       for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
    4667             :       {
    4668           0 :          fldids(count) = *it;
    4669           0 :          count++;
    4670             :       }
    4671           0 :     }
    4672             :     //else {
    4673             :     //  fldids(mssel.getFieldList());
    4674             :     //}
    4675             :     //cerr<<"fldids.nelements()="<<fldids.nelements()<<endl;
    4676             :     //for (uInt i = 0; i < fldids.nelements(); i++) {
    4677             :     //    cerr<<"fldids="<<fldids(i)<<endl;
    4678             :     //}
    4679             :     //Record selrec = ms_p->msseltoindex(spwstring, fieldnames);
    4680             :     //Vector<Int> fldids(selrec.asArrayInt("field"));
    4681             :     //Vector<Int> selToRawSpwIds(selrec.asArrayInt("spw"));
    4682             :  
    4683           7 :     expand_blank_sel(selToRawSpwIds, ms_p->spectralWindow().nrow());
    4684           7 :     expand_blank_sel(fldids, ms_p->field().nrow());
    4685             : 
    4686             :     // Warn against multiple fields in some circumstances.
    4687           7 :     if (fldids.nelements() > 1 && (model != "" || !precompute)) {
    4688           0 :       String errmsg("setjy is applying a single ");
    4689             : 
    4690           0 :       if(model != ""){
    4691           0 :         errmsg += "modimage";
    4692           0 :         if(!precompute)
    4693           0 :           errmsg += " or ";
    4694             :       }
    4695             : 
    4696           0 :       if(!precompute)
    4697           0 :         errmsg += "fluxdensity";
    4698             : 
    4699           0 :       errmsg += " to multiple fields!\n";
    4700             :       os << LogIO::WARN
    4701             :          << errmsg
    4702             :          << "This could be a user error, but sometimes a single name will\n"
    4703             :          << "resolve to > 1 field index.\n"
    4704           0 :          << LogIO::POST;
    4705             :       //throw(AipsError(errmsg));
    4706           0 :     }
    4707             : 
    4708           7 :     os << LogIO::NORMAL;
    4709           7 :     if(precompute || spix[0] != 0.0)
    4710           5 :       os << "Using " << ((chanDep || (!precompute && spix[0] != 0.0)) ? "channel" : 
    4711          12 :                          "spw") << " dependent flux densities";
    4712             :     else
    4713           0 :       os << "The applied flux density does not depend on frequency.";
    4714           7 :     os << LogIO::POST;
    4715             : 
    4716             :     // Ignore user polarization if using an image.
    4717           7 :     if(model != "" &&
    4718           0 :        (fluxdens[1] != 0.0 || fluxdens[2] != 0.0 || fluxdens[3] != 0.0)){
    4719             :       os << LogIO::WARN
    4720             :          << "Using model image, so zeroing user QUV flux densities."
    4721           0 :          << LogIO::POST;
    4722           0 :       fluxdens[1] = fluxdens[2] = fluxdens[3] = 0.0;
    4723           0 :       writeHistory(os);
    4724             :     }
    4725             : 
    4726             :     // Loop over field id. and spectral window id.
    4727             :     //Vector<Double> fluxUsed(4);
    4728           7 :     String fluxScaleName("user-specified");
    4729             :     FluxStandard::FluxScale fluxScaleEnum;
    4730           7 :     if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
    4731           0 :       throw(AipsError(standard + " is not a recognized flux density scale"));
    4732             : 
    4733           7 :     FluxStandard fluxStd(fluxScaleEnum);
    4734           7 :     if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 || 
    4735           7 :         fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017 ) {
    4736           2 :       fluxStd.setInterpMethod(interpolation);
    4737             :     }
    4738             : 
    4739             :     // Setup the frequency, Flux, and ComponentList arrays.
    4740           7 :     uInt nspws = selToRawSpwIds.nelements();
    4741           7 :     Vector<Vector<Flux<Double> > > returnFluxes(nspws), returnFluxErrs(nspws);
    4742           7 :     Vector<Vector<MFrequency> > mfreqs(nspws);
    4743           7 :     Vector<Vector<Double> > fluxUsed(nspws); // fluxesUsed(nspws,4) 
    4744           7 :     MSColumns msc(*ms_p);
    4745           7 :     MEpoch aveEpoch=MEpoch(msc.timeMeas()(0));
    4746             :     const Unit freqUnit = sjy_setup_arrs(returnFluxes, returnFluxErrs, fluxUsed, tempCLs, mfreqs,
    4747           7 :                                          msc.spectralWindow(), nspws, selToRawSpwIds,
    4748           7 :                                          chanDep);
    4749             :     // Processing for each field ***************************************************
    4750          16 :     for(Int fldInd = fldids.nelements(); fldInd--;){
    4751           9 :       Int fldid = fldids[fldInd];
    4752             :       // Extract field name and field center position 
    4753           9 :       MDirection fieldDir = msc.field().phaseDirMeas(fldid, msc.time()(0));
    4754           9 :       String fieldName = msc.field().name()(fldid);
    4755           9 :       Bool foundSrc = false;
    4756             :     
    4757             :       //for returned flux densities
    4758             :       
    4759           9 :       Record retvalperField;
    4760             :       //
    4761             :       //fluxUsed = fluxdens;
    4762           9 :       fluxUsed(0) = fluxdens;
    4763             :       //if(precompute){
    4764             :         // Pre-compute flux density for standard sources if not specified
    4765             :         // using the specified flux scale standard or catalog.
    4766             :         //
    4767             :         // The flux densities are calculated for all spws at once to avoid
    4768             :         // repeatedly digging up the flux model (and possibly the ephemeris).
    4769             :         //
    4770             :         // TT: moving this outside of if(precompute) since selected ms (mssel_p)
    4771             :         // will be needed for other cases to clear the model using 
    4772             :         // VisModelData::ClearModel()
    4773             :         
    4774           9 :         Vector<Int> selectField(1);
    4775           9 :         selectField[0] = fldid;
    4776           9 :         Vector<Int> numDeChan(1);
    4777           9 :         numDeChan[0] = 0;
    4778           9 :         Vector<Int> begin(1);
    4779           9 :         begin[0] = 0;
    4780           9 :         Vector<Int> stepsize(1);
    4781           9 :         stepsize[0] = 1;
    4782           9 :         String msSelectString = "";
    4783          36 :         setdata("none", numDeChan, begin, stepsize, MRadialVelocity(), 
    4784          18 :                 MRadialVelocity(),
    4785             :                 selToRawSpwIds, selectField, msSelectString, timerange, "",
    4786          18 :                 Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
    4787           9 :         if(nullSelect_p){
    4788           4 :           os << ((timerange == "" && scanstr == ""
    4789           2 :                   && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
    4790             :              << "No data was selected for field " << fldid << "."
    4791           4 :              << LogIO::POST;
    4792           2 :           continue;
    4793             :         }
    4794           7 :       if(precompute){
    4795             :         // Make componentlist for each spw.
    4796             :         // Pre-compute flux density for standard sources if not specified
    4797             :         // using the specified flux scale standard or catalog.
    4798             :         //
    4799             :         // The flux densities are calculated for all spws at once to avoid
    4800             :         // repeatedly digging up the flux model (and possibly the ephemeris).
    4801             :         //
    4802           7 :         MSColumns msselc(*mssel_p);
    4803             :         //if(nullSelect_p || msselc.nrow() < 1){
    4804           7 :         if(!nullSelect_p and  msselc.nrow() < 1){
    4805           0 :           os << ((timerange == "" && scanstr == ""
    4806           0 :                   && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
    4807             :              << "No data was selected for field " << fldid << "."
    4808           0 :              << LogIO::POST;
    4809           0 :           continue;
    4810             :         }
    4811             : 
    4812             :         // chnage to return cocantenated CL?
    4813           7 :         foundSrc = sjy_computeFlux(os, fluxStd, returnFluxes, returnFluxErrs, tempCLs,
    4814             :                                    fluxUsed, fluxScaleName, aveEpoch, mfreqs, model, fieldName,
    4815             :                                    msselc, fldid, fieldDir, selToRawSpwIds, standard);
    4816             :         (void)foundSrc;
    4817           7 :       }
    4818             :       
    4819             :       //*************** For loop about spw starts here ****************************
    4820           7 :       Vector<Double>  freqscaling;
    4821           7 :       Vector<Double> freqsOfScale;
    4822           7 :       Vector<Int> rawspwids(nspws);
    4823             :       // make raw spw id list
    4824          44 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4825          37 :         Int rawspwid = selToRawSpwIds[selspw];
    4826          37 :         rawspwids[selspw]=rawspwid;
    4827             :       } 
    4828             : 
    4829             :         // move inside sjy_computeFlux  - TT, 2014.06.13 
    4830             :         /***
    4831             :         if(foundSrc){
    4832             :           // Log fluxes found from the standard catalog database to HISTORY table 
    4833             :           // get I-flux density for the selected spw (returnFluxes[nspw][4]) 
    4834             :           // Read this as fluxUsed = returnFluxes[selspw][0].value().
    4835             :           os << "CHECK: foundSrc....."<<LogIO::POST;
    4836             :           returnFluxes[selspw][0].value(fluxUsed);
    4837             :             
    4838             :           // Log flux density found for this field and spectral window
    4839             :           os.output().width(12);
    4840             :           os << fieldName;
    4841             :           os.output().width(2);
    4842             :           os << " (fld ind " << fldid << ") spw ";
    4843             :           os << rawspwid << "  ";
    4844             :           os.output().width(0);
    4845             :           os.output().precision(5);
    4846             :           os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    4847             :           os << "Q=" << fluxUsed(1) << ", ";
    4848             :           os << "U=" << fluxUsed(2) << ", ";
    4849             :           os << "V=" << fluxUsed(3) << "] Jy, ";
    4850             :           os << ("(" + fluxScaleName + ")") << LogIO::POST;
    4851             :           writeHistory(os);
    4852             :         }
    4853             :           
    4854             :         // If a model image has been specified, 
    4855             :         //  rescale it according to the I f.d. determined above
    4856             : 
    4857             :         //Vector<Double> freqscaling;
    4858             :         //Vector<Double> freqsOfScale;
    4859             : 
    4860             :         //MEpoch mtime = msc.field().timeMeas()(fldid);
    4861             : 
    4862             :       } //spw for-loop end
    4863             :       ****/
    4864             :       
    4865           7 :       MEpoch mtime = msc.field().timeMeas()(fldid);
    4866             : 
    4867             :       // model image prep. changed to do all spws at once - TT, 2014.06.13
    4868           7 :       if(model != ""){
    4869             : 
    4870           0 :         tmodimage = sjy_prepImage(os, fluxStd, fluxUsed[0], freqsOfScale, freqscaling, model, msc.spectralWindow(),
    4871             :        // tmodimage = sjy_prepImage(os, fluxStd, fluxUsed, freqsOfScale, freqscaling, model, msc.spectralWindow(),
    4872             :       //                          rawspwid, chanDep, mfreqs, selspw, fieldName,
    4873             :                                   selToRawSpwIds, chanDep, mfreqs, fieldName,
    4874             :                                   fieldDir, freqUnit, fluxdens, precompute, spix,
    4875             :                                   reffreq, aveEpoch, fldid);
    4876             :           
    4877             :       }
    4878           7 :       else if (!precompute) {
    4879             :         // do it in sjy_makeComponentList()
    4880             :         // TODO: add polindex, polangle, rm handling
    4881             :         // for now ignore circular polarization
    4882             :         //Vector<Double> cppars(1,0.0);
    4883           0 :         Vector<Double> checkfluxes;
    4884           0 :         sjy_makeComponentList(os, tempCLs, returnFluxes, fluxUsed[0], selToRawSpwIds, mfreqs, fieldName, fieldDir, 
    4885             :                             spix, pipars, papars, rotMeas, reffreq, aveEpoch, fldid);
    4886           0 :         returnFluxes[0][0].value(checkfluxes);
    4887           0 :       }
    4888             :       /*** moved to sjy_makeComponentList()
    4889             :       // make componentlist using flux densities from the user specfied fluxdensity(per-spw) 
    4890             :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4891             :         Int rawspwid = selToRawSpwIds[selspw];
    4892             :         rawspwids[selspw]=rawspwid;
    4893             :         if(model == "" && !precompute){
    4894             :           // **** inside spw for-loop
    4895             :           // fluxUsed was supplied by the user instead of FluxStandard, so
    4896             :           // make a component list for it now, for use in ft.
    4897             : 
    4898             :           // Set the component flux density
    4899             :           Flux<Double> fluxval;
    4900             :           Flux<Double> fluxerr;
    4901             :           fluxval.setValue(fluxUsed[0]);
    4902             :           // Create a point component at the field center
    4903             :           // with the specified flux density 
    4904             :           // - obviously this does not correct for solar objects... 
    4905             :           PointShape point(fieldDir);
    4906             :           SpectralIndex siModel;
    4907             :           if(reffreq.getValue().getValue() > 0.0){
    4908             :             MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
    4909             :             MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
    4910             :             siModel.setRefFrequency(reffreq);
    4911             :             siModel.setIndex(spix);
    4912             :             returnFluxes[selspw][0].setValue(fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][0])));
    4913             :           }
    4914             :           else{
    4915             :             if(spix != 0.0){            // If not the default, complain and quit.
    4916             :               os << LogIO::SEVERE
    4917             :                  << "spix cannot be nonzero with reffreq = 0!"
    4918             :                  << LogIO::POST;
    4919             :               //return false;
    4920             :             }
    4921             :             siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
    4922             :             siModel.setIndex(0.0);
    4923             :           }
    4924             : 
    4925             :           // No worries about varying fluxes or sizes here, so any time will do.
    4926             :           // Moved this line up (TT 2013/05/09) 
    4927             :           //MEpoch mtime = msc.field().timeMeas()(fldid);
    4928             :           tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    4929             :                                                             mfreqs[selspw][0],
    4930             :                                                             mtime, fluxval, point,
    4931             :                                                             siModel,
    4932             :           // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
    4933             :                                                             ms_p->tableName() +
    4934             :                                                             "_setjy_spw" +
    4935             :                                                             String::toString(selspw) +
    4936             :                                                             "_");
    4937             :         }
    4938             :         ***/
    4939             : 
    4940             :         // clear existing model for the selected field and for all selected spws 
    4941             :         // outside spw loop
    4942             :         //if (!useModelCol_p && selspw==0) {
    4943           7 :         if (!useModelCol_p) {
    4944           4 :           String tmpspwstring=spwstring;
    4945           4 :           if (tmpspwstring=="") tmpspwstring="*";
    4946             :           os << LogIO::NORMAL
    4947             :              << "Will clear any existing model with matching field="
    4948             :              << fieldName
    4949             :              << " and spw=" << tmpspwstring
    4950           4 :              << LogIO::POST;
    4951             : 
    4952           4 :           String fldidstr = String::toString(fldid); 
    4953             :           // use field id due to possible MSSelection bug for handing field name with blanks
    4954             :           //VisModelData::clearModel(*mssel_p, fieldName, spwstring)
    4955           4 :           VisModelData::clearModel(*mssel_p, fldidstr, spwstring);
    4956           4 :         }
    4957             :         // TODO: do it for all spw at once............
    4958             :         //sjy_make_visibilities(tmodimage, os, rawspwid, fldid, tempCLs[selspw],
    4959             :         //                      timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    4960             :         
    4961             :         /***
    4962             :         if(tmodimage)
    4963             :           delete tmodimage;
    4964             :         tmodimage = NULL;
    4965             :         //      if (Table::canDeleteTable("temp.setjy.image")) Table::deleteTable("temp.setjy.image");
    4966             : 
    4967             :         if(tempCLs[selspw] != ""){
    4968             :           String errmsg;
    4969             : 
    4970             :           //didAnything = true;
    4971             :           // commentted out for testing of concatCLs, may need to uncommentted later!!!!!!
    4972             : 
    4973             :           if(Table::canDeleteTable(errmsg, tempCLs[selspw]))
    4974             :             Table::deleteTable(tempCLs[selspw]);
    4975             :           else
    4976             :             os << LogIO::WARN
    4977             :                << "Could not rm " << tempCLs[selspw]
    4978             :                << " because the " << errmsg << "."
    4979             :                << LogIO::POST;
    4980             :         }
    4981             :         ***/
    4982             : 
    4983          44 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4984          37 :         Record subrec;
    4985             :         //store fluxd actually used to scale (not input fluxdensity)
    4986          37 :         Vector<Double> finalFluxUsed;
    4987             :         // Flux of first chan
    4988          37 :         returnFluxes[selspw][0].value(finalFluxUsed);
    4989          37 :         subrec.define("fluxd",finalFluxUsed);
    4990             :         // TODO: add fluxd error when the flux density uncertainties 
    4991             :         //       are corrrectly filled.
    4992             :         //
    4993             :         //retvalperField.defineRecord(String::toString(rawspwid),subrec);
    4994          37 :         retvalperField.defineRecord(String::toString(selToRawSpwIds[selspw]),subrec);
    4995          37 :       }   // for selspw end **********************************************
    4996             :       //retval.defineRecord(fieldName,retvalperField);
    4997           7 :       retvalperField.define("fieldName",fieldName);
    4998           7 :       retval.defineRecord(String::toString(fldid),retvalperField);
    4999             : 
    5000             :       // cocatenate componentlists - not yet used....
    5001             :       //if (tempCLs[0]!="") {
    5002             :         // concatcl name should contains field name mjd etc...
    5003             :       //  ostringstream oss;
    5004             :       //  oss<< ms_p->tableName() << "_setjy_"
    5005             :       //     << fieldName << "_" << mtime.get("d").getValue()
    5006             :       //     << "d.cl";
    5007             :       //  String concatcl(oss);
    5008             :       //  sjy_concatComponentLists(os, tempCLs, concatcl);
    5009             :       //}
    5010             : 
    5011             :       //sjy_make_visibilities(tmodimage, os, rawspwids, fldid, concatcl,
    5012             :       //                      timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    5013             :       //
    5014             :       //### Uncomment above once setjyFTMachine can handle multi-row componentlist ############# 
    5015             : 
    5016          44 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    5017          37 :         sjy_make_visibilities(tmodimage, os, rawspwids[selspw], fldid, tempCLs[selspw],
    5018             :                             timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    5019             :       }
    5020             :       // #######################################################################################
    5021             :       // clean-up
    5022             :       //  
    5023           7 :       if(tmodimage)
    5024           0 :         delete tmodimage;
    5025           7 :       tmodimage = NULL;
    5026             : 
    5027          44 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    5028          37 :         if(tempCLs[selspw] != ""){
    5029          37 :           String errmsg;
    5030             : 
    5031             :           //didAnything = true;
    5032             : 
    5033          37 :           if(TableUtil::canDeleteTable(errmsg, tempCLs[selspw]))
    5034          37 :             TableUtil::deleteTable(tempCLs[selspw]);
    5035             :           else
    5036             :             os << LogIO::WARN
    5037           0 :                << "Could not rm " << tempCLs[selspw]
    5038             :                << " because the " << errmsg << "."
    5039           0 :                << LogIO::POST;
    5040             : 
    5041             :           //if(Table::canDeleteTable(errmsg, concatcl))
    5042             :           //  Table::deleteTable(concatcl);
    5043          37 :         }
    5044             :       }
    5045             :       
    5046          23 :     }   // End of loop over fields.
    5047             :     // add a format info for the returned flux densities (Record)
    5048             :     //retval.define("format","{field name: {spw Id: {fluxd: [I,Q,U,V] in Jy}}}");
    5049           7 :     retval.define("format","{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}");
    5050             : 
    5051           7 :     if(!precompute && spix[0] != 0.0 && reffreq.getValue().getValue() > 0.0){
    5052             :       os << LogIO::NORMAL
    5053             :          << "Flux density as a function of frequency (channel 0 of each spw):\n"
    5054             :          << "  Frequency (GHz)    Flux Density (Jy, Stokes I)"
    5055           0 :          << LogIO::POST;
    5056           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw)
    5057           0 :         os << "     " << mfreqs[selspw][0].get("GHz").getValue() << "         "
    5058           0 :            << returnFluxes[selspw][0].value(Stokes::I).getValue()
    5059           0 :            << LogIO::POST;
    5060             :     }
    5061             : 
    5062           7 :     this->writeHistory(os);
    5063           7 :     this->unlock();
    5064             :     //return true;
    5065           7 :   }
    5066           0 :   catch (AipsError x){
    5067           0 :     this->unlock();
    5068           0 :     for(Int i = tempCLs.nelements(); i--;){
    5069           0 :       if(tempCLs[i] != "")
    5070           0 :         TableUtil::deleteTable(tempCLs[i]);
    5071             :     }
    5072           0 :     if (tmodimage) delete tmodimage; tmodimage=NULL;
    5073           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    5074             :     //return false;
    5075           0 :   } 
    5076             :   //return didAnything;
    5077           7 :   return retval;
    5078           7 : }
    5079             : 
    5080           0 : String Imager::make_comp(const String& objName,
    5081             :                          const String& standard,
    5082             :                          const MEpoch& mtime, const Vector<MFrequency>& freqv,
    5083             :                          const String& prefix)
    5084             : {
    5085           0 :   Bool foundSrc = false;
    5086           0 :   logSink_p.clearLocally();
    5087           0 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    5088             : 
    5089           0 :   Vector<String> clistnames(1);
    5090             :   try{
    5091             :     FluxStandard::FluxScale fluxScaleEnum;
    5092           0 :     String fluxScaleName("user-specified");
    5093             : 
    5094           0 :     if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
    5095           0 :       throw(AipsError(standard + " is not a recognized flux density scale"));
    5096             : 
    5097           0 :     FluxStandard fluxStd(fluxScaleEnum);
    5098             : 
    5099           0 :     Vector<Vector<Flux<Double> > > returnFluxes(1), returnFluxErrs(1);
    5100           0 :     Vector<Vector<MFrequency> > mfreqs(1);
    5101           0 :     uInt nfreqs = freqv.nelements();
    5102             : 
    5103           0 :     mfreqs[0] = freqv;
    5104           0 :     returnFluxes[0].resize(nfreqs);
    5105           0 :     returnFluxErrs[0].resize(nfreqs);
    5106             : 
    5107           0 :     MDirection objDir;
    5108             :     
    5109           0 :     if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 || 
    5110           0 :         fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017) 
    5111             :     { 
    5112           0 :       fluxStd.setInterpMethod("nearest");
    5113             :     }
    5114           0 :     foundSrc = fluxStd.computeCL(objName, mfreqs, mtime, objDir,
    5115             :                                  returnFluxes, returnFluxErrs,
    5116             :                                  clistnames, prefix);
    5117           0 :   }
    5118           0 :   catch(AipsError x){
    5119           0 :     os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
    5120           0 :     RETHROW(x);
    5121           0 :   }  
    5122           0 :   return foundSrc ? clistnames[0] : "";
    5123           0 : }
    5124             : 
    5125           7 : Unit Imager::sjy_setup_arrs(Vector<Vector<Flux<Double> > >& returnFluxes,
    5126             :                             Vector<Vector<Flux<Double> > >& returnFluxErrs,
    5127             :                             Vector<Vector<Double> >& fluxUsed,
    5128             :                             Vector<String>& tempCLs,
    5129             :                             Vector<Vector<MFrequency> >& mfreqs,
    5130             :                             const MSSpWindowColumns& spwcols, const uInt nspws,
    5131             :                             const Vector<Int>& selToRawSpwIds, const Bool chanDep)
    5132             : {
    5133             :   // .getUnits() is a little confusing - it seems to return a Vector which is
    5134             :   // a list of all the units, not the unit for each row.
    5135             : 
    5136             :   
    5137           7 :   const Unit freqUnit(spwcols.chanFreqQuant().getUnits()[0]);
    5138             : 
    5139           7 :   IPosition ipos(1, 0);
    5140             : 
    5141           7 :   tempCLs.resize(nspws);
    5142          44 :   for(uInt selspw = 0; selspw < nspws; ++selspw){
    5143          37 :     Int rawspwid = selToRawSpwIds[selspw];
    5144             : 
    5145          37 :     if(chanDep){
    5146          32 :       mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid);
    5147          32 :       uInt nchan = mfreqs[selspw].nelements();
    5148          32 :       returnFluxes[selspw].resize(nchan);
    5149          32 :       returnFluxErrs[selspw].resize(nchan);
    5150             :     }
    5151             :     else{
    5152           5 :       mfreqs[selspw].resize(1);
    5153           5 :       returnFluxes[selspw].resize(1);
    5154           5 :       returnFluxErrs[selspw].resize(1);
    5155             : 
    5156             :       // Determine spectral window center frequency
    5157           5 :       Double medianFreq = median(spwcols.chanFreq()(rawspwid));
    5158           5 :       mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid)(ipos);
    5159           5 :       mfreqs[selspw].set(MVFrequency(Quantum<Double>(medianFreq, freqUnit)));
    5160             :     }
    5161             :     // initialize fluxUsed to 0 
    5162          37 :     Vector<Double> iquvF(4,0.0);
    5163          37 :     fluxUsed[selspw]=iquvF;
    5164          37 :   }
    5165             : 
    5166          14 :   return freqUnit;
    5167           7 : }
    5168             : // new signature should be...
    5169             : /***
    5170             : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
    5171             :                                    const Vector<Int>& rawspwids, const Int fldid,
    5172             :                                    const String& clname, const String& timerange,
    5173             :                                    const String& scanstr, const String& intentstr, const String& obsidstr,
    5174             :                                    const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
    5175             : ***/
    5176          37 : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
    5177             :                                    const Int rawspwid, const Int fldid,
    5178             :                                    const String& clname, const String& timerange,
    5179             :                                    const String& scanstr, const String& intentstr, const String& obsidstr,
    5180             :                                    const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
    5181             : {
    5182          37 :   Bool made_visibilities = false;
    5183             : 
    5184             :   // Select the uv-data for this field and spw. id.;
    5185             :   // all frequency channels selected.
    5186          37 :   Vector<Int> selectSpw(1), selectField(1);
    5187             :   // for the new 
    5188             :   //Vector<Int> selectSpw, selectField(1);
    5189             :   //selectSpw.resize(rawspwids.nelements());
    5190             :   //selectSpw = rawspwids;
    5191             :   //
    5192          37 :   selectSpw[0] = rawspwid;
    5193          37 :   selectField[0] = fldid;
    5194          37 :   String msSelectString = "";
    5195          37 :   Vector<Int> numDeChan(1);
    5196          37 :   numDeChan[0] = 0;
    5197          37 :   Vector<Int> begin(1);
    5198          37 :   begin[0] = 0;
    5199          37 :   Vector<Int> stepsize(1);
    5200          37 :   stepsize[0] = 1;
    5201             :   //TempImage<Float> tmodimage = tmodimages[0];
    5202          37 :   if(tmodimage || clname != "") {
    5203             :   //if(!tmodimages[0].null() || clname != "")
    5204         148 :     setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(), 
    5205          74 :             MRadialVelocity(),
    5206             :             selectSpw, selectField, msSelectString, timerange, "",
    5207          74 :             Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
    5208             :   }
    5209          37 :   if(!nullSelect_p){
    5210             :     // Use ft to form visibilities
    5211          37 :     Vector<String> modelv;
    5212             :  
    5213          37 :     if(tmodimage){
    5214             :     //if(!tmodimages[0].null()){
    5215             :       //for (uInt imod=0; imod<tmodimages.nelements();imod++) {
    5216             :       //if(!tmodimages[imod].null()) {
    5217           0 :       if(sm_p)
    5218           0 :         destroySkyEquation();
    5219             :       // do if for each spw?
    5220           0 :       if(freqsOfScale.nelements() > 0){
    5221             :       //if(freqsOfScales[imod].nelements() > 0){
    5222           0 :         delete ft_p;
    5223           0 :         ft_p=NULL;
    5224           0 :         ftmachine_p="SetJyGridFT";
    5225           0 :         createFTMachine();
    5226           0 :         (static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScale, freqscaling);
    5227             :         //(static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScales[imod], freqscalings[imod]);
    5228             :       }
    5229           0 :       if(!ft_p)
    5230           0 :         createFTMachine();
    5231           0 :       sm_p = new CleanImageSkyModel();
    5232             :       // loop over for multiple spw model images
    5233           0 :       sm_p->add(*tmodimage, 1);
    5234             :       //sm_p->add(*(tmodimages[imod]), 1);
    5235             :       //} //if-tmodimages..
    5236             :       //} //for loop
    5237             :       // this has no effect (SetJyGridFT hardcoded to use linear now, Aug. 2016)
    5238             :       //ft_p->setFreqInterpolation("nearest");
    5239           0 :       setSkyEquation();
    5240           0 :       se_p->predict(false);
    5241           0 :       destroySkyEquation();
    5242             : 
    5243           0 :       made_visibilities = true;
    5244             :     }
    5245          37 :     else if(clname != ""){
    5246             :       //made_visibilities = ft(modelv, clname, false);
    5247          37 :       made_visibilities = ft(modelv, clname, false);
    5248          37 :       destroySkyEquation();
    5249             :     }
    5250             :     else
    5251             :       os << LogIO::NORMAL
    5252             :          << "Skipping an empty component list for spw " << rawspwid
    5253             :      // for new one
    5254             :      //    << "Skipping an empty component list for spw " << rawspwids
    5255           0 :          << LogIO::POST;
    5256          37 :   }
    5257          37 :   return made_visibilities;
    5258          37 : }
    5259             : 
    5260             : 
    5261           0 : Bool Imager::sjy_concatComponentLists(LogIO& os, const Vector<String>& tempCLs, const String& outTempCL)
    5262             : {
    5263           0 :   ComponentList concatCL;
    5264             :   try {
    5265           0 :     for (uInt icl=0; icl<tempCLs.nelements(); icl++) {
    5266           0 :       if (tempCLs[icl]!="") {
    5267             :         // expected format _setjy_spw#_...
    5268           0 :         String::size_type spos=tempCLs[icl].find(String("spw"));
    5269           0 :         String::size_type epos=tempCLs[icl].find_first_of("_",spos);
    5270           0 :         String clab = tempCLs[icl].substr(spos,epos-spos);
    5271           0 :         Path clname(tempCLs[icl]);
    5272           0 :         os <<LogIO::DEBUG1 << " tempCLs["<<icl<<"]="<<tempCLs[icl]<<LogIO::POST;
    5273           0 :         ComponentList tempcl(clname, true);
    5274           0 :         Vector<Int> which(1,0);
    5275           0 :         tempcl.setLabel(which,clab);
    5276           0 :         os << LogIO::DEBUG1 << "adding "<<tempCLs[icl]<<" to "<<outTempCL<<LogIO::POST;
    5277           0 :         concatCL.addList(tempcl);
    5278           0 :       }
    5279             :     }  
    5280           0 :     concatCL.rename(outTempCL, Table::New);
    5281           0 :     return true;
    5282           0 :   } catch (AipsError x) {
    5283             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    5284           0 :        << LogIO::EXCEPTION;
    5285           0 :     return false;
    5286           0 :   }
    5287           0 : }
    5288             : 
    5289           7 : Bool Imager::sjy_computeFlux(LogIO& os, FluxStandard& fluxStd,
    5290             :                              Vector<Vector<Flux<Double> > >& returnFluxes,
    5291             :                              Vector<Vector<Flux<Double> > >& returnFluxErrs,
    5292             :                              Vector<String>& tempCLs, 
    5293             :                              //Vector<Double>& fluxUsed,
    5294             :                              Vector<Vector<Double> >& fluxUsed,
    5295             :                              String& fluxScaleName, MEpoch& aveEpoch,
    5296             :                              const Vector<Vector<MFrequency> >& mfreqs,
    5297             :                              const String& model, const String& fieldName, 
    5298             :                              const MSColumns& msc, const Int fldid, 
    5299             :                              const MDirection& fieldDir, const Vector<Int>& selToRawSpwIds,
    5300             :                              const String& standard)
    5301             : {
    5302           7 :   Bool foundSrc = false;
    5303             :    
    5304           7 :   Double meantime = msc.time()(0);
    5305           7 :   meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    5306           7 :   MEpoch mtime(msc.timeMeas()(0));
    5307           7 :   mtime.set(Quantity(meantime, "s"));
    5308           7 :   if(model != ""){
    5309             :     // Just get the fluxes and their uncertainties for scaling the image.
    5310             :     //foundSrc = fluxStd.compute(fieldName, mfreqs, returnFluxes,
    5311             :      //                          returnFluxErrs);
    5312           0 :     foundSrc = fluxStd.compute(fieldName, fieldDir, mfreqs, mtime, returnFluxes,
    5313             :                               returnFluxErrs);
    5314             :   }
    5315             :   else{
    5316             :     // Go ahead and get FluxStandard to make the ComponentList, since
    5317             :     // it knows what type of component to use. 
    5318             : 
    5319             :     // This is _a_ time.  It would be more accurate and safer, but
    5320             :     // slower, to use the weighted average of the times at which this
    5321             :     // source was observed, and to use the range of times in the
    5322             :     // estimate of the error introduced by using a single time.
    5323             :     //
    5324             :     // Obviously that would be overkill if the source does not vary.
    5325             :     //
    5326             :     /***
    5327             :     Double meantime = msc.time()(0);
    5328             :     meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    5329             :     MEpoch mtime(msc.timeMeas()(0));
    5330             :     mtime.set(Quantity(meantime, "s"));
    5331             :     ***/
    5332             :             
    5333           7 :     aveEpoch=mtime;
    5334             : 
    5335           7 :     foundSrc = fluxStd.computeCL(fieldName, mfreqs, mtime, fieldDir,
    5336             :                                  returnFluxes, returnFluxErrs,
    5337          14 :                                  tempCLs, ms_p->tableName()+"_setjy_");
    5338             :   }
    5339           7 :   if(!foundSrc){
    5340           0 :     if(standard == String("SOURCE")){
    5341             :       // *** THIS MODE IS NOT USED IN CURRENT SETJY ***
    5342             :       // dgoscha, NCSA, 02 May, 2002
    5343             :       // this else condtion is to handle the case where the user
    5344             :       // specifies standard='SOURCE' in the setjy argument.  This will
    5345             :       // then look into the SOURCE_MODEL column of the SOURCE subtable
    5346             :       // for a table-record entry that points to a component list with the
    5347             :       // model information in it.
    5348             : 
    5349             :       // Look in the SOURCE_MODEL column of the SOURCE subtable for 
    5350             :       // the name of the CL which contains the model.
    5351             : 
    5352             :       // First test to make sure the SOURCE_MODEL column exists.
    5353           0 :       if(ms_p->source().tableDesc().isColumn("SOURCE_MODEL")){
    5354           0 :         TableRecord modelRecord;
    5355           0 :         msc.source().sourceModel().get(0, modelRecord);
    5356             :         
    5357             :         // Get the name of the model component list from the table record
    5358             :         Table modelRecordTable = 
    5359           0 :           modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
    5360           0 :         String modelCLName = modelRecordTable.tableName();
    5361           0 :         modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
    5362             : 
    5363             :         // Now grab the flux from the model component list and use.
    5364           0 :         ComponentList modelCL = ComponentList(Path(modelCLName), true);
    5365           0 :         SkyComponent fluxComponent = modelCL.component(fldid);
    5366             : 
    5367             :         //fluxUsed = 0;
    5368           0 :         fluxUsed(0) = 0;
    5369             :         //fluxUsed = real(fluxComponent.flux().value());
    5370           0 :         fluxUsed(0) = real(fluxComponent.flux().value());
    5371           0 :         fluxScaleName = modelCLName;
    5372           0 :       }
    5373             :       else {
    5374             :         os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
    5375             :            << LogIO::SEVERE << "Continuing with the default, I = 1.0 Jy"
    5376           0 :            << LogIO::POST;
    5377             :         //fluxUsed = 0;
    5378           0 :         fluxUsed(0) = 0;
    5379             :         //fluxUsed(0) = 1.0;
    5380           0 :         fluxUsed(0)(0) = 1.0;
    5381             :       }
    5382             :     }
    5383             :     else {
    5384             :       // Source not found; use Stokes I=1.0 Jy for now
    5385             :       // (The flux standard already issued a complaint like this...)
    5386             :       // os << LogIO::WARN
    5387             :       //    << fieldName << " was not recognized by " << standard
    5388             :       //    << ".\nContinuing with the default, I = 1.0 Jy"
    5389             :       //    << LogIO::POST;
    5390             :       //fluxUsed = 0;
    5391           0 :       fluxUsed(0) = 0;
    5392             :       //fluxUsed(0) = 1.0;
    5393           0 :       fluxUsed(0)(0) = 1.0;
    5394           0 :       fluxScaleName = "default";
    5395             :     }
    5396             : 
    5397             :     // Currently, if !foundSrc, then the flux density is the same for all
    5398             :     // spws.
    5399             :     // Log the flux density found for this field.
    5400           0 :     os.output().width(12);
    5401           0 :     os << fieldName << "  ";
    5402           0 :     os.output().width(0);
    5403           0 :     os.output().precision(4);
    5404             :     /***
    5405             :     os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    5406             :     os << "Q=" << fluxUsed(1) << ", ";
    5407             :     os << "U=" << fluxUsed(2) << ", ";
    5408             :     os << "V=" << fluxUsed(3) << "] Jy, ";
    5409             :     ***/
    5410           0 :     os << LogIO::NORMAL << "[I=" << fluxUsed(0)(0) << ", "; // Loglevel INFO
    5411           0 :     os << "Q=" << fluxUsed(0)(1) << ", ";
    5412           0 :     os << "U=" << fluxUsed(0)(2) << ", ";
    5413           0 :     os << "V=" << fluxUsed(0)(3) << "] Jy @ ";
    5414           0 :     os << mfreqs(0)(0).getValue()<<"Hz, ";
    5415           0 :     os << ("(" + fluxScaleName + ")") << LogIO::POST;
    5416           0 :     writeHistory(os);
    5417             :   }  // End of if(!foundSrc).
    5418             :   else {
    5419             :     // Logging/History for foundSrc=true (moved from the im.setjy method)
    5420          44 :     for (uInt selspw=0; selspw<selToRawSpwIds.nelements(); selspw++) {
    5421          37 :       returnFluxes[selspw][0].value(fluxUsed[selspw]);
    5422             :       // Log flux density found for this field and spectral window
    5423          37 :       os.output().width(12);
    5424          37 :       os << fieldName;
    5425          37 :       os.output().width(2);
    5426          37 :       os << " (fld ind " << fldid << ") spw ";
    5427          37 :       os << selToRawSpwIds[selspw] << "  ";
    5428          37 :       os.output().width(0);
    5429          37 :       os.output().precision(5);
    5430          37 :       os << LogIO::NORMAL << "[I=" << fluxUsed(selspw)(0) << ", "; // Loglevel INFO
    5431          37 :       os << "Q=" << fluxUsed(selspw)(1) << ", ";
    5432          37 :       os << "U=" << fluxUsed(selspw)(2) << ", ";
    5433          37 :       os << "V=" << fluxUsed(selspw)(3) << "] Jy @ ";
    5434          37 :       os << mfreqs(selspw)(0).getValue()<<"Hz, ";
    5435          37 :       os << ("(" + fluxScaleName + ")") << LogIO::POST;
    5436          37 :       writeHistory(os);
    5437             :     } 
    5438             :   }
    5439           7 :   return foundSrc;
    5440           7 : }
    5441             : 
    5442             : //make componentlist(s) with user specified flux density
    5443           0 : void Imager::sjy_makeComponentList(LogIO& os, Vector<String>& tempCLs,
    5444             :                               Vector<Vector<Flux<Double> > >& returnFluxes,
    5445             :                               const Vector<Double>& fluxUsed, 
    5446             :                               const Vector<Int>& selToRawSpwIds, 
    5447             :                               const Vector<Vector<MFrequency> >& mfreqs,
    5448             :                               const String& fieldName,
    5449             :                               const MDirection& fieldDir, 
    5450             :                               const Vector<Double>& spix,
    5451             :                               const Vector<Double>& pipars,
    5452             :                               const Vector<Double>& papars,
    5453             :                               const Double& rotMeas,
    5454             :                               // circ pol parameters
    5455             :                               //const Vector<Double>& cppars,
    5456             :                               const MFrequency& reffreq,
    5457             :                               const MEpoch& mtime,
    5458             :                               const Int /*fldid*/)
    5459             : {
    5460             : 
    5461           0 :   for(uInt selspw = 0; selspw < selToRawSpwIds.nelements(); ++selspw){
    5462             :     // fluxUsed was supplied by the user instead of FluxStandard, so
    5463             :     // make a component list for it now, for use in ft.
    5464             : 
    5465             :     // if spix is a float/double and q,u fluxes not set or pipars and papars not
    5466             :     // set => SpectralIndex 
    5467             :     // if spix is a float/double and q,u fluxes is set but not pipars and papers
    5468             :     // => spectralindex
    5469             :     // if spix is a float/double and q,u fluxes and pipars and papars are set
    5470             :     // => tabular
    5471             :     // if spix is a vector but qu fluxes nor pipars and papers are not set 
    5472             :     // => tabular
    5473             :     // if spix is a vector => tabular form
    5474             :     //
    5475             :     // Set the component flux density
    5476           0 :     Flux<Double> fluxval;
    5477           0 :     Flux<Double> fluxerr;
    5478           0 :     fluxval.setValue(fluxUsed);
    5479             :     // Create a point component at the field center
    5480             :     // with the specified flux density
    5481             :     // - obviously this does not correct for solar objects...
    5482           0 :     PointShape point(fieldDir);
    5483             : 
    5484           0 :     Bool useTabularFlux(false);
    5485             :     //check if to use tabular form or SpectralIndex model
    5486           0 :     if ( spix.nelements() > 1 ) {
    5487           0 :       useTabularFlux=true; 
    5488             :     }
    5489             :     else {
    5490             :       //if (pipars.nelements() > 1 || papars.nelements() > 1 || rotMeas != 0.0) {
    5491           0 :       if (pipars.nelements() > 1 || papars.nelements() > 1 ) {
    5492           0 :         useTabularFlux=true;
    5493             :       }
    5494             :     }
    5495           0 :     SpectralIndex siModel;
    5496             :     //Vector<Double> iflux;
    5497             :     //Vector<Double> qflux;
    5498             :     //Vector<Double> uflux;
    5499           0 :     Vector<Flux<Double> > fluxvalvec; 
    5500           0 :     Bool gotQUFlux(false);
    5501           0 :     Bool useFluxAsIs(false);
    5502             :     // 
    5503           0 :     if(reffreq.getValue().getValue() > 0.0){
    5504             :       //original code uses first time of the data but shouldn't be using the same time as for
    5505             :       //FluxStandard::makeComponentList?
    5506             :       //MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
    5507           0 :       MeasFrame mFrame(mtime, mLocation_p, fieldDir);
    5508           0 :       MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
    5509           0 :       siModel.setRefFrequency(reffreq);
    5510             :       // if spix is not array of double,do this otherwise need to set flux densities by tabular... 
    5511             :       //
    5512           0 :       Int nchn = mfreqs[selspw].nelements(); 
    5513           0 :       fluxvalvec.resize(nchn);
    5514           0 :       Vector<Double> iflux(nchn);
    5515           0 :       Vector<Double> qflux(nchn);
    5516           0 :       Vector<Double> uflux(nchn);
    5517           0 :       Vector<Double> vflux(nchn,0.0);
    5518             :       // circular polarization fraction
    5519           0 :       Double circpolFraction=0.0;
    5520           0 :       if ( fluxUsed[0] !=0.0 && fluxUsed[3] != 0.0 ) {
    5521           0 :         circpolFraction = fluxUsed[3]/fluxUsed[0]; 
    5522             :       }
    5523             : 
    5524           0 :       if (spix.nelements()==1) {
    5525             :         //siModel.setIndex(spix[0]);
    5526           0 :         Vector<Double> stokesindex(4);
    5527           0 :         stokesindex[0]=spix[0];
    5528           0 :         stokesindex[1]=0.0;
    5529           0 :         stokesindex[2]=rotMeas!=0.0? rotMeas: 0.0;
    5530           0 :         stokesindex[3]=0.0;
    5531           0 :         siModel.setStokesIndex(stokesindex);
    5532             :         // still use iflux if q,u flux=0 but polindex and polangle is set
    5533           0 :         for (uInt ichn = 0; ichn < uInt(nchn); ichn++) { 
    5534           0 :           iflux[ichn] = fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][ichn]));
    5535             :         }
    5536           0 :       }
    5537             :       else {
    5538             :       // tabular case   
    5539           0 :         sjy_calciflux(mfreqs[selspw],reffreq,fluxUsed[0],spix,iflux);
    5540             :       }
    5541             :       // linear pol
    5542           0 :       Vector<Double> inpipars;
    5543           0 :       Vector<Double> inpapars;
    5544           0 :       if ( pipars.nelements() > 0 || papars.nelements() > 0 ) {
    5545           0 :         inpipars.resize(pipars.nelements());
    5546           0 :         inpipars=pipars;
    5547           0 :         inpapars.resize(papars.nelements());
    5548           0 :         inpapars=papars;
    5549             :       }
    5550             : 
    5551             :       // Either Q or U non-zero, so use them
    5552           0 :       if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0) {
    5553             :         // if Q U flux densities are given use that as 0th coefficient
    5554           0 :         Double pi0 = sqrt(fluxUsed[1] * fluxUsed[1] + fluxUsed[2] * fluxUsed[2]) / fluxUsed[0];
    5555           0 :         Double pa0 = 0.5 * atan2(fluxUsed[2],fluxUsed[1]);
    5556             :         os<<LogIO::DEBUG1<<"Polindex c0="<<pi0<<", polangle c0="<<pa0
    5557           0 :           <<" determined from input flux densities are used"<<LogIO::POST;
    5558           0 :         if ( pipars.nelements() == 0 || papars.nelements() == 0 ) {
    5559           0 :           inpipars.resize(1);
    5560           0 :           inpapars.resize(1);
    5561             :         }
    5562           0 :         inpipars[0] = pi0;
    5563           0 :         inpapars[0] = pa0;
    5564             :       }
    5565             :       //if (useTabularFlux) { 
    5566           0 :       if (inpipars.nelements()!=0 && inpapars.nelements()!=0) { 
    5567             :       //  cerr<<"running sjy_calcquflux...."<<endl;
    5568             :       //     - returns qflux and uflux
    5569           0 :         gotQUFlux = sjy_calcquflux(inpipars, inpapars, iflux, rotMeas, mfreqs[selspw], reffreq, qflux, uflux);
    5570             :       }
    5571           0 :       else if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0 || fluxUsed[3] != 0.0) {
    5572           0 :         gotQUFlux=true;
    5573           0 :         useFluxAsIs=true;
    5574             :       }
    5575             :         /***
    5576             :         if ( !useTabularFlux ) {
    5577             :           Vector<Double> stokesIndex(4);
    5578             :           stokesIndex[0] = index[0];
    5579             :           //need to translate polindex ...etc to stokesIndex[1,2] 
    5580             :           siModel.setStokesIndex(spix);
    5581             :         }
    5582             :         ***/ 
    5583           0 :       for (uInt ichn=0; ichn < iflux.nelements(); ichn++) {
    5584           0 :         if (!gotQUFlux) {
    5585           0 :           qflux[ichn] = 0.0; 
    5586           0 :           uflux[ichn] = 0.0;
    5587             :         } 
    5588           0 :         else if(useFluxAsIs) {
    5589           0 :           qflux[ichn] = fluxUsed[1];
    5590           0 :           uflux[ichn] = fluxUsed[2];
    5591           0 :           vflux[ichn] = fluxUsed[3];
    5592             :         }
    5593           0 :         if ( circpolFraction != 0.0) vflux[ichn] = iflux[ichn]*circpolFraction;
    5594           0 :         Flux<Double> iquvflux(iflux[ichn],qflux[ichn],uflux[ichn],vflux[ichn]);
    5595           0 :         fluxvalvec[ichn] = iquvflux; 
    5596           0 :       }
    5597           0 :       returnFluxes[selspw][0]=fluxvalvec[0];
    5598           0 :     }
    5599             :     else{
    5600           0 :       if(spix[0] != 0.0){            // If not the default, complain and quit.
    5601             :         os << LogIO::SEVERE
    5602             :            << "spix cannot be nonzero with reffreq = 0!"
    5603           0 :            << LogIO::POST;
    5604             :            //return false;
    5605             :       }
    5606           0 :       siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
    5607           0 :       siModel.setIndex(0.0);
    5608             :     }
    5609             :     // TODO: call tabular form method for full pol specification....
    5610             :     //
    5611             :     // No worries about varying fluxes or sizes here, so any time will do.
    5612           0 :     if ( useTabularFlux ) {
    5613           0 :       tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    5614             :                                                      mfreqs[selspw],
    5615             :                                                      mtime, fluxvalvec, point,
    5616           0 :                                                      ms_p->tableName() +
    5617           0 :                                                      "_setjy_spw" +
    5618           0 :                                                      String::toString(selspw) +
    5619           0 :                                                      "_");
    5620             :     }
    5621             :     else {
    5622             :     //if simodel is set use this 
    5623             :       //cerr<<"NON-Tabular makeComponentList..."<<endl;
    5624             :       //if (fluxval.value(1) ==0.0 && fluxval.value(2) == 0.0 && gotQUFlux) {
    5625             : 
    5626             :       // fluxval is @ thefreq, make sure proper freq is used 
    5627             :       // Note that refreq in siModel will be overriden by thefreq 
    5628           0 :       MFrequency thefreq = reffreq;
    5629           0 :       if ( gotQUFlux) {
    5630           0 :         fluxval=fluxvalvec[0]; 
    5631           0 :         thefreq=mfreqs[selspw][0];
    5632             :       }   
    5633           0 :       tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    5634             :                                  //                    mfreqs[selspw][0],
    5635             :                                                      thefreq,
    5636             :                                                      mtime, fluxval, point,
    5637             :                                                      siModel,
    5638             :     // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
    5639           0 :                                                      ms_p->tableName() +
    5640           0 :                                                      "_setjy_spw" +
    5641           0 :                                                      String::toString(selspw) +
    5642           0 :                                                      "_");
    5643           0 :     }
    5644           0 :   }
    5645           0 : }
    5646             : 
    5647             : // modified the input model image by regridding, scaling with a flux standard
    5648           0 : TempImage<Float>* Imager::sjy_prepImage(LogIO& os, FluxStandard& fluxStd,
    5649             :                                         Vector<Double>& fluxUsed, Vector<Double>& freqsOfScale, 
    5650             :                                         Vector<Double>& freqscale, const String& model,
    5651             :                                         const MSSpWindowColumns& spwcols,
    5652             :                                         //const Int rawspwid, const Bool chanDep,
    5653             :                                         const Vector<Int> rawspwids, const Bool chanDep,
    5654             :                                         const Vector<Vector<MFrequency> >& mfreqs,
    5655             :                                         //const uInt selspw, const String& fieldName,
    5656             :                                         const String& fieldName,
    5657             :                                         const MDirection& fieldDir,
    5658             :                                         const Unit& freqUnit,
    5659             :                                         const Vector<Double>& fluxdens,
    5660             :                                         const Bool precompute, 
    5661             :                                         //const Double spix,
    5662             :                                         const Vector<Double>& spix,
    5663             :                                         const MFrequency& reffreq,
    5664             :                                         const MEpoch& aveEpoch,
    5665             :                                         const Int fieldId)
    5666             : {
    5667           0 :   TempImage<Float>* tmodimage = NULL;
    5668             :   
    5669             :   Double freqMax, freqMin;
    5670           0 :   Vector<Vector<Int> >dummy;
    5671             :   // TT for MMS this may not work
    5672             :   //String msname=mssel_p->antenna().tableName();
    5673             :   //msname.erase(msname.length()-8);
    5674           0 :   String msname=ms_p->tableName();
    5675             :   //adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, String::toString(rawspwid));
    5676             :   // Get freqmin and freqmax in LSRK for the entire span of the selected spws
    5677           0 :   String selSpwsStr;
    5678           0 :   for (uInt ispw=0; ispw < rawspwids.nelements(); ispw++) {
    5679           0 :     if (selSpwsStr!="") selSpwsStr += ", ";
    5680           0 :     selSpwsStr += String::toString(rawspwids(ispw));
    5681             :   }
    5682           0 :   adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, selSpwsStr);
    5683             : 
    5684             :   // Find min channel width to increment to construct freqsofScale 
    5685           0 :   Double freqWidth = 0;
    5686             :   //
    5687           0 :   for (uInt ispw = 0; ispw<rawspwids.nelements(); ispw++) {
    5688           0 :     Vector<Double> freqWidths = spwcols.chanWidth()(rawspwids(ispw));
    5689             : 
    5690           0 :     Double minChanWidth = min(fabs(freqWidths));
    5691             :     // freqWidth init....
    5692           0 :     if (freqWidth == 0) 
    5693           0 :       freqWidth = minChanWidth;
    5694             :     else 
    5695           0 :       freqWidth = min(freqWidth,minChanWidth); 
    5696           0 :   }
    5697             :   
    5698             :   // ADDED for debug
    5699             :   //Int rawspwid = rawspwids[0];
    5700             :   //Vector<Double> freqArray = spwcols.chanFreq()(rawspwid);
    5701             :   //Int nchan=freqArray.shape()[0]   ;
    5702           0 :   Int nchan = Int(ceil(fabs(freqMax - freqMin)/freqWidth))+1;
    5703             :   //cerr<<"nchan="<<nchan<<" freqMax="<<freqMax<<" freqMin="<<freqMin<<" freqWidth="<<freqWidth<<endl; 
    5704             :   //Filling it with the LSRK values
    5705             :   // SetJyGridFT will trigger nearestNeighbour interpolation for nchan>=2
    5706           0 :   Vector<Double> freqArray(nchan);
    5707           0 :   if (nchan==1) {
    5708           0 :     freqArray[0] = freqMin;
    5709             :   }
    5710           0 :   else if (nchan==2) {
    5711           0 :     freqArray[0] = freqMin;
    5712           0 :     freqArray[1] = freqMax;
    5713             :   }
    5714           0 :   else if (nchan==3) {
    5715           0 :     freqArray[0] = freqMin - freqWidth;
    5716           0 :     freqArray[1] = freqMin;
    5717           0 :     freqArray[2] = freqMin + freqWidth;
    5718             :   }
    5719             :   else {
    5720           0 :     for (Int k =0;k < nchan; ++k){
    5721           0 :       freqArray[k]=freqMin+k*freqWidth;
    5722             :     }
    5723             :   }
    5724             :   //Vector<Double> freqInc = spwcols.chanWidth()(rawspwid);
    5725           0 :   Double medianFreq = median(freqArray);
    5726           0 :   freqsOfScale.resize();
    5727           0 :   freqscale.resize();
    5728             : 
    5729             :   // 2 bw channel extra
    5730             :   // UNCOMMENTED for debug
    5731             :   //freqWidth = fabs(freqMax - freqMin) + 2 * max(freqInc);
    5732           0 :   Matrix<Double> fluxUsedPerChan; // 4 rows nchan col ...will resize when needed
    5733             : 
    5734             :   // Set fluxUsedPerChan to the flux densities for each chan.
    5735           0 :   if(chanDep || (spix[0] != 0.0 && fluxdens[0] != 0.0)){
    5736           0 :     IPosition whichChan(1, 0);
    5737           0 :     Flux<Double> returnFlux;
    5738           0 :     Flux<Double> returnFluxErr;
    5739           0 :     Double reffreqInGHz = 1.0;
    5740             : 
    5741           0 :     Unit ghz("GHz");
    5742           0 :     if(!precompute)
    5743           0 :       reffreqInGHz = reffreq.get(ghz).getValue();
    5744             : 
    5745           0 :     fluxUsedPerChan.resize(4, freqArray.nelements());
    5746           0 :     for(uInt k = 0; k < freqArray.nelements(); ++k){
    5747           0 :       whichChan[0] = k;
    5748           0 :       if(precompute){
    5749             :         //fluxStd.compute(fieldName, spwcols.chanFreqMeas()(rawspwid)(whichChan),
    5750             :         //                returnFlux, returnFluxErr);
    5751           0 :         fluxStd.compute(fieldName, fieldDir, MFrequency(Quantity(freqArray[k], "Hz"), MFrequency::LSRK),
    5752             :                         aveEpoch, returnFlux, returnFluxErr);
    5753           0 :         returnFlux.value(fluxUsed);
    5754             :       }
    5755             :       else{
    5756             :         // spix: index = c0 + c1*log(f/fo) + c2*log(f/fo)^2+ ... 
    5757             :         //             = log(So) + alpha*log(f/fo) + curv1*log(f/f0)^2 ....
    5758           0 :         uInt order = spix.nelements();
    5759           0 :         Polynomial<Double> spixfunc(order);
    5760           0 :         Vector<Double> coeffs(order+1);
    5761           0 :         coeffs[0] = log10(fluxdens[0]); 
    5762           0 :         for (uInt ispix = 1; ispix < order+1; ispix++) {
    5763           0 :           coeffs[ispix] = spix[ispix-1];
    5764             :         }
    5765           0 :         spixfunc.setCoefficients(coeffs);
    5766             : 
    5767             :         //Double freq = spwcols.chanFreqMeas()(rawspwids(0))(whichChan).get(ghz).getValue();
    5768             :         //Double specfac = pow(freq / reffreqInGHz, spix);
    5769             :         // TT mod-06/11/14
    5770             :         // freqArray may or may not be exactly match with data chan frequencies
    5771             :         // so probably make sense to use  freqArray instead 
    5772             :         //Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spix);
    5773           0 :         Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spixfunc(freqArray[k]));
    5774             :         
    5775           0 :         for(uInt stokes = 0; stokes < 4; ++stokes)
    5776           0 :           fluxUsed[stokes] = fluxdens[stokes] * specfac;
    5777           0 :       }
    5778           0 :       fluxUsedPerChan.column(k) = fluxUsed;
    5779             :     }
    5780           0 :   }
    5781           0 :   PagedImage<Float> modimage(model);
    5782           0 :   modimage.table().unmarkForDelete();
    5783           0 :   IPosition imshape = modimage.shape();
    5784           0 :   CoordinateSystem csys(modimage.coordinates());
    5785           0 :   Int freqAxis = CoordinateUtil::findSpectralAxis(csys);
    5786           0 :   Vector<Stokes::StokesTypes> whichPols;
    5787           0 :   Int polAxis = CoordinateUtil::findStokesAxis(whichPols, csys);
    5788           0 :   Int icoord = csys.findCoordinate(Coordinate::SPECTRAL);
    5789           0 :   SpectralCoordinate spcsys = csys.spectralCoordinate(icoord);
    5790           0 :   MEpoch elEpoch; MDirection elDir; MFrequency::Types elTypes; MPosition elPos;
    5791           0 :   spcsys.getReferenceConversion(elTypes, elEpoch, elPos, elDir);
    5792           0 :   spcsys.setReferenceConversion(MFrequency::LSRK, aveEpoch, elPos, elDir);  
    5793           0 :   spcsys.setReferenceValue(Vector<Double>(1, medianFreq));
    5794           0 :   spcsys.setReferencePixel(Vector<Double>(1, 0.0));
    5795           0 :   spcsys.setWorldAxisUnits(Vector<String>(1,
    5796             :                                           //mfreqs[selspw][0].getUnit().getName()));
    5797           0 :                                           mfreqs[0][0].getUnit().getName()));
    5798             :   //make image freq. width wide enough for FTMachine to work correctly 
    5799           0 :   spcsys.setIncrement(Vector<Double>(1, 2*fabs(freqMax-freqMin)));
    5800             :   // make a cube model if the model is a cube already
    5801           0 :   if(modimage.shape()(freqAxis) >1){
    5802             :     // model image is a cube...just regrid it then
    5803             :     os << LogIO::NORMAL
    5804             :        << "The model image is a cube, so it is being regridded but without scaling the flux density."
    5805           0 :        << LogIO::POST;
    5806           0 :     spcsys = SpectralCoordinate(
    5807             :                                 //MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
    5808           0 :                                 MFrequency::castType(mfreqs[0][0].getRef().getType()),
    5809           0 :                                 freqArray, spcsys.restFrequency());
    5810           0 :     imshape(freqAxis)=freqArray.nelements();
    5811           0 :     csys.replaceCoordinate(spcsys, icoord);
    5812           0 :     tmodimage = new TempImage<Float>(imshape, csys);
    5813           0 :     sjy_regridCubeChans(tmodimage, modimage, freqAxis);
    5814             :     //return from here itself
    5815           0 :     return tmodimage;
    5816             :   }
    5817             :  
    5818           0 :   if(chanDep && (fluxUsedPerChan.ncolumn() > 1)){
    5819             :     //spcsys = SpectralCoordinate(
    5820             :     //                  MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
    5821             :     //                            freqArray, spcsys.restFrequency());
    5822           0 :     if(freqAxis < 2 || polAxis < 2)
    5823           0 :       throw(AipsError("Cannot setjy with a model that has spectral or stokes axis before direction axes.\n Please reorder the axes of the image"));
    5824           0 :     freqscale.resize(freqArray.nelements());
    5825           0 :     freqsOfScale.resize(freqArray.nelements());
    5826           0 :     freqsOfScale=freqArray;
    5827           0 :     freqscale=1.0;
    5828           0 :     if(freqAxis == 2) {//pol and freq are swapped
    5829           0 :       imshape[2]=imshape[3];
    5830           0 :       imshape[3] = 1;      
    5831           0 :       Vector<Int> trans(4);
    5832           0 :       trans[0] = 0; trans[1] = 1; trans[2] = 3; trans[3] = 2;
    5833           0 :       csys.transpose(trans, trans);
    5834           0 :     }
    5835             :     else{
    5836           0 :       imshape(freqAxis) = 1;
    5837             :     }
    5838             :   } 
    5839           0 :   csys.replaceCoordinate(spcsys, icoord);
    5840           0 :   tmodimage = new TempImage<Float>(imshape, csys);
    5841           0 :   IPosition blcin(modimage.shape().nelements(), 0);
    5842           0 :   IPosition trcin=modimage.shape()-1;
    5843           0 :   IPosition blcout(imshape.nelements(), 0); 
    5844           0 :   IPosition trcout=imshape-1;
    5845             :   
    5846           0 :   for (uInt ipol=0; ipol < imshape[2]; ++ipol){
    5847           0 :     blcin[polAxis]=ipol;
    5848           0 :     trcin[polAxis]=ipol;
    5849           0 :     blcout[2]=ipol;
    5850           0 :     trcout[2]=ipol;
    5851           0 :     Slicer slin(blcin, trcin, Slicer::endIsLast);
    5852           0 :     Slicer slout(blcout, trcout, Slicer::endIsLast);
    5853           0 :     SubImage<Float> subimout(*tmodimage, slout, true);
    5854           0 :     SubImage<Float> subimin(modimage, slin, false);
    5855           0 :     subimout.copyData(subimin);
    5856           0 :   }
    5857             :   os << LogIO::DEBUG1
    5858             :      << "freqUnit.getName() = " << freqUnit.getName()
    5859           0 :      << LogIO::POST;
    5860             :   os << LogIO::DEBUG1
    5861             :      //<< "mfreqs[selspw].get(freqUnit).getValue() = "
    5862             :      //<< mfreqs[selspw][0].get(freqUnit).getValue()
    5863             :      << "mfreqs[0][0].get(freqUnit).getValue() = "
    5864           0 :      << mfreqs[0][0].get(freqUnit).getValue()
    5865           0 :      << LogIO::POST;
    5866             : 
    5867             :   // Check direction consistency (reported in log message below)
    5868           0 :   String err;
    5869           0 :   if(!CoordinateUtil::setDirectionConversion(err, csys, fieldDir.getRefString())){
    5870             :     os << "LogIO::WARN " 
    5871             :        << "Could not set direction conversion between flux image and " 
    5872           0 :        << fieldDir.getRefString() << LogIO::POST;
    5873             :   }
    5874           0 :   Int dircoord(csys.findCoordinate(Coordinate::DIRECTION));
    5875           0 :   DirectionCoordinate dircsys=csys.directionCoordinate(dircoord);
    5876           0 :   MVDirection mvd;
    5877           0 :   dircsys.toWorld(mvd,dircsys.referencePixel());
    5878           0 :   Double sep = fieldDir.getValue().separation(mvd,"\"").getValue();
    5879             :           
    5880             :   //Apply radius limit for 3C286,3C48,3C147 and 3C138
    5881           0 :   sjy_setRadiusLimit(tmodimage, modimage, model, dircsys);
    5882             : 
    5883             :   // for debugging
    5884             :   //PagedImage<Float> checkIm(TiledShape(modimage.shape(),
    5885             :   //                                        modimage.niceCursorShape()),
    5886             :   //                                  modimage.coordinates(),
    5887             :   //                                  "checkImage");
    5888             :   //checkIm.copyData((LatticeExpr<Float>)(*tmodimage));
    5889             : 
    5890           0 :   if(fluxdens[0] != 0.0){
    5891           0 :     Float sumI = 1.0;
    5892             : 
    5893             :     // ?: can't handle the different return types.
    5894           0 :     if(whichPols.nelements() > 1)
    5895             :       //sumI = sum(ImagePolarimetry(modimage).stokesI()).getFloat();
    5896           0 :       sumI = sum(ImagePolarimetry(*tmodimage).stokesI()).getFloat();
    5897             :     else
    5898             :       //sumI = sum(modimage).getFloat();
    5899           0 :       sumI = sum(*tmodimage).getFloat();
    5900             : 
    5901             :     //if(selspw == 0)
    5902             :       os << LogIO::NORMAL
    5903           0 :          << "Using model image " << modimage.name() // Loglevel INFO
    5904           0 :          << LogIO::POST;
    5905             : 
    5906             :     // scale the image
    5907           0 :     if(freqscale.nelements() > 0){
    5908           0 :       Int midchan = freqArray.nelements()/2;
    5909           0 :       if(modimage.shape()(freqAxis) == 1){
    5910             :         //     IPosition blc(imshape.nelements(), 0);
    5911             :         //IPosition trc = imshape - 1;
    5912             :         os << LogIO::NORMAL
    5913             :            //<< "Scaling spw " << selspw << "'s model image by channel to I = " 
    5914           0 :            << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image by channel to  I = " 
    5915           0 :            << fluxUsedPerChan.row(0)(0)<<", "
    5916           0 :            << fluxUsedPerChan.row(0)(midchan)<<", "
    5917           0 :            << fluxUsedPerChan.row(0)(nchan-1)
    5918             :            << " Jy @("
    5919           0 :            << freqArray(0)<<", "
    5920           0 :            << freqArray(midchan)<<", "
    5921           0 :            << freqArray(nchan-1)
    5922             :            <<")Hz (LSRK) for visibility prediction (a few representative values are shown)."
    5923           0 :            << LogIO::POST;
    5924           0 :         writeHistory(os);
    5925           0 :         for(uInt k = 0; k < fluxUsedPerChan.ncolumn(); ++k){
    5926           0 :           freqscale[k] = fluxUsedPerChan.column(k)(0)/sumI;
    5927             :           //blc[3] = k;
    5928             :           //trc[3] = k;
    5929             :           //Slicer sl(blc, trc, Slicer::endIsLast);
    5930             :           //SubImage<Float> subim(*tmodimage, sl, true);
    5931             :           //subim.copyData((LatticeExpr<Float>)(modimage*scale));
    5932             :         }
    5933             :         // for debug
    5934             :         //cerr<<"freqscale="<<freqscale<<endl;
    5935             :         //cerr<<"freqsOfScale="<<freqsOfScale<<endl;
    5936             :       }
    5937             :     }
    5938             :     else{
    5939             :       // Scale factor
    5940           0 :       Float scale = fluxUsed[0] / sumI;
    5941             :       //for addition of sjy_setRadiusLimit
    5942             :       //tmodimage->copyData( (LatticeExpr<Float>)(modimage * scale) ); 
    5943           0 :       tmodimage->copyData( (LatticeExpr<Float>)(*tmodimage * scale) ); 
    5944             :       os << LogIO::NORMAL
    5945             :      //    << "Scaling spw " << selspw << "'s model image to I = "
    5946           0 :          << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image to I = "
    5947           0 :          << fluxUsed[0] // Loglevel INFO
    5948             :          << " Jy @ "
    5949             :          //<< mfreqs[0][0].getValue()
    5950           0 :          << freqArray(0) 
    5951             :          << "Hz (LSRK) for visibility prediction."
    5952           0 :          << LogIO::POST;
    5953           0 :       writeHistory(os);
    5954             :     }
    5955             :   }
    5956             :   else{
    5957             :     os << LogIO::NORMAL                                  // Loglevel INFO
    5958             :  << "Using the model image's original unscaled flux density for visibility prediction."
    5959           0 :        << LogIO::POST;
    5960           0 :     writeHistory(os);
    5961             :     // included in sjy_setRadiusLimit
    5962             :     //tmodimage->copyData( (LatticeExpr<Float>)(modimage) );
    5963             :   }
    5964             :             
    5965             :   //if(selspw == 0){
    5966             :     os << LogIO::NORMAL // Loglevel INFO
    5967             :        << "The model image's reference pixel is " << sep 
    5968             :        << " arcsec from " << fieldName << "'s phase center."
    5969           0 :        << LogIO::POST;
    5970           0 :     writeHistory(os);
    5971             :   //}
    5972             : 
    5973           0 :   return tmodimage;
    5974           0 : }
    5975             : 
    5976           0 : Bool Imager::sjy_regridCubeChans(TempImage<Float>* tmodimage,
    5977             :                                  PagedImage<Float>& modimage, Int freqAxis)
    5978             : {
    5979           0 :   if(freqAxis != 3)
    5980           0 :     throw(AipsError("Cannot setjy with a cube model that does not have the spectral axis as the last one.\n Please reorder the axes of the image"));
    5981           0 :   ImageRegrid<Float> ir;
    5982           0 :   IPosition axes(1, freqAxis);   // regrid the spectral only
    5983           0 :   ir.regrid(*tmodimage, Interpolate2D::LINEAR, axes, modimage);
    5984           0 :   return true;
    5985           0 : }
    5986             : 
    5987           0 : Bool Imager::sjy_setRadiusLimit(TempImage<Float>* tmodimage,
    5988             :                                 PagedImage<Float>& modimage, const String& model, DirectionCoordinate& dircsys)
    5989             : {
    5990           0 :   Path path(model);
    5991           0 :   String basename=path.baseName();
    5992             :   Float arad;
    5993             :   // radius limit in arcsec from AIPS
    5994           0 :   if (basename.find("3C286")==0) {
    5995           0 :       arad=3.0;
    5996             :   }
    5997           0 :   else if (basename.find("3C48")==0) {
    5998           0 :       arad=0.95;
    5999             :   }
    6000           0 :   else if (basename.find("3C147")==0) {
    6001           0 :       arad=0.85;
    6002             :   }
    6003           0 :   else if (basename.find("3C138")==0) {
    6004           0 :       arad=0.75;
    6005             :   }
    6006             :   else {
    6007           0 :       arad=0;
    6008           0 :       tmodimage->copyData(modimage);
    6009           0 :       return true;
    6010             :   }
    6011             :   try {
    6012           0 :     Quantity qrad(arad,"arcsec");
    6013           0 :     Float prad=Float(qrad.get(Unit("rad")).getValue()/abs(dircsys.increment()(0)));
    6014           0 :     Float radius = (prad >0.5 ? prad: 0.5);
    6015             :     //Add current ms name to avoid file access clash for MMS processing
    6016           0 :     String tempmaskname=ms_p->tableName()+"__tmp_mask_setjy_radiuslimit";
    6017           0 :     PagedImage<Float> maskImage(TiledShape(modimage.shape(),
    6018           0 :                                            modimage.niceCursorShape()),
    6019           0 :                                 modimage.coordinates(), tempmaskname);
    6020           0 :     maskImage.table().markForDelete();
    6021           0 :     Matrix<Float> circ(1,3);
    6022           0 :     Record *imrec=0;
    6023           0 :     Matrix<Quantity> blctrcs;
    6024           0 :     circ(0,0)=radius;
    6025           0 :     circ(0,1)=dircsys.referencePixel()(0);
    6026           0 :     circ(0,2)=dircsys.referencePixel()(1);
    6027           0 :     Imager::regionToImageMask(tempmaskname,imrec,blctrcs,circ,1.0);
    6028           0 :     PagedImage<Float> tmpmask(tempmaskname);
    6029           0 :     tmpmask.table().markForDelete();
    6030           0 :     tmodimage->copyData( (LatticeExpr<Float>)(tmpmask*modimage));
    6031           0 :   }
    6032           0 :   catch (...) {
    6033           0 :     return false;
    6034           0 :   }
    6035           0 :   return true;
    6036           0 : }
    6037             : 
    6038           0 : Bool Imager::sjy_calciflux(const Vector<MFrequency>& freqs, const MFrequency& reffreq, 
    6039             :                            const Double refflux, const Vector<Double>& vspix, Vector<Double>& iflux)
    6040             : {
    6041             :   try {
    6042             :     // assume polynomical is log(S) = c0 + alpha*log(f/fo) + curv1*log(f/fo)^2+
    6043             :     // vspix should contains [alpha, curv1, etc..] and c0 is calculated from refflux 
    6044           0 :     uInt porder = vspix.nelements();
    6045           0 :     Polynomial<Double> lf(porder);
    6046           0 :     Vector<Double> coeffs(porder+1);
    6047           0 :     coeffs[0] = log10(refflux);
    6048           0 :     for (uInt i = 1; i < vspix.nelements()+1; i++ ) {
    6049           0 :       coeffs[i] = vspix[i-1];
    6050             :     }
    6051           0 :     lf.setCoefficients(coeffs);
    6052           0 :     Int nf = freqs.nelements();
    6053           0 :     iflux.resize(nf);
    6054           0 :     Unit frequnit("GHz");
    6055           0 :     Double reffreqval = reffreq.get(frequnit).getValue();
    6056           0 :     for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
    6057           0 :       iflux[cfidx] = pow(10.0,lf(log10(freqs[cfidx].get(frequnit).getValue()/reffreqval))); 
    6058             :     }
    6059           0 :   }
    6060           0 :   catch (...) {
    6061           0 :     return false;
    6062           0 :   } 
    6063           0 :   return true; 
    6064             : }
    6065             : 
    6066           0 : Bool Imager::sjy_calcquflux(const Vector<Double>& pipars, const Vector<Double>& papars,
    6067             :                             const Vector<Double>& iflux, const Double rotMeas,
    6068             :                             const Vector<MFrequency>& freqs, 
    6069             :                             const MFrequency& reffreq, Vector<Double>& qflux,
    6070             :                             Vector<Double>& uflux)
    6071             : {
    6072             : 
    6073             :   try {
    6074           0 :     Int nf = freqs.nelements();
    6075             :     //polindex
    6076             :     // of the form, pi_o + c1*(f-fo)/fo + c2*(f-fo)/fo
    6077           0 :     Polynomial<Double> pipoly(pipars.nelements());
    6078           0 :     pipoly.setCoefficients(pipars);
    6079             :     //pangle
    6080           0 :     Polynomial<Double> papoly(papars.nelements());
    6081           0 :     papoly.setCoefficients(papars);
    6082           0 :     qflux.resize(nf);
    6083           0 :     uflux.resize(nf);
    6084           0 :     Unit ghz("Hz"); 
    6085           0 :     Double f0 = reffreq.get(ghz).getValue();
    6086             : 
    6087           0 :     for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
    6088           0 :       Double f = freqs[cfidx].get(ghz).getValue();
    6089           0 :       Double ipi = pipoly((f-f0)/f0);
    6090           0 :       Double ipa = papoly((f-f0)/f0);
    6091           0 :       Double iiflux = iflux[cfidx];
    6092           0 :       Double qfluxval = ipi * iiflux * cos(2.0*ipa);
    6093           0 :       Double ufluxval = ipi * iiflux * sin(2.0*ipa);
    6094             :       //debug
    6095             :       //if (cfidx<10) cerr<<"sjy_calcquflux:: poli="<<ipi<<" pola="<<ipa<<" qflux="<<qfluxval<<" uflux="<<ufluxval<<endl;
    6096           0 :       if (rotMeas!=0.0 ) {
    6097           0 :         Double rotangle = 2*rotMeas * C::c * C::c * (f0*f0-f*f)/(f*f*f0*f0);
    6098             :         //if (cfidx<10) cerr<<"rotangle="<<rotangle<<endl;
    6099           0 :         qflux[cfidx] = qfluxval*cos(rotangle) - ufluxval*sin(rotangle);
    6100           0 :         uflux[cfidx] = qfluxval*sin(rotangle) + ufluxval*cos(rotangle); 
    6101             :       }
    6102             :       else { 
    6103           0 :         qflux[cfidx] = qfluxval; 
    6104           0 :         uflux[cfidx] = ufluxval; 
    6105             :       }
    6106             :       //if (cfidx<10) cerr<<"uflux/qflux["<<cfidx<<"]="<<uflux[cfidx]/qflux[cfidx]<<endl;
    6107             :     }
    6108           0 :   }
    6109           0 :   catch (...) {
    6110           0 :     return false;
    6111           0 :   }
    6112           0 :   return true;
    6113             : }
    6114             : 
    6115             : 
    6116           0 : Bool Imager::clone(const String& imageName, const String& newImageName)
    6117             : {
    6118             :   //if(!valid()) return false;
    6119             :   // This is not needed if(!assertDefinedImageParameters()) return false;
    6120           0 :   LogIO os(LogOrigin("imager", "clone()", WHERE));
    6121             :   try {
    6122           0 :     PagedImage<Float> oldImage(imageName);
    6123           0 :     PagedImage<Float> newImage(TiledShape(oldImage.shape(), 
    6124           0 :                                           oldImage.niceCursorShape()), oldImage.coordinates(),
    6125           0 :                                newImageName);
    6126           0 :     newImage.set(0.0);
    6127           0 :     newImage.table().flush(true, true);
    6128           0 :   } catch (AipsError x) {
    6129           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6130           0 :     return false;
    6131           0 :   } 
    6132           0 :   return true;
    6133           0 : }
    6134             : 
    6135             : // Make an empty image
    6136           0 : Bool Imager::make(const String& model)
    6137             : {
    6138             : 
    6139           0 :   if(!valid())
    6140             :     {
    6141           0 :       return false;
    6142             :     }
    6143           0 :   LogIO os(LogOrigin("imager", "make()", WHERE));
    6144             :   
    6145           0 :   this->lock();
    6146             :   try {
    6147           0 :     if(!assertDefinedImageParameters())
    6148             :       {
    6149           0 :         return false;
    6150             :       }
    6151             :     
    6152             :     // Make an image with the required shape and coordinates
    6153           0 :     String modelName(model);
    6154           0 :     if(modelName=="") modelName=imageName()+".model";
    6155             :     os << LogIO::DEBUG1
    6156           0 :        << "Making empty image: " << modelName << LogIO::POST;
    6157             :     
    6158           0 :     removeTable(modelName);
    6159           0 :     CoordinateSystem coords;
    6160             :     //if(!imagecoordinates(coords, false)) 
    6161           0 :     if(!imagecoordinates2(coords, false)) 
    6162             :       {
    6163           0 :         this->unlock();
    6164           0 :         return false;
    6165             :       }
    6166           0 :     this->makeEmptyImage(coords, modelName, fieldid_p);
    6167           0 :     this->unlock();
    6168             :     
    6169           0 :     return true;
    6170           0 :   } catch (AipsError x) {
    6171           0 :     this->unlock();
    6172           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6173             : 
    6174           0 :     return false;    
    6175             : 
    6176           0 :   } 
    6177             :   this->unlock();
    6178             : 
    6179             :   return true;
    6180           0 : }
    6181             : 
    6182             : // Fit the psf. If psf is blank then make the psf first.
    6183           0 : Bool Imager::fitpsf(const String& psf, ImageBeamSet& mbeam) {
    6184             : 
    6185           0 :   if(!valid()) 
    6186             :     {
    6187           0 :       return false;
    6188             :     }
    6189           0 :   LogIO os(LogOrigin("imager", "fitpsf()", WHERE));
    6190             :   
    6191           0 :   this->lock();
    6192             :   try {
    6193           0 :     if(!assertDefinedImageParameters()) 
    6194             :       {
    6195           0 :         this->unlock();
    6196           0 :         return false;
    6197             :       }
    6198             :     
    6199           0 :     os << LogIO::NORMAL << "Fitting to psf" << LogIO::POST; // Loglevel PROGRESS
    6200             :     
    6201           0 :     String lpsf; lpsf=psf;
    6202           0 :     if(lpsf=="") {
    6203           0 :       lpsf=imageName()+".psf";
    6204           0 :       makeimage("psf", lpsf);
    6205             :     }
    6206             : 
    6207           0 :     if(!Table::isReadable(lpsf)) {
    6208           0 :       this->unlock();
    6209             :       os << LogIO::SEVERE << "PSF image " << lpsf << " does not exist"
    6210           0 :          << LogIO::POST;
    6211             : 
    6212           0 :       return false;
    6213             :     }
    6214             : 
    6215           0 :     PagedImage<Float> psfImage(lpsf);
    6216           0 :     StokesImageUtil::FitGaussianPSF(psfImage, mbeam);
    6217           0 :     beam_p = mbeam;
    6218           0 :     beamValid_p=true;
    6219             :     
    6220           0 :     GaussianBeam elbeam=beam_p(0,0);
    6221             :     os << LogIO::NORMAL // Loglevel INFO
    6222             :        << "  Beam fit: " << elbeam.getMajor("arcsec") << " by "
    6223             :        << elbeam.getMinor("arcsec") << " (arcsec) at pa "
    6224           0 :        << elbeam.getPA(Unit("deg")) << " (deg) " << endl;
    6225             : 
    6226           0 :     this->unlock();
    6227             :     
    6228           0 :     return true;
    6229           0 :   } catch (AipsError x) {
    6230           0 :     this->unlock();
    6231           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6232             : 
    6233           0 :      return false;
    6234           0 :   } 
    6235             :   this->unlock();
    6236             : 
    6237             :   return true;
    6238           0 : }
    6239             : 
    6240             : 
    6241           0 : Bool Imager::setscales(const String& scaleMethod,
    6242             :                             const Int inscales,
    6243             :                             const Vector<Float>& userScaleSizes)
    6244             : {
    6245           0 :   scaleMethod_p = scaleMethod;
    6246           0 :   userScaleSizes_p.resize(userScaleSizes.nelements());
    6247           0 :   userScaleSizes_p = userScaleSizes;
    6248           0 :   if (scaleMethod_p == "uservector") {
    6249           0 :     nscales_p =  userScaleSizes.nelements();
    6250             :   } else {
    6251           0 :     nscales_p = inscales;
    6252             :   }
    6253             :   //Force the creation of a new sm_p with the new scales
    6254           0 :   destroySkyEquation();
    6255           0 :   scaleInfoValid_p = true;  
    6256           0 :   return true;
    6257             : };
    6258             : 
    6259           0 : Bool Imager::setSmallScaleBias(const Float inbias)
    6260             : { 
    6261           0 :   smallScaleBias_p = inbias;
    6262           0 :   return true;
    6263             : }
    6264             : 
    6265             : // Added for wb algo.
    6266           0 : Bool Imager::settaylorterms(const Int intaylor,const Double inreffreq)
    6267             : {
    6268           0 :   ntaylor_p = intaylor;
    6269           0 :   reffreq_p = inreffreq;
    6270           0 :   return true;
    6271             : };
    6272             : 
    6273             : // Set the beam
    6274           0 : Bool Imager::setbeam(const ImageBeamSet& mbeam)
    6275             : {
    6276           0 :   if(!valid()) return false;
    6277             :   
    6278           0 :   LogIO os(LogOrigin("imager", "setbeam()", WHERE));
    6279           0 :   beam_p = ImageBeamSet(mbeam);
    6280           0 :   beamValid_p=true;
    6281             :     
    6282           0 :   return true;
    6283           0 : }
    6284             : 
    6285             : // Plot the uv plane
    6286           0 : Bool Imager::plotuv(const Bool rotate) 
    6287             : {
    6288             : 
    6289           0 :   if(!valid()) return false;
    6290             :   
    6291           0 :   LogIO os(LogOrigin("imager", "plotuv()", WHERE));
    6292             :   
    6293           0 :   this->lock();
    6294             :   try {
    6295             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6296           0 :        << "Plotting uv coverage for currently selected data" << LogIO::POST;
    6297             :     
    6298           0 :     ROVisIter& vi(*rvi_p);
    6299           0 :     VisBuffer vb(vi);
    6300             :     
    6301           0 :     uInt nVis = count_visibilities(rvi_p, true, true);
    6302             :     
    6303           0 :     if(nVis==0) {
    6304           0 :       this->unlock();
    6305           0 :       os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
    6306           0 :       return false;
    6307             :     }
    6308             :     
    6309           0 :     if(rotate) {
    6310             :       os << LogIO::NORMAL // Loglevel INFO
    6311           0 :          << "UVW will be rotated to specified phase center" << LogIO::POST;    
    6312             :     }
    6313             :     
    6314             :     
    6315           0 :     Vector<Float> u(nVis); u=0.0;
    6316           0 :     Vector<Float> v(nVis); v=0.0;
    6317           0 :     Vector<Float> uRotated(nVis); uRotated=0.0;
    6318           0 :     Vector<Float> vRotated(nVis); vRotated=0.0;
    6319           0 :     Float maxAbsUV=0.0;
    6320             :     
    6321           0 :     Int iVis=0;
    6322           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6323           0 :       for (vi.origin();vi.more();vi++) {
    6324           0 :         Int nRow=vb.nRow();
    6325           0 :         Int nChan=vb.nChannel();
    6326           0 :         Vector<Double> uvwRotated(3);
    6327           0 :         MeasFrame mFrame((MEpoch(Quantity(vb.time()(0), "s"))), mLocation_p);
    6328           0 :         UVWMachine uvwMachine(phaseCenter_p, vb.phaseCenter(), mFrame);
    6329           0 :         for (Int row=0; row<nRow; ++row) {
    6330           0 :           if(rotate) {
    6331           0 :             for (Int dim=0;dim<3;++dim) {
    6332           0 :               uvwRotated(dim)=vb.uvw()(row)(dim);
    6333             :             }
    6334           0 :             uvwMachine.convertUVW(uvwRotated);
    6335             :           }
    6336             :           
    6337           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6338           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6339           0 :               Float f=vb.frequency()(chn)/C::c;
    6340           0 :               u(iVis)=vb.uvw()(row)(0)*f;
    6341           0 :               v(iVis)=vb.uvw()(row)(1)*f;
    6342           0 :               if(abs(u(iVis))>maxAbsUV) maxAbsUV=abs(u(iVis));
    6343           0 :               if(abs(v(iVis))>maxAbsUV) maxAbsUV=abs(v(iVis));
    6344           0 :               if(rotate) {
    6345           0 :                 uRotated(iVis)=uvwRotated(0)*f;
    6346           0 :                 vRotated(iVis)=uvwRotated(1)*f;
    6347           0 :                 if(abs(uRotated(iVis))>maxAbsUV) maxAbsUV=abs(uRotated(iVis));
    6348           0 :                 if(abs(vRotated(iVis))>maxAbsUV) maxAbsUV=abs(vRotated(iVis));
    6349             :               }
    6350           0 :               ++iVis;
    6351             :             }
    6352             :           }
    6353             :         }
    6354           0 :       }
    6355             :     }
    6356             :     
    6357           0 :     if(maxAbsUV==0.0) {
    6358           0 :       this->unlock();
    6359           0 :       os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6360           0 :       return false;
    6361             :     }
    6362             :     else {
    6363           0 :       Quantity cell(0.5/maxAbsUV, "rad");
    6364             :       os << LogIO::NORMAL // Loglevel INFO
    6365           0 :          << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
    6366             :       os << LogIO::NORMAL // Loglevel INFO
    6367           0 :          << "Recommended cell size < " << cell.get("arcsec").getValue()
    6368           0 :          << " arcsec" << LogIO::POST;
    6369           0 :     }
    6370             :     
    6371             :    
    6372           0 :     return false;
    6373             : 
    6374             :     this->unlock();
    6375             :   
    6376           0 :   } 
    6377           0 :   catch (AipsError x) {
    6378           0 :     this->unlock();
    6379           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6380           0 :     return false;
    6381             :     
    6382           0 :   } 
    6383           0 :   catch (...) {
    6384           0 :     this->unlock();  
    6385           0 :   } 
    6386           0 :   this->unlock();
    6387             :   
    6388             :   
    6389             : 
    6390           0 :   return true;
    6391           0 : }
    6392             : 
    6393             : // Plot the visibilities
    6394           0 : Bool Imager::plotvis(const String& type, const Int increment) 
    6395             : {
    6396             : 
    6397           0 :   if(!valid()) return false;
    6398           0 :   LogIO os(LogOrigin("imager", "plotvis()", WHERE));
    6399             :   
    6400           0 :   this->lock();
    6401             :   try {
    6402             :     
    6403             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6404             :        << "Plotting Stokes I visibility for currently selected data"
    6405           0 :        << LogIO::POST;
    6406             :     
    6407             :     
    6408           0 :     MSColumns msc(*mssel_p);
    6409           0 :     Bool hasCorrected=!(msc.correctedData().isNull());
    6410           0 :     Bool hasModel= true; //with virtual model data service model data is always there
    6411             :     //why bother if it is not requested
    6412           0 :     if(!((type == "all") || (type=="model") || (type == "residual")))
    6413           0 :       hasModel=false;
    6414           0 :     if(!((type == "all") || (type=="corrected") || (type == "residual")))
    6415           0 :       hasCorrected=false;
    6416             :     
    6417             : 
    6418             : 
    6419           0 :     Bool twoPol=true;
    6420           0 :     Vector<String> polType=msc.feed().polarizationType()(0);
    6421           0 :     if (polType(0)!="X" && polType(0)!="Y" &&
    6422           0 :         polType(0)!="R" && polType(0)!="L") {
    6423           0 :       twoPol=false;
    6424             :     }
    6425             :     
    6426           0 :     ROVisIter& vi(*rvi_p);
    6427           0 :     VisBuffer vb(vi);
    6428             :     
    6429           0 :     Int nVis=0;
    6430           0 :     Int counter=0;
    6431           0 :     Float maxWeight=0;
    6432           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6433           0 :       for (vi.origin();vi.more();vi++) {
    6434           0 :         Int nRow=vb.nRow();
    6435           0 :         Int nChan=vb.nChannel();
    6436           0 :         maxWeight=max(maxWeight, max(vb.imagingWeight()));
    6437           0 :         for (Int row=0; row<nRow; ++row) {
    6438           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6439           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6440           0 :               ++counter;
    6441           0 :               if(counter==increment) {
    6442           0 :                 counter=0;
    6443           0 :                 ++nVis;
    6444             :               }
    6445             :             }
    6446             :           }
    6447             :         }
    6448             :       }
    6449             :     }
    6450             :     
    6451           0 :     if(nVis==0) {
    6452           0 :       os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
    6453           0 :       if(maxWeight <=0){
    6454             :         os << LogIO::SEVERE << "Max of imaging-weight is " << maxWeight 
    6455           0 :            << LogIO::POST;
    6456             :         os << LogIO::SEVERE << "Try setting it with the function weight"  
    6457           0 :            << LogIO::POST;
    6458             :       }
    6459           0 :       this->unlock();
    6460           0 :       return false;
    6461             :     }
    6462             :     
    6463           0 :     if(increment>1) {
    6464             :       os << LogIO::NORMAL << "For increment = " << increment << ", found " << nVis // Loglevel INFO
    6465           0 :          << " points for plotting" << endl;
    6466             :     }
    6467             :     else {
    6468           0 :       os << LogIO::NORMAL << "Found " << nVis << " points for plotting" << endl; // Loglevel INFO
    6469             :     }
    6470           0 :     Vector<Float> amp(nVis); amp=0.0;
    6471           0 :     Vector<Float> correctedAmp(nVis); correctedAmp=0.0;
    6472           0 :     Vector<Float> modelAmp(nVis); modelAmp=0.0;
    6473           0 :     Vector<Float> residualAmp(nVis); residualAmp=0.0;
    6474           0 :     Vector<Float> uvDistance(nVis); uvDistance=0.0;
    6475             :    
    6476           0 :     if(!hasModel)
    6477           0 :       modelAmp.resize();
    6478           0 :     if(!hasCorrected)
    6479           0 :       correctedAmp.resize();
    6480           0 :     if(!hasCorrected || !hasModel)
    6481           0 :       residualAmp.resize();
    6482             :     
    6483             : 
    6484           0 :     Float maxuvDistance=0.0;
    6485           0 :     Float maxAmp=0.0;
    6486           0 :     Float maxCorrectedAmp=0.0;
    6487           0 :     Float maxModelAmp=0.0;
    6488           0 :     Float maxResidualAmp=0.0;
    6489           0 :     Int iVis=0;
    6490           0 :     counter=0;
    6491           0 :     vi.originChunks();
    6492           0 :     vi.origin();
    6493           0 :     uInt numCorrPol=vb.nCorr();
    6494           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6495           0 :       for (vi.origin();vi.more();vi++) {
    6496           0 :         Int nRow=vb.nRow();
    6497           0 :         Int nChan=vb.nChannel();
    6498           0 :         for (Int row=0; row<nRow; ++row) {
    6499           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6500           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6501           0 :               ++counter;
    6502           0 :               if(counter==increment) {
    6503           0 :                 counter=0;
    6504           0 :                 Float f=vb.frequency()(chn)/C::c;
    6505           0 :                 Float u=vb.uvw()(row)(0)*f; 
    6506           0 :                 Float v=vb.uvw()(row)(1)*f;
    6507           0 :                 uvDistance(iVis)=sqrt(square(u)+square(v));
    6508           0 :                 if(twoPol) {
    6509           0 :                   amp(iVis)=sqrt((square(abs(vb.visCube()(0,chn,row)))+
    6510           0 :                                   square(abs(vb.visCube()(numCorrPol,chn,row))))/2.0);
    6511           0 :                   if(hasCorrected)
    6512           0 :                     correctedAmp(iVis)=
    6513           0 :                       sqrt((square(abs(vb.correctedVisCube()(0,chn,row)))+
    6514           0 :                             square(abs(vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6515           0 :                   if(hasModel)
    6516           0 :                     modelAmp(iVis)=
    6517           0 :                       sqrt((square(abs(vb.modelVisCube()(0,chn,row)))+
    6518           0 :                             square(abs(vb.modelVisCube()(numCorrPol,chn,row))))/2.0);
    6519           0 :                   if(hasCorrected && hasModel)
    6520           0 :                     residualAmp(iVis)=
    6521           0 :                       sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
    6522           0 :                                        vb.correctedVisCube()(0,chn,row)))+
    6523           0 :                             square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
    6524           0 :                                        vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6525             :                 }
    6526             :                 else {
    6527           0 :                   amp(iVis)=abs(vb.visCube()(0,chn,row));
    6528           0 :                   if(hasCorrected)
    6529           0 :                     correctedAmp(iVis)=abs(vb.correctedVisCube()(0,chn,row));
    6530           0 :                    if(hasModel)
    6531           0 :                      modelAmp(iVis)=abs(vb.modelVisCube()(0,chn,row));
    6532           0 :                   if(hasCorrected && hasModel) 
    6533           0 :                     residualAmp(iVis)=
    6534           0 :                       abs(vb.modelVisCube()(0,chn,row)-
    6535           0 :                           vb.correctedVisCube()(0,chn,row));
    6536             :                 }
    6537           0 :                 if(uvDistance(iVis)>maxuvDistance) {
    6538           0 :                   maxuvDistance=uvDistance(iVis);
    6539             :                 }
    6540           0 :                 if(amp(iVis)>maxAmp) {
    6541           0 :                   maxAmp=amp(iVis);
    6542             :                 }
    6543           0 :                 if(hasCorrected && (correctedAmp(iVis)>maxCorrectedAmp)) {
    6544           0 :                   maxCorrectedAmp=correctedAmp(iVis);
    6545             :                 }
    6546           0 :                 if(hasModel && (modelAmp(iVis)>maxModelAmp)) {
    6547           0 :                   maxModelAmp=modelAmp(iVis);
    6548             :                 }
    6549           0 :                 if((hasModel&&hasCorrected) && (residualAmp(iVis)>maxResidualAmp)) {
    6550           0 :                   maxResidualAmp=residualAmp(iVis);
    6551             :                 }
    6552           0 :                 ++iVis;
    6553             :               }
    6554             :             }
    6555             :           }
    6556             :         }
    6557             :       }
    6558             :     }
    6559             :     
    6560             : 
    6561             : 
    6562           0 :     if(maxuvDistance==0.0) {
    6563           0 :       os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6564           0 :       this->unlock();
    6565           0 :       return false;
    6566             :     }
    6567             :     
    6568             : 
    6569             : 
    6570             :     
    6571             : 
    6572           0 :     Float Ymax(0.0);
    6573             : 
    6574           0 :     if (type.contains("corrected") && hasCorrected)
    6575           0 :       if(maxCorrectedAmp>Ymax) Ymax = maxCorrectedAmp;
    6576             : 
    6577           0 :     if (type.contains("model") && hasModel)
    6578           0 :       if(maxModelAmp>Ymax)     Ymax = maxModelAmp;
    6579             : 
    6580           0 :     if (type.contains("residual") && (hasModel && hasCorrected))
    6581           0 :       if(maxResidualAmp>Ymax)  Ymax = maxResidualAmp;
    6582             : 
    6583           0 :     if (type.contains("observed"))
    6584           0 :       if(maxAmp>Ymax)          Ymax = maxAmp;
    6585             : 
    6586           0 :     if ((type=="all") || (type == ""))
    6587             :       {
    6588           0 :         if (maxAmp > Ymax)       Ymax = maxAmp;
    6589           0 :         if(hasCorrected && (maxCorrectedAmp>Ymax)) Ymax = maxCorrectedAmp;
    6590           0 :         if(hasModel && (maxModelAmp>Ymax))     Ymax = maxModelAmp;
    6591           0 :         if((hasModel && hasCorrected) && maxResidualAmp>Ymax)  Ymax = maxResidualAmp;
    6592             :       }
    6593             :    
    6594             : 
    6595           0 :     return false;
    6596             : 
    6597             :     
    6598             :     this->unlock();
    6599             :     return true;
    6600           0 :   } catch (AipsError x) {
    6601           0 :     this->unlock();
    6602           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6603           0 :     return false;
    6604           0 :   } 
    6605             :   this->unlock();
    6606             : 
    6607             :   return true;
    6608           0 : }
    6609             : 
    6610             : // Plot the weights
    6611           0 : Bool Imager::plotweights(const Bool gridded, const Int increment) 
    6612             : {
    6613             : 
    6614           0 :   if(!valid()) return false;
    6615           0 :   LogIO os(LogOrigin("imager", "plotweights()", WHERE));
    6616             :   
    6617           0 :   this->lock();
    6618             :   try {
    6619             :     
    6620             :     
    6621             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6622             :        << "Plotting imaging weights for currently selected data"
    6623           0 :        << LogIO::POST;
    6624             :     
    6625           0 :     ROVisIter& vi(*rvi_p);
    6626           0 :     VisBuffer vb(vi);
    6627             :     
    6628           0 :     if(gridded) {
    6629           0 :       if(!assertDefinedImageParameters()) {this->unlock(); return false;}
    6630             :       // First find the gridded weights
    6631             :       Float uscale, vscale;
    6632             :       Int uorigin, vorigin;
    6633           0 :       uscale=(nx_p*mcellx_p.get("rad").getValue())/2.0;
    6634           0 :       vscale=(ny_p*mcelly_p.get("rad").getValue())/2.0;
    6635           0 :       uorigin=nx_p/2;
    6636           0 :       vorigin=ny_p/2;
    6637             :       
    6638             :       // Simply declare a big matrix 
    6639           0 :       Float maxWeight=0.0;
    6640           0 :       Matrix<Float> gwt(nx_p,ny_p);
    6641           0 :       gwt=0.0;
    6642             :       
    6643             :       Float u, v;
    6644           0 :       Float sumwt=0.0;
    6645           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6646           0 :         for (vi.origin();vi.more();vi++) {
    6647           0 :           Int nRow=vb.nRow();
    6648           0 :           Int nChan=vb.nChannel();
    6649           0 :           for (Int row=0; row<nRow; ++row) {
    6650           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6651           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6652           0 :                 Float f=vb.frequency()(chn)/C::c;
    6653           0 :                 u=vb.uvw()(row)(0)*f; 
    6654           0 :                 v=vb.uvw()(row)(1)*f;
    6655           0 :                 Int ucell=Int(uscale*u+uorigin);
    6656           0 :                 Int vcell=Int(vscale*v+vorigin);
    6657           0 :                 if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
    6658           0 :                   gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
    6659           0 :                   sumwt+=vb.imagingWeight()(chn,row);
    6660           0 :                   if(vb.imagingWeight()(chn,row)>maxWeight) {
    6661           0 :                     maxWeight=vb.imagingWeight()(chn,row);
    6662             :                   }
    6663             :                 }
    6664           0 :                 ucell=Int(-uscale*u+uorigin);
    6665           0 :                 vcell=Int(-vscale*v+vorigin);
    6666           0 :                 if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
    6667           0 :                   gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
    6668             :                 }
    6669             :               }
    6670             :             }
    6671             :           }
    6672             :         }
    6673             :       }
    6674             :       
    6675           0 :       if(sumwt>0.0) {
    6676           0 :         os << LogIO::NORMAL << "Sum of weights = " << sumwt << endl; // Loglevel INFO
    6677             :       }
    6678             :       else {
    6679           0 :         this->unlock();
    6680             :         os << LogIO::SEVERE << "Sum of weights is zero: perhaps you need to weight the data"
    6681           0 :            << LogIO::POST;
    6682           0 :           return false;
    6683             :       }
    6684             :      
    6685             :       
    6686             :       //Float umax=Float(nx_p/2)/uscale;
    6687             :       //Float vmax=Float(ny_p/2)/vscale;
    6688             : 
    6689             : 
    6690           0 :       return false;
    6691           0 :     }
    6692             :     else {
    6693             :       
    6694             :       // Now do the points plot
    6695           0 :       Int nVis=0;
    6696           0 :       Int counter=0;
    6697           0 :       Float maxWeight=0.0;
    6698           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6699           0 :         for (vi.origin();vi.more();vi++) {
    6700           0 :           Int nRow=vb.nRow();
    6701           0 :           Int nChan=vb.nChannel();
    6702           0 :           for (Int row=0; row<nRow; ++row) {
    6703           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6704           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6705           0 :                 ++counter;
    6706           0 :                 if(counter==increment) {
    6707           0 :                   counter=0;
    6708           0 :                   ++nVis;
    6709             :                 }
    6710             :               }
    6711             :             }
    6712             :           }
    6713             :         }
    6714             :       }
    6715             :       
    6716           0 :       if(increment>1) {
    6717             :         os << LogIO::NORMAL // Loglevel INFO
    6718             :            << "For increment = " << increment << ", found " << nVis
    6719           0 :            << " points for plotting" << endl;
    6720             :       }
    6721             :       else {
    6722             :         os << LogIO::NORMAL // Loglevel INFO
    6723           0 :            << "Found " << nVis << " points for plotting" << endl;
    6724             :       }
    6725             :       
    6726           0 :       Float maxuvDistance=0.0;
    6727           0 :       Vector<Float> weights(nVis);
    6728           0 :       Vector<Float> uvDistance(nVis);
    6729           0 :       weights=0.0;
    6730           0 :       uvDistance=0.0;
    6731             :       
    6732           0 :       Int iVis=0;
    6733           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6734           0 :         for (vi.origin();vi.more();vi++) {
    6735           0 :           Int nRow=vb.nRow();
    6736           0 :           Int nChan=vb.nChannel();
    6737           0 :           for (Int row=0; row<nRow; ++row) {
    6738           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6739           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6740           0 :                 ++counter;
    6741           0 :                 if(counter==increment) {
    6742           0 :                   Float f=vb.frequency()(chn)/C::c;
    6743           0 :                   Float u=vb.uvw()(row)(0)*f; 
    6744           0 :                   Float v=vb.uvw()(row)(1)*f;
    6745           0 :                   uvDistance(iVis)=sqrt(square(u)+square(v));
    6746           0 :                   weights(iVis)=vb.imagingWeight()(chn,row);
    6747           0 :                   if(vb.imagingWeight()(chn,row)>maxWeight) {
    6748           0 :                     maxWeight=vb.imagingWeight()(chn,row);
    6749             :                   }
    6750           0 :                   if(uvDistance(iVis)>maxuvDistance) {
    6751           0 :                     maxuvDistance=uvDistance(iVis);
    6752             :                   }
    6753           0 :                   counter=0;
    6754           0 :                   ++iVis;
    6755             :                 }
    6756             :               }
    6757             :             }
    6758             :           }
    6759             :         }
    6760             :       }
    6761             :       
    6762           0 :       if(maxuvDistance==0.0) {
    6763           0 :         this->unlock();
    6764           0 :         os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6765           0 :         return false;
    6766             :       }
    6767             : 
    6768             : 
    6769           0 :       return false;
    6770           0 :     }
    6771             :     
    6772             : 
    6773             :     
    6774             :     this->unlock();
    6775             :     return true;
    6776           0 :   } catch (AipsError x) {
    6777           0 :     this->unlock();
    6778           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6779           0 :     return false;
    6780           0 :   } 
    6781             :   this->unlock();
    6782             : 
    6783             :   return true;
    6784           0 : }
    6785             : 
    6786           0 : Bool Imager::clipvis(const Quantity& threshold) 
    6787             : {
    6788             : 
    6789           0 :   if(!valid()) return false;
    6790             :   
    6791           0 :   LogIO os(LogOrigin("imager", "clipvis()", WHERE));
    6792             :   
    6793           0 :   this->lock();
    6794             :   try {
    6795             :     
    6796           0 :     Float thres=threshold.get("Jy").getValue();
    6797             :     
    6798             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6799             :        << "Clipping visibilities where residual visibility > "
    6800           0 :        << thres << " Jy" << LogIO::POST;
    6801           0 :     if(!wvi_p){
    6802             :       os << LogIO::WARN
    6803             :          << "Cannot clip visibilities in read only mode of ms" 
    6804           0 :          << LogIO::POST;
    6805           0 :       return false;
    6806             :     }
    6807           0 :     VisIter& vi(*wvi_p);
    6808           0 :     VisBuffer vb(vi);
    6809             :     
    6810             : 
    6811           0 :     vi.originChunks();
    6812           0 :     vi.origin();
    6813             : // Making sure picking LL for [RR RL LR LL] correlations or [RR LL] 
    6814           0 :     uInt numCorrPol=vb.modelVisCube().shape()(0) - 1 ; 
    6815           0 :     Int nBad=0;
    6816           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6817           0 :       for (vi.origin();vi.more();vi++) {
    6818           0 :         Int nRow=vb.nRow();
    6819           0 :         Int nChan=vb.nChannel();
    6820           0 :         for (Int row=0; row<nRow; ++row) {
    6821           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6822           0 :             if(!vb.flag()(chn,row)) {
    6823             :               Float residualAmp=
    6824           0 :                 sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
    6825           0 :                                  vb.correctedVisCube()(0,chn,row)))+
    6826           0 :                       square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
    6827           0 :                                  vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6828           0 :               if(residualAmp>thres) {
    6829           0 :                 vb.flag()(chn,row)=true;
    6830           0 :                 ++nBad;
    6831             :               }
    6832             :             }
    6833             :           }
    6834             :         }
    6835           0 :         vi.setFlag(vb.flag());
    6836             :       }
    6837             :     }
    6838             :     
    6839           0 :     os << LogIO::NORMAL << "Flagged " << nBad << " points" << LogIO::POST; // Loglevel INFO
    6840             :     
    6841           0 :     this->unlock();
    6842           0 :     return true;
    6843           0 :   } catch (AipsError x) {
    6844           0 :     this->unlock();
    6845           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6846           0 :   } 
    6847           0 :   this->unlock();
    6848             : 
    6849           0 :   return true;
    6850           0 : }
    6851             : 
    6852             : // Plot various ids
    6853           0 : Bool Imager::plotsummary() 
    6854             : {
    6855             :   
    6856           0 :   if(!valid()) return false;
    6857             :   
    6858           0 :   LogIO os(LogOrigin("imager", "plotsummary()", WHERE));
    6859             :   
    6860           0 :   os << LogIO::WARN << "NOT implemented " << LogIO::POST;
    6861           0 :   return false;
    6862             : 
    6863             :   this->lock();
    6864             :   try {
    6865             :     /*
    6866             :     os << "Plotting field and spectral window ids for currently selected data" << LogIO::POST;
    6867             :     
    6868             :     ROVisIter& vi(*rvi_p);
    6869             :     VisBuffer vb(vi);
    6870             :     
    6871             :     Int nVis=0;
    6872             :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6873             :       for (vi.origin();vi.more();vi++) {
    6874             :         Int nRow=vb.nRow();
    6875             :         for (Int row=0; row<nRow; ++row) {
    6876             :           ++nVis;
    6877             :         }
    6878             :       }
    6879             :     }
    6880             :     
    6881             :     os << "Found " << nVis << " selected records" << LogIO::POST;
    6882             :     
    6883             :     Vector<Float> fieldId(nVis);
    6884             :     Vector<Float> spectralWindowId(nVis);
    6885             :     Vector<Double> t(nVis);
    6886             :     
    6887             :     Int maxFieldId=0;
    6888             :     Int maxSpectralWindowId=0;
    6889             :     Int iVis=0;
    6890             :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6891             :       for (vi.origin();vi.more();vi++) {
    6892             :         Int nRow=vb.nRow();
    6893             :         for (Int row=0; row<nRow; ++row) {
    6894             :           t(iVis)=vb.time()(row);
    6895             :           fieldId(iVis)=vb.fieldId()+1.0;
    6896             :           spectralWindowId(iVis)=vb.spectralWindow()+1.003;
    6897             :           if(Int(fieldId(iVis))>maxFieldId) maxFieldId=Int(fieldId(iVis));
    6898             :           if(Int(spectralWindowId(iVis))>maxSpectralWindowId)
    6899             :             maxSpectralWindowId=Int(spectralWindowId(iVis));
    6900             :           ++iVis;
    6901             :         }
    6902             :       }
    6903             :     }
    6904             :     
    6905             :     Double tStart=t(0);
    6906             :     Vector<Float> timeFloat(nVis);
    6907             :     for(Int i=0;i<nVis;++i) {
    6908             :       timeFloat(i)=Float(t(i)-tStart);
    6909             :     }
    6910             :     
    6911             :     MSColumns msc(*ms_p);
    6912             :     PGPlotter plotter=getPGPlotter();
    6913             :     plotter.subp(1, 2);
    6914             :     plotter.page();
    6915             :     plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0, Float(maxFieldId)*1.1);
    6916             :     plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
    6917             :     String xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
    6918             :     plotter.lab(xLabel, "ID", "Field IDs for " +imageName());
    6919             :     plotter.sci(1);
    6920             :     for (Int fid=0;fid<maxFieldId;++fid) {
    6921             :       String fieldName=msc.field().name()(fid);
    6922             :       plotter.text(1.02*timeFloat(nVis-1), Float(fid+1), fieldName);
    6923             :     }
    6924             :     plotter.pt(timeFloat,fieldId,-1);
    6925             :     plotter.page();
    6926             :     plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0,
    6927             :                  Float(maxSpectralWindowId)*1.1);
    6928             :     plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
    6929             :     xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
    6930             :     plotter.lab(xLabel, "ID", "Spectral Window IDs for " +imageName());
    6931             :     plotter.sci(1);
    6932             :     for(Int spwId=0;spwId<maxSpectralWindowId;++spwId) {
    6933             :       Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spwId); 
    6934             :       ostringstream spwString;
    6935             :       spwString<<chanFreq(0)/1.0e9<<" GHz";
    6936             :       plotter.text(1.02*timeFloat(nVis-1), Float(spwId+1),
    6937             :                    spwString);
    6938             :     }
    6939             :     plotter.pt(timeFloat,spectralWindowId,-1);
    6940             :     plotter.iden();
    6941             :     this->unlock();
    6942             :     return true;
    6943             :     */
    6944             :   } catch (AipsError x) {
    6945             :     this->unlock();
    6946             :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6947             :     return false;
    6948             :   } 
    6949             :     
    6950             :   this->unlock();
    6951             : 
    6952             :   return true;
    6953           0 : }
    6954             : 
    6955             : 
    6956           0 : Bool Imager::detached() const
    6957             : {
    6958           0 :   if (ms_p.null()) {
    6959           0 :     LogIO os(LogOrigin("imager", "detached()", WHERE));
    6960             :     os << LogIO::SEVERE << 
    6961             :       "imager is detached - cannot perform operation." << endl <<
    6962           0 :       "Call imager.open('filename') to reattach." << LogIO::POST;
    6963           0 :     return true;
    6964           0 :   }
    6965           0 :   return false;
    6966             : }
    6967             : 
    6968           0 : Bool Imager::makemodelfromsd(const String& sdImage, const String& modelImage, 
    6969             :                              const String& lowPSF, String& maskImage)
    6970             : {
    6971             : 
    6972           0 :  if(!valid()) return false;
    6973             :   
    6974           0 :   LogIO os(LogOrigin("imager", "makemodelfromsd()", WHERE));
    6975             :   
    6976             :   try {
    6977             :     
    6978           0 :     if(!Table::isReadable(sdImage)){
    6979             :       os << LogIO::SEVERE  << "Single Dish " << sdImage 
    6980           0 :          << "  image is not readable" << LogIO::EXCEPTION;
    6981             :       
    6982           0 :       return false;
    6983             :     }
    6984             : 
    6985             :     os << LogIO::NORMAL << "Creating an initial model image " << modelImage  // Loglevel INFO
    6986           0 :        << " from single dish image " << sdImage << LogIO::POST;
    6987             :     
    6988           0 :     CoordinateSystem coordsys;
    6989             :     //imagecoordinates(coordsys);
    6990           0 :     imagecoordinates2(coordsys);
    6991           0 :     String modelName=modelImage;
    6992           0 :     this->makeEmptyImage(coordsys, modelName, fieldid_p);
    6993             :     
    6994           0 :     PagedImage<Float> model(modelImage);
    6995           0 :     PagedImage<Float> low0(sdImage);
    6996           0 :     String sdObs=low0.coordinates().obsInfo().telescope();
    6997             : 
    6998           0 :     GaussianBeam lBeam;
    6999           0 :     ImageInfo lowInfo=low0.imageInfo();
    7000           0 :     lBeam=lowInfo.restoringBeam();
    7001             :   
    7002           0 :     Float beamFactor=-1.0;
    7003             : 
    7004             :     
    7005             :     // regrid the single dish image
    7006             :     {
    7007           0 :       ImageRegrid<Float> ir;
    7008           0 :       IPosition axes(3,0,1,3);   // if its a cube, regrid the spectral too
    7009           0 :       ir.regrid(model, Interpolate2D::LINEAR, axes, low0);
    7010           0 :     }
    7011             :     
    7012             :   
    7013             : 
    7014             :     // Will need to make a complex image to apply the beam
    7015           0 :     TempImage<Complex> ctemp(model.shape(), model.coordinates());
    7016           0 :     if(lowPSF=="") {
    7017             :       os << LogIO::NORMAL // Loglevel INFO
    7018             :          << "Using primary beam of single dish to determine flux scale"
    7019           0 :          << LogIO::POST;
    7020             : 
    7021           0 :       TempImage<Float> beamTemp(model.shape(), model.coordinates());
    7022             :       //Make the PB accordingly
    7023           0 :       if(lBeam.isNull()) {
    7024             :       
    7025           0 :         if (doDefaultVP_p) { 
    7026           0 :           if(telescope_p!=""){
    7027           0 :             ObsInfo myobsinfo=this->latestObsInfo();
    7028           0 :             myobsinfo.setTelescope(telescope_p);
    7029           0 :             coordsys.setObsInfo(myobsinfo);
    7030             :             
    7031           0 :           }
    7032             :           else{
    7033           0 :             if(sdObs != ""){
    7034           0 :               telescope_p=sdObs;
    7035           0 :               ObsInfo myobsinfo=this->latestObsInfo();
    7036           0 :               myobsinfo.setTelescope(telescope_p);
    7037           0 :               coordsys.setObsInfo(myobsinfo);
    7038           0 :             }
    7039             :             else{
    7040           0 :               telescope_p=coordsys.obsInfo().telescope();
    7041             :             }
    7042             :           }
    7043           0 :           beamTemp.setCoordinateInfo(coordsys);
    7044           0 :           this->makePBImage(beamTemp);
    7045             :          
    7046             :         }
    7047             :         else{
    7048           0 :           Table vpTable(vpTableStr_p);
    7049           0 :           this->makePBImage(vpTable, beamTemp);      
    7050           0 :         }
    7051           0 :         StokesImageUtil::FitGaussianPSF(beamTemp, lBeam);
    7052           0 :         LatticeExprNode sumImage = sum(beamTemp);
    7053           0 :         beamFactor=sumImage.getFloat();
    7054             :         
    7055           0 :       }
    7056             :       
    7057             :       
    7058           0 :     }
    7059             :     else {
    7060             :       os << LogIO::NORMAL // Loglevel INFO
    7061             :          << "Using specified low resolution PSF to determine sd flux scale"
    7062           0 :          << LogIO::POST;
    7063             :       // regrid the single dish psf
    7064           0 :       PagedImage<Float> lowpsf0(lowPSF);
    7065           0 :       TempImage<Float> lowpsf(model.shape(), model.coordinates());
    7066             :       {
    7067           0 :         ImageRegrid<Float> ir;
    7068           0 :         IPosition axes(2,0,1);   //
    7069           0 :         ir.regrid(lowpsf, Interpolate2D::LINEAR, axes, lowpsf0);
    7070           0 :       }
    7071           0 :       LatticeExprNode sumImage = sum(lowpsf);
    7072           0 :       beamFactor=sumImage.getFloat();
    7073           0 :       if(lBeam.isNull()) {
    7074           0 :         os << LogIO::NORMAL << "Finding SD beam from given PSF" << LogIO::POST; // Loglevel PROGRESS
    7075           0 :         StokesImageUtil::FitGaussianPSF(lowpsf0, lBeam);
    7076             :       }
    7077           0 :     }
    7078             :     
    7079             : 
    7080             :     // This factor comes from the beam volumes
    7081           0 :     if(sdScale_p!=1.0)
    7082             :       os << LogIO::DEBUG1
    7083             :          << "Multiplying single dish data by user specified factor "
    7084           0 :          << sdScale_p << LogIO::POST;
    7085           0 :     Float sdScaling  = sdScale_p;
    7086           0 :     if(! lBeam.isNull()) {
    7087           0 :       Int directionIndex=model.coordinates().findCoordinate(Coordinate::DIRECTION);
    7088             :       DirectionCoordinate
    7089           0 :         directionCoord=model.coordinates().directionCoordinate(directionIndex);
    7090           0 :       Vector<String> units(2); units.set("arcsec");
    7091           0 :       directionCoord.setWorldAxisUnits(units); 
    7092           0 :       Vector<Double> incr= directionCoord.increment();
    7093           0 :       if(beamFactor >0.0) {
    7094           0 :         beamFactor=1.0/beamFactor;
    7095             :       }
    7096             :       else{
    7097             :         //      beamFactor=
    7098             :         //        abs(incr(0)*incr(1))/(lBeam(0).get("arcsec").getValue()*lBeam(1).get("arcsec").getValue()*1.162);
    7099             :         //Brute Force for now.
    7100           0 :         IPosition imshape(4, nx_p, ny_p, 1, 1);
    7101           0 :         TempImage<Float> lowpsf(imshape, coordsys);
    7102           0 :         lowpsf.set(0.0);
    7103           0 :         IPosition center(4, Int((nx_p/4)*2), Int((ny_p/4)*2),0,0);
    7104           0 :         lowpsf.putAt(1.0, center);
    7105           0 :         StokesImageUtil::Convolve(lowpsf, lBeam, false);
    7106           0 :         LatticeExprNode sumImage = sum(lowpsf);
    7107           0 :         beamFactor=1.0/sumImage.getFloat();
    7108             : 
    7109             :         
    7110           0 :       }
    7111             :       os << LogIO::NORMAL << "Beam volume factor  " // Loglevel INFO
    7112           0 :          <<  beamFactor << LogIO::POST;
    7113           0 :       sdScaling*=beamFactor;
    7114           0 :     }
    7115             :     else {
    7116           0 :       os << LogIO::WARN << "Insufficient information to scale correctly" << LogIO::POST;
    7117             :     }
    7118             :  
    7119             :     //Convert to Jy/pixel
    7120           0 :     model.copyData(  (LatticeExpr<Float>)((model * sdScaling)));
    7121           0 :     model.setUnits(Unit("Jy/pixel"));
    7122             :     
    7123             :     //make a mask image
    7124           0 :     this->makeEmptyImage(coordsys, maskImage, fieldid_p);
    7125           0 :     PagedImage<Float> mask(maskImage);
    7126           0 :     mask.set(1.0);
    7127           0 :     ArrayLattice<Bool> sdMask(model.getMask());
    7128           0 :     mask.copyData( LatticeExpr<Float> (mask* ntrue(sdMask)*model));
    7129           0 :     StokesImageUtil::MaskFrom(mask, mask, Quantity(0.0, "Jy"));
    7130           0 :     model.copyData( LatticeExpr<Float> (mask*model));
    7131           0 :     return true;
    7132           0 :   } catch (AipsError x) {
    7133             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    7134           0 :        << LogIO::POST;
    7135           0 :     return false;
    7136           0 :   } 
    7137             :   
    7138             :   return true;
    7139             : 
    7140             : 
    7141           0 : }
    7142             : 
    7143             : 
    7144           0 : Int Imager::interactivemask(const String& image, const String& mask, 
    7145             :                             Int& niter, Int& ncycles, String& thresh, const Bool forceReload){
    7146             : 
    7147           0 :   LogIO os(LogOrigin("Imager", "interactivemask()", WHERE));
    7148           0 :    if(Table::isReadable(mask)) {
    7149           0 :     if (! Table::isWritable(mask)) {
    7150           0 :       os << LogIO::WARN << "Mask image is not modifiable " << LogIO::POST;
    7151           0 :       return false;
    7152             :     }
    7153             :     //we should regrid here if image and mask do not match
    7154             :    }
    7155             :    else{
    7156           0 :      clone(image, mask);
    7157             :    }
    7158             : #ifdef USE_GRPC
    7159           0 :    Quantity thr;
    7160           0 :    if ( ! Quantity::read(thr,thresh) ) thr = Quantity(0,"Jy");
    7161           0 :    float thold = (float) thr.get("Jy").getValue( );
    7162           0 :    grpcInteractiveClean::getManager( ).setControls( niter, ncycles, thold);
    7163             : #endif
    7164           0 :    return false;
    7165           0 : }
    7166             : 
    7167           0 :   Record Imager::iClean(const String& algorithm, const Int niter, const Double gain, 
    7168             :                       const Quantity& threshold,
    7169             :                       const Bool displayprogress,
    7170             :                       const Vector<String>& model,
    7171             :                       const Vector<Bool>& keepfixed, const String& complist,
    7172             :                       const Vector<String>& mask,
    7173             :                       const Vector<String>& image,
    7174             :                       const Vector<String>& residual,
    7175             :                       const Vector<String>& psfnames,
    7176             :                       const Bool interactive, const Int npercycle,
    7177             :                       const String& masktemplate)
    7178             :   {
    7179           0 :     Record rstat;
    7180             :       
    7181           0 :     logSink_p.clearLocally();
    7182           0 :     LogIO os(LogOrigin("imager", "iClean()"), logSink_p);
    7183             : 
    7184           0 :     if(!ms_p.null()) {
    7185             :       //try
    7186             :        {
    7187             :        
    7188           0 :         Vector<String> amodel(model);
    7189           0 :         Vector<Bool>   fixed(keepfixed);
    7190           0 :         Vector<String> amask(mask);
    7191           0 :         Vector<String> aimage(image);
    7192           0 :         Vector<String> aresidual(residual);
    7193           0 :         Vector<String> apsf(psfnames);
    7194             :         
    7195           0 :         if(String(algorithm) != "msmfs") ntaylor_p=1; /* masks increment by ntaylor_p only for msmfs */
    7196           0 :         uInt nmods = aresidual.nelements()/ntaylor_p;
    7197             : 
    7198           0 :         if( (apsf.nelements()==1) && apsf[0]==String(""))
    7199           0 :           apsf.resize();
    7200           0 :         if(!interactive){
    7201           0 :           rstat = clean(String(algorithm), niter, gain,  
    7202             :                         threshold, displayprogress, 
    7203           0 :                         amodel, fixed, String(complist), amask,  
    7204           0 :                         aimage, aresidual, apsf);
    7205             :         }
    7206             :         else{
    7207           0 :           if((amask.nelements()==0) || (amask[0]==String(""))){
    7208           0 :             amask.resize(amodel.nelements());
    7209           0 :             for (uInt k=0; k < amask.nelements(); ++k){
    7210           0 :               amask[k]=amodel[k]+String(".mask");
    7211             :             }
    7212             :           }
    7213           0 :           Vector<Bool> nointerac(nmods);
    7214           0 :           nointerac.set(false);
    7215           0 :           if(fixed.nelements() != nmods){
    7216           0 :             fixed.resize(nmods);
    7217           0 :             fixed.set(false);
    7218             :           }
    7219           0 :           Bool forceReload=true;
    7220           0 :           Int nloop=0;
    7221           0 :           if(npercycle != 0)
    7222           0 :             nloop=niter/npercycle;
    7223           0 :           Int continter=0;
    7224           0 :           Int elniter=npercycle;
    7225           0 :           ostringstream oos;
    7226           0 :           threshold.print(oos);
    7227           0 :           String thresh=String(oos);
    7228           0 :           if(String(masktemplate) != String("")){
    7229           0 :             continter=interactivemask(masktemplate, amask[0], 
    7230             :                                                  elniter, nloop, thresh);
    7231             :           }
    7232             :           else {
    7233             :             // do a zero component clean to get started
    7234           0 :             rstat=clean(String(algorithm), 0, gain, 
    7235             :                   threshold, displayprogress,
    7236           0 :                   amodel, fixed, String(complist), amask,  
    7237           0 :                   aimage, aresidual, Vector<String>(0), false);
    7238             :             
    7239           0 :             for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
    7240           0 :               if(Table::isReadable(aimage[nIm]) && Table::isWritable(aresidual[nIm]) ){
    7241           0 :                 PagedImage<Float> rest(aimage[nIm]);
    7242           0 :                 PagedImage<Float> resi(aresidual[nIm]);
    7243           0 :                 copyMask(resi, rest, "mask0");
    7244           0 :               }
    7245           0 :               forceReload=forceReload || (aresidual.nelements() >1);
    7246           0 :               continter=interactivemask(aresidual[nIm], amask[nIm], 
    7247             :                                                    elniter, nloop,thresh, forceReload);
    7248           0 :               forceReload=false;
    7249           0 :               if(continter>=1)
    7250           0 :                 nointerac(nIm)=true;
    7251           0 :               if(continter==2)
    7252           0 :                 fixed(nIm)=true;
    7253             :               
    7254             :             }
    7255           0 :             if(allEQ(nointerac, true)){
    7256           0 :               elniter=niter;
    7257             :               //make it do one more loop/clean but with all niter 
    7258           0 :               nloop=1;
    7259             :             }
    7260             :           }
    7261           0 :           for (Int k=0; k < nloop; ++k){
    7262             :             
    7263           0 :             casacore::Quantity thrsh;
    7264           0 :             if(!casacore::Quantity::read(thrsh, thresh)){
    7265             :               os << LogIO::WARN << "Error interpreting threshold" 
    7266           0 :                       << LogIO::POST;
    7267           0 :               thrsh=casacore::Quantity(0, "Jy");
    7268           0 :               thresh="0.0Jy";
    7269             :             }
    7270           0 :             Vector<String> elpsf(0);
    7271             :             //Need to save psfs in interactive only once and lets do it the 
    7272             :             //first time
    7273           0 :             if(k==0)
    7274           0 :               elpsf=apsf;
    7275           0 :             if(anyEQ(fixed, false)){
    7276           0 :               rstat = clean(String(algorithm), elniter, gain, 
    7277             :                             thrsh, 
    7278             :                             displayprogress,
    7279           0 :                             amodel, fixed, String(complist), 
    7280             :                             amask,  
    7281           0 :                             aimage, aresidual, elpsf, k == 0);
    7282             :               //if clean converged... equivalent to stop
    7283           0 :               if(rstat.asBool("converged")){
    7284           0 :                 continter=2;
    7285           0 :                 fixed.set(true);
    7286             :               }
    7287           0 :               if(anyEQ(fixed, false) && anyEQ(nointerac,false)){
    7288           0 :                 Int remainloop=nloop-k-1;
    7289           0 :                 for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
    7290           0 :                   if(!nointerac(nIm)){
    7291           0 :                     continter=interactivemask(aresidual[nIm], amask[nIm],
    7292             :                                               
    7293             :                                               elniter, remainloop, 
    7294           0 :                                               thresh, (aresidual.nelements() >1));
    7295           0 :                     if(continter>=1)
    7296           0 :                       nointerac(nIm)=true;
    7297           0 :                     if(continter==2)
    7298           0 :                       fixed(nIm)=true;
    7299             :                   }
    7300             :                 }
    7301           0 :                 k=nloop-remainloop-1;
    7302           0 :                 if(allEQ(nointerac,true)){
    7303           0 :                   elniter=niter-(k+1)*npercycle;
    7304             :                   //make it do one more loop/clean but with remaining niter 
    7305           0 :                   k=nloop-2;
    7306             :                 }
    7307             :               } 
    7308             :             }
    7309           0 :           }
    7310             :           //Unset the mask in the residual 
    7311             :           // Cause as requested in CAS-1768...
    7312           0 :           for (uInt nIm=0; nIm < aresidual.nelements(); ++nIm){
    7313           0 :             if(Table::isWritable(aresidual[nIm]) ){
    7314           0 :               PagedImage<Float> resi(aresidual[nIm]);
    7315           0 :               if(resi.hasRegion("mask0", RegionHandler::Masks)){
    7316           0 :                 resi.setDefaultMask("");
    7317             :               }
    7318           0 :             }
    7319             :           }
    7320             :           
    7321           0 :         }
    7322             : 
    7323           0 :         os << "Restoring Image(s) with the clean-beam" << LogIO::POST;
    7324           0 :         restoreImages(aimage, (niter>=0) );
    7325           0 :         this->writeHistory(os);
    7326             :         try{
    7327             :           // write data processing history into image logtable
    7328           0 :           LoggerHolder imagelog (false);
    7329           0 :           LogSink& sink = imagelog.sink();
    7330           0 :           LogOrigin lor( String("imager"), String("clean()") );
    7331           0 :           LogMessage msg(lor);
    7332           0 :           sink.postLocally(msg);
    7333           0 :           MSHistoryColumns msHis(ms_p->history());
    7334           0 :           transferHistory(imagelog, msHis);
    7335           0 :           for (Int thismodel=0;thismodel<Int(aimage.nelements());++thismodel) {
    7336           0 :             if(Table::isWritable(aimage(thismodel))){
    7337           0 :               PagedImage<Float> restoredImage(aimage(thismodel),
    7338           0 :                                               TableLock(TableLock::AutoNoReadLocking));
    7339           0 :               LoggerHolder& log = restoredImage.logger();
    7340           0 :               log.append(imagelog);
    7341           0 :               log.flush();
    7342           0 :               restoredImage.table().relinquishAutoLocks(true);
    7343           0 :             }
    7344             :           }
    7345           0 :         }
    7346           0 :         catch(exception& x){
    7347             :       
    7348           0 :           this->unlock();
    7349           0 :           destroySkyEquation();
    7350           0 :           os << LogIO::WARN << "Caught exception: " << x.what()
    7351           0 :              << LogIO::POST;
    7352             :           os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted;  you may consider deleting all the rows from this table"
    7353           0 :              <<LogIO::POST; 
    7354             :           //continue and wrap up this function
    7355             :           
    7356           0 :         }
    7357           0 :         catch(...){
    7358           0 :           this->unlock();
    7359           0 :           destroySkyEquation();
    7360           0 :           os << LogIO::WARN << "Caught unknown exception" <<  LogIO::POST;
    7361             :           os << LogIO::SEVERE << "The MS/HISTORY table may be corrupted;  you may consider deleting all the rows from this table"
    7362           0 :              <<LogIO::POST;
    7363             :           
    7364           0 :         }
    7365             : 
    7366             : 
    7367           0 :        } //catch  (AipsError x) {
    7368             :        //os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
    7369             :        //       RETHROW(x);
    7370             :        //  }
    7371             :     } else {
    7372           0 :       os << LogIO::SEVERE << "No MeasurementSet has been assigned, please run open." << LogIO::POST;
    7373             :     }
    7374           0 :     return rstat;
    7375           0 :   }
    7376             : 
    7377           0 : Bool Imager::adviseChanSelex(Double& freqStart, Double& freqEnd, 
    7378             :                        const Double& freqStep,  const MFrequency::Types& freqframe,
    7379             :                        Vector< Vector<Int> >& spw, Vector< Vector<Int> >& start,
    7380             :                              Vector< Vector<Int> >& nchan, const String& ms, const Int field_id, const Bool getFreqRange, const String spwselection){
    7381             : 
    7382           0 :   LogIO os(LogOrigin("imager", "adviseChanSelex"));
    7383           0 :   if(ms==String("")){
    7384           0 :     if(numMS_p < 1 || !rvi_p){
    7385             :       os << LogIO::SEVERE << "Data selection incomplete" 
    7386           0 :          << LogIO::POST;
    7387           0 :       return false;
    7388             :     }
    7389             :   }
    7390           0 :   spw.resize();
    7391           0 :   start.resize();
    7392           0 :   nchan.resize();
    7393             :   try {
    7394           0 :     if(!getFreqRange){
    7395           0 :       Block<Vector<Int> > bnchan;
    7396           0 :       Block<Vector<Int> > bstart;
    7397           0 :       Block<Vector<Int> > bspw;
    7398             :       Double fS, fE;
    7399           0 :       fS=freqStart;
    7400           0 :       fE=freqEnd;
    7401           0 :       if(freqEnd < freqStart){
    7402           0 :         fS=freqEnd;
    7403           0 :         fE=freqStart;
    7404             :       }
    7405             :     
    7406           0 :       if(ms==String("")){
    7407           0 :         rvi_p->getSpwInFreqRange(bspw, bstart, bnchan, fS, fE, fabs(freqStep), freqframe);
    7408             :       }
    7409             :       else{
    7410           0 :         bnchan.resize(1);
    7411           0 :         bstart.resize(1);
    7412           0 :         bspw.resize(1);
    7413           0 :         MeasurementSet elms(String(ms), TableLock(TableLock::AutoNoReadLocking), Table::Old);
    7414           0 :         MSUtil::getSpwInFreqRange(bspw[0], bstart[0], bnchan[0], elms, fS, fE, fabs(freqStep), freqframe, field_id);
    7415           0 :         elms.relinquishAutoLocks(true);
    7416             : 
    7417           0 :       }
    7418           0 :       spw=Vector<Vector<Int> >(bspw.begin( ), bspw.end( ));
    7419           0 :       start=Vector<Vector<Int> >(bstart.begin( ), bstart.end( ));
    7420           0 :       nchan=Vector<Vector<Int> >(bnchan.begin( ), bnchan.end( ));
    7421           0 :     }
    7422             :     else{
    7423           0 :       if(ms==String("")){
    7424           0 :         rvi_p->getFreqInSpwRange(freqStart, freqEnd, freqframe);
    7425             :       }
    7426             :       else{
    7427           0 :         MeasurementSet elms(ms, TableLock(TableLock::AutoNoReadLocking), Table::Old);
    7428           0 :         MSSelection thisSelection;
    7429           0 :         String spsel=spwselection;
    7430           0 :         if(spsel=="")spsel="*";
    7431           0 :         thisSelection.setSpwExpr(spsel);
    7432           0 :         TableExprNode exprNode=thisSelection.toTableExprNode(&elms);
    7433           0 :         Matrix<Int> chanlist=thisSelection.getChanList();
    7434           0 :         if(chanlist.ncolumn() <3){
    7435           0 :           freqStart=-1.0;
    7436           0 :           freqEnd=-1.0;
    7437           0 :           return false;
    7438             :         }
    7439           0 :         Vector<Int> elspw=chanlist.column(0);
    7440           0 :         Vector<Int> elstart=chanlist.column(1);
    7441           0 :         Vector<Int> elnchan=Vector<Int> (chanlist.column(2)-elstart)+1;
    7442           0 :         MSUtil::getFreqRangeInSpw(freqStart, freqEnd, elspw, elstart, elnchan, elms, freqframe, field_id);
    7443           0 :       }
    7444             : 
    7445             :     }
    7446             : 
    7447             : 
    7448             : 
    7449             :         
    7450           0 :   } catch (AipsError x) {
    7451             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    7452           0 :        << LogIO::POST;
    7453           0 :     return false;
    7454           0 :   } 
    7455           0 :   catch (...){
    7456             :     os << LogIO::SEVERE << "Unknown  exception handled" 
    7457           0 :        << LogIO::POST;
    7458           0 :     return false;
    7459             : 
    7460           0 :   }
    7461             : 
    7462           0 :   return true;
    7463             : 
    7464           0 : }
    7465             : 
    7466             : 
    7467             : 
    7468             : } //# NAMESPACE CASA - END
    7469             : 

Generated by: LCOV version 1.16