LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - Imager.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 115 3894 3.0 %
Date: 2024-10-28 15:53:10 Functions: 3 78 3.8 %

          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           4 : Imager::Imager() 
     194           4 :   :  msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), ft_p(0), 
     195           4 :      cft_p(0), se_p(0),
     196           4 :      sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false), 
     197           4 :      mssFreqSel_p(), mssChanSel_p(),
     198           4 :      clean_panel_p(0), image_id_p(0), mask_id_p(0), 
     199          12 :       prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
     200             : {
     201           4 :   ms_p=0;
     202           4 :   mssel_p=0;
     203           4 :   lockCounter_p=0;
     204           4 :   numMS_p=0;
     205           4 :   defaults();
     206           4 : };
     207             : 
     208             : 
     209           4 : void Imager::defaults() 
     210             : {
     211             : 
     212           4 :   setimaged_p=false;
     213           4 :   nullSelect_p=false;
     214           4 :   nx_p=128; ny_p=128; facets_p=1;
     215           4 :   wprojPlanes_p=-1;
     216           4 :   mcellx_p=Quantity(1, "arcsec"); mcelly_p=Quantity(1, "arcsec");
     217           4 :   shiftx_p=Quantity(0.0, "arcsec"); shifty_p=Quantity(0.0, "arcsec");
     218           4 :   distance_p=Quantity(0.0, "m");
     219           4 :   stokes_p="I"; npol_p=1;
     220           4 :   nscales_p=5;
     221           4 :   ntaylor_p=1;
     222           4 :   reffreq_p=0.0;
     223           4 :   useNewMTFT_p=false;
     224           4 :   scaleMethod_p="nscales";  
     225           4 :   scaleInfoValid_p=false;
     226           4 :   dataMode_p="none";
     227           4 :   imageMode_p="MFS";
     228           4 :   dataNchan_p=0;
     229           4 :   imageNchan_p=0;
     230           4 :   doVP_p=false;
     231           4 :   doDefaultVP_p = true;
     232           4 :   parAngleInc_p=Quantity(360.,"deg");
     233           4 :   skyPosThreshold_p=Quantity(180.,"deg");
     234           4 :   telescope_p="";
     235           4 :   gridfunction_p="SF";
     236           4 :   minWeight_p=0.;
     237           4 :   clipminmax_p=false;
     238           4 :   doMultiFields_p=false;
     239           4 :   doWideBand_p=false;
     240           4 :   multiFields_p=false;
     241             :   // Use half the machine memory as cache. The user can override
     242             :   // this via the setoptions function().
     243           4 :   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           4 :   if(cache_p <=0 )
     247           0 :     cache_p=2000000000/8;
     248           4 :   tile_p=16;
     249           4 :   ftmachine_p="ft";
     250           4 :   wfGridding_p=false;
     251           4 :   padding_p=1.2;
     252           4 :   sdScale_p=1.0;
     253           4 :   sdWeight_p=1.0;
     254           4 :   sdConvSupport_p=-1;
     255             : 
     256           4 :   doShift_p=false;
     257           4 :   spectralwindowids_p.resize(1); 
     258           4 :   spectralwindowids_p=0;
     259           4 :   fieldid_p=0;
     260           4 :   dataspectralwindowids_p.resize(0); 
     261           4 :   datadescids_p.resize(0);
     262           4 :   datafieldids_p.resize(0);
     263           4 :   mImageStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     264           4 :   mImageStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     265           4 :   mDataStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     266           4 :   mDataStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
     267           4 :   beamValid_p=false;
     268           4 :   beam_p = ImageBeamSet();
     269           4 :   images_p.resize(0);
     270           4 :   masks_p.resize(0);
     271           4 :   fluxMasks_p.resize(0);
     272           4 :   residuals_p.resize(0);
     273           4 :   componentList_p=0;
     274             : 
     275           4 :   cyclefactor_p = 1.5;
     276           4 :   cyclespeedup_p =  -1;
     277           4 :   cyclemaxpsffraction_p = 0.8;
     278           4 :   stoplargenegatives_p = 2;
     279           4 :   stoppointmode_p = -1;
     280           4 :   fluxscale_p.resize(0);
     281           4 :   scaleType_p = "NONE";
     282           4 :   minPB_p = 0.1;
     283           4 :   constPB_p = 0.4;
     284           4 :   redoSkyModel_p=true;
     285           4 :   nmodels_p=0;
     286           4 :   useModelCol_p=false;
     287           4 :   freqFrameValid_p=false;
     288           4 :   doTrackSource_p=false;
     289           4 :   freqInterpMethod_p="nearest";
     290           4 :   pointingDirCol_p="DIRECTION";
     291           4 :   logSink_p=LogSink(LogMessage::NORMAL, false);
     292           4 :   imwgt_p=VisImagingWeight();
     293           4 :   smallScaleBias_p=0.6;
     294           4 :   freqFrame_p=MFrequency::LSRK;
     295           4 :   imageTileVol_p=0;
     296           4 :   singlePrec_p=false;
     297           4 :   spwchansels_p.resize();
     298           4 :   flatnoise_p=true;
     299           4 :   freqrange_p.resize();
     300           4 :   numthreads_p=-1;
     301           4 :   avoidTempLatt_p=false;
     302           4 :   mssFreqSel_p.resize();
     303           4 :   mssChanSel_p.resize();
     304           4 :   projection_p=String("SIN");
     305             : 
     306           4 : }
     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           4 : Imager::~Imager()
     432             : {
     433             :   try{
     434           4 :     destroySkyEquation();
     435           4 :     this->unlock(); //unlock things if they are in a locked state
     436             :     
     437             :     //if (mssel_p) {
     438             :     //  delete mssel_p;
     439             :     // }
     440           4 :     mssel_p = 0;
     441             :     //if (ms_p) {
     442             :     //  delete ms_p;
     443             :     //}
     444           4 :     ms_p = 0;
     445           4 :     if (vs_p) {
     446           0 :       delete vs_p;
     447             :     }
     448           4 :     if(rvi_p)
     449           0 :       delete rvi_p;
     450           4 :     rvi_p=wvi_p=0;
     451             : 
     452           4 :     vs_p = 0;
     453           4 :     if (ft_p) {
     454           0 :       delete ft_p;
     455             :     }
     456             :     
     457             :     
     458           4 :     ft_p = 0;
     459           4 :     if (cft_p) {
     460           0 :       delete cft_p;
     461             :     }
     462           4 :     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           4 : }
     491             : 
     492             : 
     493           0 : Bool Imager::open(MeasurementSet& theMs, Bool /*compress*/, Bool useModelCol)
     494             : {
     495             : 
     496           0 :   LogIO os(LogOrigin("Imager", "open()", WHERE));
     497             :   
     498           0 :   if (!ms_p.null()) {
     499           0 :     *ms_p = theMs;
     500             :   } else {
     501           0 :     ms_p = new MeasurementSet(theMs);
     502           0 :     AlwaysAssert(!ms_p.null(), AipsError);
     503             :   }
     504             :   
     505             : 
     506             :   try {
     507           0 :     this->openSubTables();
     508           0 :     this->lock();
     509           0 :     msname_p = ms_p->tableName();
     510             :     
     511           0 :     os << "Opening MeasurementSet " << msname_p << LogIO::POST;
     512             : 
     513             :     // Check for DATA or FLOAT_DATA column
     514           0 :     if(!ms_p->tableDesc().isColumn("DATA") && 
     515           0 :        !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           0 :     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           0 :     mssel_p=new MeasurementSet(*ms_p);
     542           0 :     useModelCol_p=useModelCol;
     543             :     
     544             :     // Now create the VisSet
     545           0 :     this->makeVisSet(*mssel_p);
     546           0 :     AlwaysAssert(rvi_p, AipsError);
     547             :     
     548             :     // Polarization
     549           0 :     MSColumns msc(*mssel_p);
     550           0 :     Vector<String> polType=msc.feed().polarizationType()(0);
     551           0 :     if (polType(0)!="X" && polType(0)!="Y" &&
     552           0 :         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           0 :     numMS_p=1;
     559             : 
     560           0 :     this->unlock();
     561             : 
     562           0 :     return true;
     563           0 :   } 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           0 : }
     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")) > C::pi) || (abs(Double(ny)*celly.getValue("rad")) > C::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(C::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(C::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           0 : 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           0 :   LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
    1243           0 :   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           0 :   MRadialVelocity dummy;
    1258             :   //Calling the old setdata
    1259           0 :   return   setdata(mode, nchan, start, step, dummy, dummy, spectralwindowids, 
    1260             :                    fieldids, msSelect, timerng, fieldnames, antIndex, 
    1261           0 :                    antnames, spwstring, uvdist, scan, intent, obs, useModelCol);
    1262             : 
    1263           0 : }
    1264             : 
    1265             : 
    1266           0 : 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           0 :   logSink_p.clearLocally();
    1282           0 :   LogIO os(LogOrigin("imager", "data selection"), logSink_p);
    1283             : 
    1284           0 :   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           0 :      <<  " start=" << start << " step=" << step;
    1294           0 :   ostringstream clicom;
    1295           0 :   clicom <<  " mstart='" << mStart << "' mstep='" << mStep;
    1296           0 :   os << String(clicom) ;
    1297             :   os <<  "' spectralwindowids=" << spectralwindowids
    1298           0 :      << " fieldids=" << fieldids << " msselect=" << msSelect;
    1299             : 
    1300           0 :   nullSelect_p=false;
    1301           0 :   String local_spwstring(spwstring);
    1302           0 :   if (local_spwstring  == "") local_spwstring="*";
    1303             :   try {
    1304             :     
    1305           0 :     this->lock();
    1306           0 :     this->writeCommand(os);
    1307             : 
    1308             :     os << (be_calm ? LogIO::NORMAL2 : LogIO::NORMAL)
    1309           0 :        << "Performing selection on MeasurementSet : " << ms_p->tableName()
    1310           0 :        << LogIO::POST; // Loglevel PROGRESS
    1311             :     //Some MSSelection 
    1312           0 :     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           0 :     datafieldids_p.resize(fieldids.nelements());
    1323           0 :     datafieldids_p = fieldids;
    1324           0 :     if(datafieldids_p.nelements() > 0){
    1325           0 :       thisSelection.setFieldExpr(MSSelection::indexExprStr(datafieldids_p));
    1326             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1327           0 :          << "Selecting on field ids : " << datafieldids_p <<  LogIO::POST;
    1328             :     }
    1329           0 :     if(fieldnames != ""){
    1330           0 :       thisSelection.setFieldExpr(fieldnames);
    1331             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1332           0 :          << "Selecting on fields : " << fieldnames << LogIO::POST;
    1333             :     }
    1334             :     
    1335           0 :     dataspectralwindowids_p.resize(spectralwindowids.nelements());
    1336           0 :     dataspectralwindowids_p = spectralwindowids;
    1337           0 :     if(dataspectralwindowids_p.nelements() > 0){
    1338           0 :       thisSelection.setSpwExpr(MSSelection::indexExprStr(dataspectralwindowids_p));
    1339             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1340           0 :          << "Selecting on spectral windows" << LogIO::POST;
    1341             :     }
    1342           0 :     else if(local_spwstring != ""){
    1343             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1344             :          << "Selecting on spectral windows expression : " << local_spwstring
    1345           0 :          << LogIO::POST;
    1346           0 :       thisSelection.setSpwExpr(local_spwstring);
    1347             :     }
    1348             :     
    1349           0 :     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           0 :     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           0 :     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           0 :     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           0 :     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           0 :     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           0 :     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           0 :     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           0 :     TableExprNode exprNode;
    1398             :     try{
    1399           0 :       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           0 :     if(ft_p)
    1418           0 :       delete ft_p;
    1419           0 :     ft_p=0;
    1420           0 :     dataMode_p=mode;
    1421           0 :     dataNchan_p.resize();
    1422           0 :     dataStart_p.resize();
    1423           0 :     dataStep_p.resize();
    1424           0 :     dataNchan_p=nchan;
    1425           0 :     dataStart_p=start;
    1426           0 :     dataStep_p=step;
    1427           0 :     mDataStart_p=mStart;
    1428           0 :     mDataStep_p=mStep;
    1429             :     //    useModelCol_p=useModelCol;
    1430             :     
    1431           0 :     if(rvi_p)
    1432           0 :       delete rvi_p; 
    1433           0 :     rvi_p=0;
    1434           0 :     wvi_p=0;
    1435             :     // if(mssel_p) delete mssel_p; 
    1436           0 :     mssel_p=0;
    1437             :     
    1438           0 :     datafieldids_p.resize();
    1439           0 :     datafieldids_p=thisSelection.getFieldList();
    1440           0 :     if(datafieldids_p.nelements()==0){
    1441           0 :       Int nf=ms_p->field().nrow();
    1442           0 :       datafieldids_p.resize(nf);
    1443           0 :       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           0 :     Matrix<Int> chansels=thisSelection.getChanList(NULL, 1, true);
    1455           0 :     mssChanSel_p.assign(chansels);
    1456           0 :     mssFreqSel_p.resize();
    1457           0 :     mssFreqSel_p=thisSelection.getChanFreqList(NULL, true);
    1458             : 
    1459             :     //cout<<"chansels="<<chansels<<endl;
    1460             :     //convert the selection into flag
    1461           0 :     uInt nms = 1;
    1462           0 :     uInt nrow = chansels.nrow();
    1463           0 :     dataspectralwindowids_p.resize();
    1464           0 :     const MSSpWindowColumns spwc(ms_p->spectralWindow());
    1465           0 :     uInt nspw = spwc.nrow();
    1466           0 :     const ScalarColumn<Int> spwNchans(spwc.numChan());
    1467           0 :     Vector<Int> nchanvec = spwNchans.getColumn();
    1468           0 :     Int maxnchan = 0;
    1469           0 :     for (uInt i=0;i<nchanvec.nelements();i++) {
    1470           0 :       maxnchan=max(nchanvec[i],maxnchan);
    1471             :     }
    1472             :     
    1473           0 :     spwchansels_p.resize(nms,nspw,maxnchan);
    1474           0 :     spwchansels_p.set(0);
    1475           0 :     uInt nselspw=0;
    1476           0 :     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           0 :       spwchansels_p=0; //deselect
    1483           0 :       Int prvspwid=-1;
    1484           0 :       Vector<Int> selspw;
    1485           0 :       for (uInt i=0;i<nrow;i++) {
    1486           0 :         Vector<Int> sel = chansels.row(i);
    1487           0 :         Int spwid = sel[0];
    1488           0 :         if((sel[1] >= nchanvec[spwid]) || (sel[2] >=nchanvec[spwid]))
    1489           0 :           throw(AipsError("Unexpected selection  in spw selection of spwid "+String::toString(spwid)));
    1490           0 :         if (spwid != prvspwid){
    1491           0 :           nselspw++;
    1492           0 :           selspw.resize(nselspw,true);
    1493           0 :           selspw[nselspw-1]=spwid;
    1494             :         }
    1495           0 :         uInt minc= sel[1];
    1496           0 :         uInt maxc = sel[2];
    1497           0 :         uInt step = sel[3];
    1498             :         // step as the same context as in im.selectvis
    1499             :         // select channels 
    1500           0 :         for (uInt k=minc;k<(maxc+1);k+=step) {
    1501           0 :           spwchansels_p(0,spwid,k)=1;
    1502             :         }
    1503           0 :         prvspwid=spwid;
    1504           0 :       }
    1505           0 :       dataspectralwindowids_p=selspw;
    1506           0 :     }
    1507             :     
    1508             :     // Map the selected spectral window ids to data description ids
    1509           0 :     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           0 :     MSDataDescIndex msDatIndex(ms_p->dataDescription());
    1515           0 :     datadescids_p.resize(0);
    1516           0 :     datadescids_p=msDatIndex.matchSpwId(dataspectralwindowids_p);
    1517             :     
    1518           0 :     if (datafieldids_p.nelements() > 1) {
    1519           0 :       os << LogIO::NORMAL4<< "Multiple fields specified" << LogIO::POST;
    1520           0 :       multiFields_p = true;
    1521             :     }
    1522             :     
    1523             :     
    1524           0 :     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           0 :       if(nselspw==dataspectralwindowids_p.nelements()){
    1533             :         
    1534           0 :         dataMode_p="channel";
    1535           0 :         dataStep_p.resize(dataspectralwindowids_p.nelements());
    1536           0 :         dataStart_p.resize(dataspectralwindowids_p.nelements());
    1537           0 :         dataNchan_p.resize(dataspectralwindowids_p.nelements());
    1538           0 :         Cube<Int> spwchansels_tmp=spwchansels_p;
    1539             :         
    1540           0 :         for (uInt k =0 ; k < dataspectralwindowids_p.nelements(); ++k){
    1541           0 :           uInt curspwid=dataspectralwindowids_p[k];
    1542             :           //dataStep_p[k]=1;
    1543           0 :           if (nrow > 0) {
    1544           0 :             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           0 :           dataStart_p[k]=0;
    1551           0 :           dataNchan_p[k]=nchanvec(curspwid);
    1552             :           //find start
    1553           0 :           Bool first =true;
    1554           0 :           uInt nchn = 0;
    1555           0 :           uInt lastchan = 0;
    1556           0 :           for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++) {
    1557           0 :             if (spwchansels_p(0,curspwid,j)==1) {
    1558           0 :               if (first) {
    1559           0 :                 dataStart_p[k]=j;
    1560           0 :                 first = false;
    1561             :               }
    1562           0 :               lastchan=j;
    1563           0 :               nchn++;
    1564             :             }   
    1565             :           }
    1566           0 :           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           0 :           for (uInt j=0  ; j < uInt(nchanvec(curspwid)); j++){
    1579           0 :             if ( Int(j) < nchanvec(curspwid)-dataStart_p[k]) {
    1580           0 :               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           0 :         spwchansels_p = spwchansels_tmp;
    1588           0 :       }
    1589             :     }
    1590           0 :     if(!(exprNode.isNull())){
    1591           0 :       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           0 :     AlwaysAssert(!mssel_p.null(), AipsError);
    1599           0 :     if(mssel_p->nrow()==0) {
    1600             :       //delete mssel_p; 
    1601           0 :       mssel_p=0;
    1602             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::WARN)
    1603             :          << "Selection is empty: reverting to sorted MeasurementSet"
    1604           0 :          << LogIO::POST;
    1605           0 :       mssel_p=new MeasurementSet(*ms_p);
    1606           0 :       nullSelect_p=true;
    1607             :     }
    1608             :     else {
    1609           0 :       mssel_p->flush();
    1610           0 :       nullSelect_p=false;
    1611             :     }
    1612           0 :     if (nullSelect_p) {
    1613           0 :       if ((mssel_p->field()).nrow() > 1) {
    1614           0 :         os << LogIO::NORMAL4 << "Multiple fields selected" << LogIO::POST;
    1615           0 :         multiFields_p = true;
    1616             :       } else {
    1617           0 :         os << LogIO::NORMAL4 << "Single field selected" << LogIO::POST;
    1618           0 :         multiFields_p = false;
    1619             :       }
    1620             :     }
    1621             :     
    1622           0 :     uInt nvis_all = ms_p->nrow();
    1623             :     
    1624             :     // Now create the VisSet
    1625           0 :     this->makeVisSet(*mssel_p); 
    1626           0 :     AlwaysAssert(rvi_p, AipsError);
    1627           0 :     uInt nvis_sel = mssel_p->nrow();
    1628             :     
    1629           0 :     if(nvis_sel != nvis_all) {
    1630             :       os << LogIO::NORMAL // Loglevel INFO
    1631             :          << "Selected " << nvis_sel << " out of "
    1632             :          << nvis_all << " rows."
    1633           0 :          << LogIO::POST;
    1634             :     }
    1635             :     else {
    1636             :       os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
    1637           0 :          << "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           0 :     Vector<Int> chancounts(dataspectralwindowids_p.nelements());
    1644           0 :     chancounts=0;
    1645             :     //    if( local_spwstring == "" ) os << "Selected all spws and channels" << LogIO::POST;
    1646             :     //else os << "Channel selection : " << local_spwstring << LogIO::POST;
    1647           0 :     os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL) << "Selected:";
    1648           0 :     for(uInt k=0;k<dataspectralwindowids_p.nelements();k++)
    1649             :       {
    1650           0 :         for(uInt ch=0;ch<uInt(nchanvec(dataspectralwindowids_p[k]));ch++) 
    1651           0 :           {if(spwchansels_p(0,dataspectralwindowids_p[k],ch)) chancounts[k]++; }
    1652           0 :         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           0 :     os << LogIO::POST;
    1657             : 
    1658             :     // Now we do a selection to cut down the amount of information
    1659             :     // passed around.
    1660             :   
    1661           0 :     this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
    1662           0 :                             dataNchan_p, dataStart_p, dataStep_p,
    1663           0 :                             mDataStart_p, mDataStep_p);
    1664             :     ///Tell iterator to use on the fly imaging weights if scratch columns is
    1665             :     ///not in use
    1666           0 :     imwgt_p=VisImagingWeight("natural");
    1667           0 :     rvi_p->useImagingWeight(imwgt_p);
    1668             :     
    1669             :     // Guess that the beam is no longer valid
    1670           0 :     beamValid_p=false;
    1671           0 :     destroySkyEquation();
    1672           0 :     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           0 :     this->unlock();
    1679           0 :     return !nullSelect_p;
    1680           0 :   } catch (AipsError x) {
    1681           0 :     this->unlock();
    1682           0 :     throw(x);
    1683             :    
    1684             :     return false;
    1685           0 :   } 
    1686             :   return !nullSelect_p;
    1687           0 : }
    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           0 : 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           0 :   LogIO os(LogOrigin("Imager", "setvp()", WHERE));
    1728             :   
    1729           0 :   os << LogIO::NORMAL << "Setting voltage pattern parameters" << LogIO::POST; // Loglevel PROGRESS
    1730             :   
    1731           0 :   if(!dovp && !vp_p)
    1732           0 :     delete vp_p;
    1733           0 :   vp_p=0;
    1734           0 :   doVP_p=dovp;
    1735           0 :   doDefaultVP_p = doDefaultVPs;
    1736           0 :   vpTableStr_p = vpTable;
    1737           0 :   telescope_p= defaultTel;
    1738           0 :   if (doSquint) {
    1739           0 :     squintType_p = BeamSquint::GOFIGURE;
    1740             :   } else {
    1741           0 :     squintType_p = BeamSquint::NONE;
    1742             :   }
    1743             : 
    1744           0 :   parAngleInc_p = parAngleInc;
    1745             : 
    1746           0 :   skyPosThreshold_p = skyPosThreshold;
    1747             :   os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1748             :      <<"Sky position tolerance is "<<skyPosThreshold_p.getValue("deg")
    1749           0 :      << " degrees" << LogIO::POST;
    1750             : 
    1751           0 :   if (doDefaultVP_p) {
    1752             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1753           0 :        << "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           0 :   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           0 :   destroySkyEquation();
    1769           0 :   return true;
    1770           0 : }
    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           0 : 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           0 :   LogIO os(LogOrigin("imager", "setsdoptions()", WHERE));
    1882             :   
    1883           0 :   os << LogIO::NORMAL << "Setting single dish processing options" << LogIO::POST; // Loglevel PROGRESS
    1884             :   
    1885           0 :   sdScale_p=scale;
    1886           0 :   sdWeight_p=weight;
    1887             : 
    1888             :   
    1889           0 :   sdConvSupport_p=convsupport;
    1890           0 :   pointingDirCol_p=pointCol;
    1891           0 :   pointingDirCol_p.upcase();
    1892           0 :   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           0 :   qtruncate_p=truncate;
    1898           0 :   qgwidth_p=gwidth;
    1899           0 :   qjwidth_p=jwidth;
    1900           0 :   minWeight_p = minweight;
    1901           0 :   clipminmax_p = clipminmax;
    1902           0 :   enablecache_p = enablecache;
    1903           0 :   convertfirst_p = convertfirst;
    1904           0 :   convertfirst_p.upcase();
    1905             : 
    1906             : 
    1907             :   // Destroy the FTMachine
    1908           0 :   if(ft_p) {delete ft_p; ft_p=0;}
    1909           0 :   if(gvp_p) {delete gvp_p; gvp_p=0;}
    1910           0 :   if(cft_p) {delete cft_p; cft_p=0;}
    1911             : 
    1912           0 :   return true;
    1913           0 : }
    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           0 : 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           0 :   Float effDiam=effDishDiam;
    2177           0 :   LoggerHolder lh (false);
    2178           0 :   LogIO os = lh.logio();
    2179           0 :   os << LogOrigin("imager", "feather()");
    2180             :   
    2181             :   try {
    2182           0 :     Bool noStokes=false;
    2183           0 :     String outLowRes=lowRes;
    2184           0 :     String outHighRes=highRes;
    2185             :     {
    2186           0 :       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           0 :          << "\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           0 :       PagedImage<Float> high(outHighRes);
    2233           0 :       PagedImage<Float> low0(outLowRes);
    2234             :       
    2235           0 :       Feather::feather(image, high, low0, sdScale_p, lowPSF, doDefaultVP_p, vpTableStr_p, effDiam, lowPassFilterSD);
    2236           0 :     }
    2237             :   
    2238           0 :     if(noStokes){
    2239           0 :       TableUtil::deleteTable(outHighRes);
    2240           0 :       TableUtil::deleteTable(outLowRes);
    2241             :     }
    2242           0 :     return true;
    2243           0 :   } catch (AipsError x) {
    2244             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2245           0 :        << LogIO::EXCEPTION;
    2246           0 :     return false;
    2247           0 :   } 
    2248             :   
    2249             :   return true;
    2250           0 : }
    2251             : 
    2252             : 
    2253             : 
    2254           0 : Bool Imager::linearmosaic(const String& mosaic,
    2255             :                           const String& fluxscale,
    2256             :                           const String& sensitivity,
    2257             :                           const Vector<String>& images,
    2258             :                           const Vector<Int>& fieldids)
    2259             : 
    2260             : {
    2261           0 :   if(!valid()) return false;
    2262           0 :   LogIO os(LogOrigin("imager", "linearmosaic()", WHERE));
    2263             :   try{
    2264           0 :     if(mosaic=="") {
    2265           0 :       os << LogIO::SEVERE << "Need name for mosaic image" << LogIO::POST;
    2266           0 :       return false;
    2267             :     }
    2268           0 :     if(!Table::isWritable( mosaic )) {
    2269           0 :       make( mosaic );
    2270             :     }
    2271           0 :     if (images.nelements() == 0) {
    2272           0 :       os << LogIO::SEVERE << "Need names of images to mosaic" << LogIO::POST;
    2273           0 :       return false;
    2274             :     }
    2275           0 :     if (images.nelements() != fieldids.nelements()) {
    2276             :       os << LogIO::SEVERE << "number of fieldids doesn\'t match the" 
    2277           0 :          << " number of images" << LogIO::POST;
    2278           0 :       return false;
    2279             :     }
    2280             :     
    2281           0 :     Double meminMB=Double(HostInfo::memoryTotal(true))/1024.0;
    2282           0 :     PagedImage<Float> mosaicImage( mosaic );
    2283           0 :     CoordinateSystem cs=mosaicImage.coordinates();
    2284           0 :     String err;
    2285             :     //for some reason subimages below  fail if they are in some frames like BARY
    2286           0 :     if(cs.setSpectralConversion(err, "LSRK")){
    2287           0 :       mosaicImage.setCoordinateInfo(cs);
    2288             :     }
    2289           0 :     mosaicImage.set(0.0);
    2290           0 :     TempImage<Float>  numerator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
    2291           0 :     numerator.set(0.0);
    2292           0 :     TempImage<Float>  denominator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
    2293           0 :     denominator.set(0.0);
    2294           0 :     ImageRegrid<Float> regridder;
    2295             :     
    2296           0 :     MSColumns msc(*ms_p);
    2297           0 :     for (uInt i=0; i < images.nelements(); ++i) {
    2298           0 :       if(!Table::isReadable(images(i))) {   
    2299             :         os << LogIO::SEVERE << "Image " << images(i) << 
    2300           0 :           " is not readable" << LogIO::POST;
    2301           0 :         return false;
    2302             :       }
    2303             :       
    2304           0 :       PagedImage<Float> smallImagedisk( images(i) );
    2305           0 :       cs=smallImagedisk.coordinates();
    2306             :       //for some reason subimages below  fail if they are in some frames like BARY
    2307           0 :       if(!cs.setSpectralConversion(err, "LSRK")){
    2308           0 :         cs=smallImagedisk.coordinates();
    2309             :       }
    2310             :       
    2311           0 :       TempImage<Float> smallImage(smallImagedisk.shape(), cs, meminMB/8.0);
    2312           0 :       smallImage.copyData(smallImagedisk);
    2313           0 :       IPosition iblc(smallImage.shape().nelements(),0);
    2314           0 :       IPosition itrc(smallImage.shape());
    2315           0 :       itrc=itrc-Int(1);
    2316             :       
    2317           0 :       LCBox lbox(iblc, itrc, smallImage.shape());
    2318           0 :       ImageRegion imagreg(WCBox(lbox, cs) );
    2319             :       try{
    2320             :         // accumulate the images
    2321           0 :         SubImage<Float> subNum;
    2322           0 :         SubImage<Float> subDen;
    2323             :         try{
    2324           0 :           subNum=SubImage<Float>(numerator, imagreg, true);
    2325           0 :           subDen=SubImage<Float>(denominator, imagreg, true);
    2326             :         }
    2327           0 :         catch(...){
    2328             :           //Failed to make a subimage let us use the full image
    2329           0 :           subNum=SubImage<Float>(numerator, true);
    2330           0 :           subDen=SubImage<Float>(denominator, true);
    2331             :           
    2332           0 :         }
    2333             :         
    2334             :         
    2335             :         
    2336           0 :         TempImage<Float> fullImage(subNum.shape(), subNum.coordinates(), meminMB/8.0);
    2337             :         
    2338           0 :         os  << "Processing Image " << images(i)  << LogIO::POST;
    2339             :         
    2340           0 :         regridder.regrid( fullImage, Interpolate2D::LINEAR,
    2341           0 :                           IPosition(2,0,1), smallImage );
    2342             :         
    2343           0 :         TempImage<Float>  PB( subNum.shape(), subNum.coordinates(), meminMB/8.0);
    2344           0 :         PB.set(1.0);
    2345             :         
    2346           0 :         MDirection pointingDirection = msc.field().phaseDirMeas( fieldids(i) );
    2347             :         
    2348           0 :         Quantity pa(0.0, "deg");
    2349           0 :         pbguts ( PB, PB, pointingDirection, pa);
    2350             :         
    2351           0 :         fullImage.copyData( (LatticeExpr<Float>) (fullImage *  PB ) );
    2352           0 :         subNum.copyData( (LatticeExpr<Float>) (subNum + fullImage) );
    2353           0 :         subDen.copyData( (LatticeExpr<Float>) (subDen + (PB*PB)) );
    2354             :         
    2355           0 :       }
    2356           0 :       catch (AipsError x) {
    2357             :         os << LogIO::WARN<< "Caught exception while processing  " << images(i) 
    2358             :            << "\n"<< x.getMesg()
    2359           0 :            << LogIO::POST;
    2360           0 :         continue;
    2361           0 :       } 
    2362           0 :       catch(...){
    2363           0 :         os << LogIO::WARN << "Unknown error processing " << images(i) << LogIO::POST; 
    2364           0 :         continue;
    2365           0 :       }
    2366           0 :     }
    2367             :     
    2368           0 :     LatticeExprNode LEN = max( denominator );
    2369           0 :     Float dMax =  LEN.getFloat();
    2370             :     
    2371             :     
    2372           0 :     if (scaleType_p == "SAULT") {
    2373             :       
    2374             :       // truncate denominator at ggSMin1
    2375           0 :       denominator.copyData( (LatticeExpr<Float>) 
    2376           0 :                             (iif(denominator < (dMax * constPB_p), dMax, 
    2377             :                                  denominator) ) );
    2378             :       
    2379           0 :       if (fluxscale != "") {
    2380           0 :         clone( mosaic, fluxscale );
    2381             :         
    2382           0 :         PagedImage<Float> fluxscaleImage( fluxscale );
    2383           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>) 
    2384           0 :                                  (iif(denominator < (dMax*minPB_p), 0.0,
    2385           0 :                                       (dMax*minPB_p)/(denominator) )) );
    2386           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>) 
    2387           0 :                                  (iif(denominator > (dMax*constPB_p), 1.0,
    2388             :                                       (fluxscaleImage) )) );
    2389           0 :         mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
    2390           0 :                                                        (numerator/denominator), 0)) );
    2391           0 :       }
    2392             :     } else {
    2393           0 :       mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
    2394           0 :                                                      (numerator/denominator), 0)) );
    2395           0 :       if (fluxscale != "") {
    2396           0 :         clone(mosaic, fluxscale );
    2397           0 :         PagedImage<Float> fluxscaleImage( fluxscale );
    2398           0 :         fluxscaleImage.copyData( (LatticeExpr<Float>)( 1.0 ) );
    2399           0 :       }
    2400             :     }
    2401           0 :     if (sensitivity != "") {
    2402           0 :       clone(mosaic, sensitivity);
    2403           0 :       PagedImage<Float> sensitivityImage( sensitivity );
    2404           0 :       sensitivityImage.copyData( (LatticeExpr<Float>)( denominator/dMax ));
    2405           0 :     }
    2406           0 :   }
    2407           0 :   catch (AipsError x) {
    2408             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2409           0 :        << LogIO::POST;
    2410           0 :     return false;
    2411           0 :   } 
    2412           0 :   return true;
    2413           0 : }
    2414             : 
    2415             : // Weight the MeasurementSet
    2416           0 : Bool Imager::weight(const String& type, const String& crmode,
    2417             :                  const Quantity& noise, const Double robust,
    2418             :                  const Quantity& fieldofview,
    2419             :                     const Int npixels, const Bool multiField)
    2420             : {
    2421           0 :   if(!valid()) return false;
    2422           0 :   logSink_p.clearLocally();
    2423           0 :   LogIO os(LogOrigin("imager", "weight()"),logSink_p);
    2424             :   
    2425           0 :   this->lock();
    2426             :   try {
    2427             :     
    2428           0 :     String rmode=crmode; // can change it 
    2429             : 
    2430             : 
    2431             :     os << LogIO::NORMAL // Loglevel INFO
    2432           0 :        << "Weighting MS: Imaging weights will be changed" << LogIO::POST;
    2433             :     
    2434           0 :     if (type=="natural") {
    2435             :       os << LogIO::NORMAL // Loglevel INFO
    2436           0 :          << "Natural weighting" << LogIO::POST;
    2437           0 :       imwgt_p=VisImagingWeight("natural");
    2438             :     }
    2439           0 :     else if(type=="superuniform"){
    2440           0 :       if(!assertDefinedImageParameters()) return false;
    2441             :       ///making usage of npixels consistent with uniform, briggs
    2442             :       /// don't know why this was done seperately which is kind of redundant in the code
    2443             :       /// one achieves superuniform with  just uniform with npixels or fieldofview 
    2444             :       /// set to non-defaults in the section below
    2445           0 :       Int actualNpix=npixels/2;
    2446           0 :       if(actualNpix <=0)
    2447           0 :         actualNpix=3;
    2448             :       os << LogIO::NORMAL // Loglevel INFO
    2449             :          << "SuperUniform weighting over a square cell spanning [" 
    2450             :          << -actualNpix 
    2451           0 :          << ", " << actualNpix << "] in the uv plane" << LogIO::POST;
    2452           0 :       imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, nx_p, 
    2453           0 :                                ny_p, mcellx_p, mcelly_p, actualNpix, 
    2454           0 :                                actualNpix, multiField);
    2455             :     }
    2456           0 :     else if ((type=="robust")||(type=="uniform")||(type=="briggs")) {
    2457           0 :       if(!assertDefinedImageParameters()) return false;
    2458           0 :       Quantity actualFieldOfView(fieldofview);
    2459           0 :       Int actualNPixels(npixels);
    2460           0 :       String wtype;
    2461           0 :       if(type=="briggs") {
    2462             :         //The user really meant to use Brigg's weighting and forgot to set norm or abs
    2463             :         // guessing it should be norm
    2464           0 :         if(rmode=="none")
    2465           0 :           rmode="norm";
    2466           0 :         wtype = "Briggs";
    2467             :       }
    2468             :       else {
    2469           0 :         wtype = "Uniform";
    2470             :       }
    2471           0 :       if(actualFieldOfView.get().getValue()==0.0&&actualNPixels==0) {
    2472           0 :         actualNPixels=nx_p;
    2473           0 :         actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
    2474           0 :                                                                    "rad");
    2475             :         os << LogIO::NORMAL // Loglevel INFO
    2476             :            << wtype
    2477             :            << " weighting: sidelobes will be suppressed over full image"
    2478           0 :            << LogIO::POST;
    2479             :       }
    2480           0 :       else if(actualFieldOfView.get().getValue()>0.0&&actualNPixels==0) {
    2481           0 :         actualNPixels=Int(actualFieldOfView.get("rad").getValue()/mcellx_p.get("rad").getValue());
    2482             :         os << LogIO::NORMAL // Loglevel INFO
    2483             :            << wtype
    2484             :            << " weighting: sidelobes will be suppressed over specified field of view: "
    2485           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2486             :       }
    2487           0 :       else if(actualFieldOfView.get().getValue()==0.0&&actualNPixels>0) {
    2488           0 :         actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
    2489           0 :                                                                    "rad");
    2490             :         os << LogIO::NORMAL // Loglevel INFO
    2491             :            << wtype
    2492             :            << " weighting: sidelobes will be suppressed over full image field of view: "
    2493           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2494             :       }
    2495             :       else {
    2496             :         os << LogIO::NORMAL // Loglevel INFO
    2497             :            << wtype
    2498             :            << " weighting: sidelobes will be suppressed over specified field of view: "
    2499           0 :            << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
    2500             :       }
    2501             :       os << LogIO::DEBUG1
    2502             :          << "Weighting used " << actualNPixels << " uv pixels."
    2503           0 :          << LogIO::POST;
    2504           0 :       Quantity actualCellSize(actualFieldOfView.get("rad").getValue()/actualNPixels, "rad");
    2505             : 
    2506           0 :       imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, 
    2507             :                                actualNPixels, actualNPixels, actualCellSize, 
    2508           0 :                                actualCellSize, 0, 0, multiField);
    2509             :       
    2510           0 :     }
    2511           0 :     else if (type=="radial") {
    2512           0 :       os << "Radial weighting" << LogIO::POST;
    2513           0 :       imwgt_p=VisImagingWeight("radial");
    2514             :     }
    2515             :     else {
    2516           0 :       this->unlock();
    2517             :       os << LogIO::SEVERE << "Unknown weighting " << type
    2518           0 :          << LogIO::EXCEPTION;    
    2519           0 :       return false;
    2520             :     }
    2521             :     
    2522           0 :       rvi_p->useImagingWeight(imwgt_p);
    2523             :     
    2524             :     // Beam is no longer valid
    2525           0 :     beamValid_p=false;
    2526           0 :     destroySkyEquation();
    2527           0 :     this->writeHistory(os);
    2528           0 :     this->unlock();
    2529           0 :     return true;
    2530           0 :   } catch (AipsError x) {
    2531           0 :     this->unlock();
    2532             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    2533           0 :        << LogIO::EXCEPTION;
    2534           0 :     return false;
    2535           0 :   } 
    2536             :   
    2537             :   return true;
    2538           0 : }
    2539             : 
    2540             : 
    2541           0 : Bool Imager::getWeightGrid(Block<Matrix<Float> >&weightgrid, const String& type, const Vector<String>&imagenames){
    2542             : 
    2543           0 :   if(type=="imaging"){
    2544           0 :     weightgrid.resize(0, true, false);
    2545           0 :     if(imwgt_p.getType()!="uniform")
    2546           0 :       return false;
    2547           0 :     imwgt_p.getWeightDensity(weightgrid);
    2548           0 :     return true;
    2549             :   }
    2550           0 :   if((type=="ftweight") && (sm_p) && (Int(imagenames.nelements())== sm_p->numberOfModels())){
    2551           0 :     for (Int model=0; model < sm_p->numberOfModels(); ++model){
    2552           0 :       PagedImage<Float> wgtImage(sm_p->image(model).shape(),
    2553           0 :                                    (sm_p->image(model)).coordinates(),
    2554           0 :                                    imagenames(model));
    2555           0 :       se_p->getWeightImage(model, wgtImage);
    2556             :       
    2557             : 
    2558           0 :     }
    2559           0 :     return true;
    2560             :   } 
    2561             :         
    2562           0 :   return false;
    2563             : }
    2564             : 
    2565           0 : Bool Imager::setWeightGrid(const Block<Matrix<Float> >& weightgrid, const String& type){
    2566             : 
    2567           0 :   if(type=="imaging"){
    2568           0 :     if(imwgt_p.getType()!="uniform")
    2569           0 :       return false;
    2570           0 :     imwgt_p.setWeightDensity(weightgrid);
    2571           0 :     rvi_p->useImagingWeight(imwgt_p);
    2572             :   }
    2573             : 
    2574           0 :   return true;
    2575             : }
    2576             : 
    2577             : // Filter the MeasurementSet
    2578           0 : Bool Imager::filter(const String& type, const Quantity& bmaj,
    2579             :                  const Quantity& bmin, const Quantity& bpa)
    2580             : {
    2581           0 :   if(!valid()) return false;
    2582           0 :   logSink_p.clearLocally();
    2583           0 :   LogIO os(LogOrigin("imager", "filter()"),logSink_p);
    2584             :   
    2585           0 :   this->lock();
    2586             :   try {
    2587             :       
    2588             :     os << LogIO::NORMAL // Loglevel INFO
    2589           0 :        << "Imaging weights will be tapered" << LogIO::POST;
    2590           0 :     imwgt_p.setFilter(type, bmaj, bmin, bpa);
    2591           0 :     rvi_p->useImagingWeight(imwgt_p);
    2592             :       
    2593             :     // Beam is no longer valid
    2594           0 :     beamValid_p=false;
    2595           0 :     destroySkyEquation();
    2596           0 :     this->writeHistory(os);
    2597           0 :     this->unlock();
    2598           0 :     return true;
    2599           0 :   } catch (AipsError x) {
    2600           0 :     this->unlock();
    2601           0 :     throw(x);
    2602             :     return false;
    2603           0 :   } 
    2604             :   
    2605             :   return true;
    2606           0 : }
    2607             : 
    2608             : 
    2609             : // Implement a uv range
    2610           0 : Bool Imager::uvrange(const Double& uvmin, const Double& uvmax)
    2611             : {
    2612           0 :   if(!valid()) return false;
    2613           0 :   logSink_p.clearLocally();
    2614           0 :   LogIO os(LogOrigin("imager", "uvrange()"),logSink_p);
    2615             :   
    2616             :   try {
    2617             :     os << LogIO::NORMAL // Loglevel INFO
    2618             :        << "Selecting data according to  uvrange: setdata will reset this selection"
    2619           0 :        << LogIO::POST;
    2620             : 
    2621           0 :     Double auvmin(uvmin);
    2622           0 :     Double auvmax(uvmax);
    2623             : 
    2624           0 :     if(auvmax<=0.0) auvmax=1e10;
    2625           0 :     if(auvmax>auvmin&&(auvmin>=0.0)) {
    2626             :       os << LogIO::NORMAL // Loglevel INFO
    2627             :          << "Allowed uv range: " << auvmin << " to " << auvmax
    2628           0 :          << " wavelengths" << LogIO::POST;
    2629             :     }
    2630             :     else {
    2631             :       os << LogIO::SEVERE << "Invalid uvmin and uvmax: "
    2632             :          << auvmin << ", " << auvmax
    2633           0 :          << LogIO::EXCEPTION;
    2634           0 :       return false;
    2635             :     }
    2636           0 :     Vector<Double> freq;
    2637           0 :     ostringstream strUVmax, strUVmin, ostrInvLambda;
    2638             : 
    2639           0 :     this->lock();
    2640             :       
    2641           0 :     if(mssel_p.null()){ os << "Please setdata first before using uvrange " << LogIO::POST; return false; }
    2642             : 
    2643             : 
    2644             :      // use the average wavelength for the selected windows to convert
    2645             :      // uv-distance from lambda to meters
    2646           0 :      ostringstream spwsel;
    2647           0 :      spwsel << "select from $1 where ROWID() IN [";
    2648           0 :      for(uInt i=0; i < dataspectralwindowids_p.nelements(); ++i) {
    2649           0 :          if (i > 0) spwsel << ", ";
    2650           0 :          spwsel << dataspectralwindowids_p(i);
    2651             :      }
    2652           0 :      spwsel << "]";
    2653             : 
    2654           0 :      MSSpectralWindow msspw(tableCommand(spwsel.str(), 
    2655           0 :                                          mssel_p->spectralWindow()).table());
    2656           0 :      MSSpWindowColumns spwc(msspw);
    2657             : 
    2658             :      // This averaging scheme will work even if the spectral windows are
    2659             :      // of different sizes.  Note, however, that using an average wavelength
    2660             :      // may not be a good choice when the total range in frequency is 
    2661             :      // large (e.g. mfs across double sidebands).
    2662           0 :      uInt nrows = msspw.nrow();
    2663           0 :      Double ftot = 0.0;
    2664           0 :      Int nchan = 0;
    2665           0 :      for(uInt i=0; i < nrows; ++i) {
    2666           0 :          nchan += (spwc.numChan())(i);
    2667           0 :          ftot += sum((spwc.chanFreq())(i));
    2668             :      }
    2669           0 :      Double invLambda=ftot/(nchan*C::c);
    2670             : 
    2671             :      // This is message may not be helpful as mfs is set with setimage()
    2672             :      // which may sometimes get called after uvrange()
    2673           0 :      if (nrows > 1 && imageMode_p=="MFS") {
    2674             :          os << LogIO::WARN 
    2675             :             << "When using mfs over a broad range of frequencies, It is more "
    2676             :             << "accurate to " << endl 
    2677             :             << "constrain uv-ranges using setdata(); try: " << endl 
    2678             :             << "  msselect='(SQUARE(UVW[1]) + SQUARE(UVW[2])) > uvmin && "
    2679             :             << "(SQUARE(UVW[1]) + SQUARE(UVW[2])) < uvmax'" << endl
    2680             :             << "where [uvmin, uvmax] is the range given in meters." 
    2681           0 :             << LogIO::POST;
    2682             :      }
    2683             : 
    2684           0 :      invLambda=invLambda*invLambda;
    2685           0 :      auvmax=auvmax*auvmax;
    2686           0 :      auvmin=auvmin*auvmin;
    2687           0 :      strUVmax << auvmax; 
    2688           0 :      strUVmin << auvmin;
    2689           0 :      ostrInvLambda << invLambda; 
    2690           0 :      String strInvLambda=ostrInvLambda;
    2691             :      MeasurementSet* mssel_p2;
    2692             : 
    2693             :      // Apply the TAQL selection string, to remake the selected MS
    2694           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( );
    2695             : 
    2696           0 :      mssel_p2=new MeasurementSet(tableCommand(parseString,*mssel_p).table());
    2697           0 :      AlwaysAssert(mssel_p2, AipsError);
    2698             :      // Rename the selected MS as */SELECTED_UVRANGE
    2699             :      //mssel_p2->rename(msname_p+"/SELECTED_UVRANGE", Table::Scratch);
    2700             :       
    2701           0 :      if (mssel_p2->nrow()==0) {
    2702             :          os << LogIO::WARN
    2703             :             << "Selection string results in empty MS: "
    2704             :             << "reverting to sorted MeasurementSet"
    2705           0 :             << LogIO::POST;
    2706           0 :          delete mssel_p2;
    2707             :      } else {
    2708           0 :        if (!mssel_p.null()) {
    2709             :              os << LogIO::NORMAL // Loglevel INFO
    2710             :                 << "By UVRANGE selection previously selected number of rows "
    2711           0 :                 << mssel_p->nrow() << "  are now reduced to "
    2712           0 :                 << mssel_p2->nrow() << LogIO::POST; 
    2713             :              //delete mssel_p; 
    2714           0 :              mssel_p=mssel_p2;
    2715           0 :              mssel_p->flush();
    2716             :          }
    2717             :      }
    2718             :       
    2719             :      
    2720           0 :      this->makeVisSet(*mssel_p);
    2721           0 :      AlwaysAssert(rvi_p, AipsError);
    2722             : 
    2723             :      // NOW WE HAVE TO REDO THE VELOCITY INFO FOR visiter AS IN SETDATA
    2724             : 
    2725           0 :      this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
    2726           0 :                              dataNchan_p, dataStart_p, dataStep_p,
    2727           0 :                              mDataStart_p, mDataStep_p);
    2728             : 
    2729           0 :      this->writeHistory(os);
    2730           0 :      this->unlock();
    2731             :      
    2732             :      // Beam is no longer valid
    2733           0 :      beamValid_p=false;
    2734           0 :      return true;    
    2735           0 :   } catch (AipsError x) {
    2736           0 :     this->unlock();
    2737           0 :     throw(x);
    2738             :     return false;
    2739           0 :   } 
    2740             :   return true;
    2741           0 : }
    2742             : 
    2743             : // Find the sensitivity
    2744           0 : Bool Imager::sensitivity(Quantity& pointsourcesens, Double& relativesens,
    2745             :                          Double& sumwt,
    2746             :                          Double& effectiveBandwidth,
    2747             :                          Double& effectiveIntegration,
    2748             :                          Int& nBaselines,
    2749             :                          Matrix<Int>& mssChanSel,
    2750             :                          Vector<Vector<Int> >& nData,
    2751             :                          Vector<Vector<Double> >& sumwtChan,
    2752             :                          Vector<Vector<Double> >& sumwtsqChan,
    2753             :                          Vector<Vector<Double> >& sumInverseVarianceChan)
    2754             : {
    2755           0 :   if(!valid()) return false;
    2756           0 :   LogIO os(LogOrigin("imager", "sensitivity()", WHERE));
    2757             :   
    2758             :   try {
    2759             :     
    2760             :     os << LogIO::NORMAL // Loglevel INFO
    2761             :        << "Calculating sensitivity from imaging weights and from effective bandwidth and integration time"
    2762           0 :        << LogIO::POST;
    2763             :     
    2764           0 :     this->lock();
    2765           0 :     mssChanSel.assign(mssChanSel_p);
    2766             : 
    2767           0 :     VisSetUtil::Sensitivity(*rvi_p, mssFreqSel_p, mssChanSel, pointsourcesens, relativesens, sumwt,
    2768             :                             effectiveBandwidth, effectiveIntegration, nBaselines,nData, sumwtChan, 
    2769             :                             sumwtsqChan, sumInverseVarianceChan);
    2770             :     os << LogIO::NORMAL << "RMS Point source sensitivity  : " // Loglevel INFO
    2771           0 :        << pointsourcesens.get("Jy").getValue() << " Jy.m2/K"
    2772           0 :        << LogIO::POST;
    2773             :     os << LogIO::NORMAL // Loglevel INFO
    2774           0 :        << "Relative to natural weighting : " << relativesens << LogIO::POST;
    2775             :     os << LogIO::NORMAL // Loglevel INFO
    2776           0 :        << "Sum of weights                : " << sumwt << LogIO::POST;
    2777           0 :     this->unlock();
    2778           0 :     return true;
    2779           0 :   } catch (AipsError x) {
    2780           0 :     this->unlock();
    2781           0 :     throw(x);
    2782             :     return false;
    2783           0 :   } 
    2784             :   return true;
    2785           0 : }
    2786             : 
    2787           0 : Bool Imager::apparentSensitivity(Double& effSensitivity,
    2788             :                                  Double& relToNat) {
    2789           0 :   if(!valid()) return false;
    2790           0 :   LogIO os(LogOrigin("imager", "apparentSensitivity()", WHERE));
    2791             :   
    2792             :   try {
    2793             : 
    2794             :     os << LogIO::NORMAL // Loglevel INFO
    2795             :        << "Calculating apparent sensitivity from MS weights, as modified by gridding weight function"
    2796           0 :        << LogIO::POST;
    2797             :     os << LogIO::NORMAL // Loglevel INFO
    2798             :        << "(assuming that MS weights have correct scale and units)"
    2799           0 :        << LogIO::POST;
    2800             :     
    2801           0 :     this->lock();
    2802             :     
    2803           0 :     Double sumNatWt=0.0;
    2804           0 :     Double sumGridWt=0.0;
    2805           0 :     Double sumGridWt2OverNatWt=0.0;
    2806             :     
    2807           0 :     Float iNatWt(0.0),iGridWt(0.0);
    2808             :     
    2809           0 :     ROVisibilityIterator& vi(*rvi_p);
    2810           0 :     VisBuffer vb(vi);
    2811             :     //Bool doWtSp=vb.existsWeightSpectrum();
    2812           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    2813           0 :       for (vi.origin();vi.more();vi++) {
    2814           0 :         Int nRow=vb.nRow();
    2815           0 :         Vector<Bool> rowFlags=vb.flagRow();
    2816           0 :         Matrix<Bool> flag = vb.flag();
    2817             :         
    2818           0 :         Vector<Int>& a1(vb.antenna1()), a2(vb.antenna2());
    2819             :         
    2820           0 :         for (Int row=0; row<nRow; row++) {
    2821           0 :           if (!rowFlags(row) && a1(row)!=a2(row)) {  // exclude ACs
    2822           0 :             iNatWt=2.0f*vb.weight()(row);
    2823           0 :             for (Int ich=0;ich<vb.nChannel();++ich) {
    2824           0 :               if(!flag(ich,row)&&(iNatWt>0.0)) {
    2825           0 :                 iGridWt=2.0f*vb.imagingWeight()(ich,row);
    2826           0 :                 sumNatWt+=(iNatWt);
    2827           0 :                 sumGridWt+=(iGridWt);
    2828           0 :                 sumGridWt2OverNatWt+=(iGridWt*iGridWt/iNatWt);
    2829             :               }
    2830             :             }
    2831             :           }
    2832             :         }
    2833           0 :       }
    2834             :     }
    2835             :     
    2836           0 :     if (sumNatWt==0.0) {
    2837           0 :       os << "Cannot calculate sensitivity: sum of selected natural weights is zero" << LogIO::EXCEPTION;
    2838             :     }
    2839           0 :     if (sumGridWt==0.0) {
    2840           0 :       os << "Cannot calculate sensitivity: sum of gridded weights is zero" << LogIO::EXCEPTION;
    2841             :     }
    2842             : 
    2843           0 :     effSensitivity = sqrt(sumGridWt2OverNatWt)/sumGridWt;
    2844           0 :     Double natSensitivity = 1.0/sqrt(sumNatWt);
    2845           0 :     relToNat=effSensitivity/natSensitivity;
    2846             : 
    2847             :     os << LogIO::NORMAL << "RMS Point source sensitivity  : " // Loglevel INFO
    2848             :        << effSensitivity      //  << " Jy/beam"       // actually, units are arbitrary
    2849           0 :        << LogIO::POST;
    2850             :     os << LogIO::NORMAL // Loglevel INFO
    2851           0 :        << "Relative to natural weighting : " << relToNat << LogIO::POST;
    2852             : 
    2853           0 :     this->unlock();
    2854           0 :     return true;
    2855           0 :   } catch (AipsError x) {
    2856           0 :     this->unlock();
    2857           0 :     throw(x);
    2858             :     return false;
    2859           0 :   } 
    2860             :   return true;
    2861             :     
    2862           0 : }
    2863             : 
    2864             : 
    2865             : 
    2866             : 
    2867             : 
    2868             : // Calculate various sorts of image. Only one image
    2869             : // can be calculated at a time. The complex Image make
    2870             : // be retained if a name is given. This does not use
    2871             : // the SkyEquation.
    2872           0 : Bool Imager::makeimage(const String& type, const String& image,
    2873             :                        const String& compleximage, const Bool verbose)
    2874             : {
    2875           0 :   if(!valid()) 
    2876             :     {
    2877           0 :       return false;
    2878             :     }
    2879           0 :   LogIO os(LogOrigin("imager", "makeimage()", WHERE));
    2880             :   
    2881           0 :   this->lock();
    2882             :   try {
    2883           0 :     if(!assertDefinedImageParameters())
    2884             :       {
    2885           0 :         return false;
    2886             :       }
    2887             :     
    2888             :     os << LogIO::NORMAL // Loglevel INFO
    2889           0 :        << "Calculating image (without full skyequation)" << LogIO::POST;
    2890             :     
    2891           0 :     FTMachine::Type seType(FTMachine::OBSERVED);
    2892           0 :     Bool doSD(false);
    2893             : 
    2894           0 :     if(type=="observed") {
    2895           0 :       seType=FTMachine::OBSERVED;
    2896             :       os << LogIO::NORMAL // Loglevel INFO
    2897             :          << "Making dirty image from " << type << " data "
    2898           0 :          << LogIO::POST;
    2899             :     }
    2900           0 :     else if (type=="model") {
    2901           0 :       seType=FTMachine::MODEL;
    2902             :       os << LogIO::NORMAL // Loglevel INFO
    2903             :          << "Making dirty image from " << type << " data "
    2904           0 :          << LogIO::POST;
    2905             :     }
    2906           0 :     else if (type=="corrected") {
    2907           0 :       seType=FTMachine::CORRECTED;
    2908             :       os << LogIO::NORMAL // Loglevel INFO
    2909             :          << "Making dirty image from " << type << " data "
    2910           0 :          << LogIO::POST;
    2911             :     }
    2912           0 :     else if (type=="psf") {
    2913           0 :       seType=FTMachine::PSF;
    2914             :       os << "Making point spread function "
    2915           0 :          << LogIO::POST;
    2916             :     }
    2917           0 :     else if (type=="residual") {
    2918           0 :       seType=FTMachine::RESIDUAL;
    2919             :       os << LogIO::NORMAL // Loglevel INFO
    2920             :          << "Making dirty image from " << type << " data "
    2921           0 :          << LogIO::POST;
    2922             :     }
    2923           0 :     else if (type=="singledish-observed") {
    2924           0 :       doSD = true;
    2925           0 :       seType=FTMachine::OBSERVED;
    2926             :       os << LogIO::NORMAL // Loglevel INFO
    2927           0 :          << "Making single dish image from observed data" << LogIO::POST;
    2928             :     }
    2929           0 :     else if (type=="singledish") {
    2930           0 :       doSD = true;
    2931           0 :       seType=FTMachine::CORRECTED;
    2932             :       os << LogIO::NORMAL // Loglevel INFO
    2933           0 :          << "Making single dish image from corrected data" << LogIO::POST;
    2934             :     }
    2935           0 :     else if (type=="coverage") {
    2936           0 :       doSD = true;
    2937           0 :       seType=FTMachine::COVERAGE;
    2938             :       os << LogIO::NORMAL // Loglevel PROGRESS
    2939             :          << "Making single dish coverage function "
    2940           0 :          << LogIO::POST;
    2941             :     }
    2942           0 :     else if (type=="holography") {
    2943           0 :       doSD = true;
    2944           0 :       seType=FTMachine::CORRECTED;
    2945             :       os << LogIO::NORMAL // Loglevel INFO
    2946             :          << "Making complex holographic image from corrected data "
    2947           0 :          << LogIO::POST;
    2948             :     }
    2949           0 :     else if (type=="holography-observed") {
    2950           0 :       doSD = true;
    2951           0 :       seType=FTMachine::OBSERVED;
    2952             :       os << LogIO::NORMAL // Loglevel INFO
    2953             :          << "Making complex holographic image from observed data "
    2954           0 :          << LogIO::POST;
    2955             :     }
    2956           0 :     else if (type=="pb"){
    2957           0 :       if ( ! doVP_p ) {
    2958           0 :         if( ftmachine_p == "pbwproject" ){
    2959           0 :            os << LogIO::WARN << "Using pb from ft-machines" << LogIO::POST;
    2960             :         }
    2961             :         else{
    2962           0 :           this->unlock();
    2963             :           os << LogIO::SEVERE << 
    2964             :             "Must invoke setvp() first in order to make its image" 
    2965           0 :              << LogIO::EXCEPTION;
    2966           0 :           return false;
    2967             :         }
    2968             :       }
    2969           0 :       CoordinateSystem coordsys;
    2970             :       //imagecoordinates(coordsys, verbose);
    2971           0 :       imagecoordinates2(coordsys, verbose);
    2972           0 :       if (doDefaultVP_p) {
    2973           0 :         if(telescope_p!=""){
    2974           0 :           ObsInfo myobsinfo=this->latestObsInfo();
    2975           0 :           myobsinfo.setTelescope(telescope_p);
    2976           0 :           coordsys.setObsInfo(myobsinfo);
    2977             :           
    2978           0 :         }
    2979             :         else{
    2980           0 :           telescope_p=coordsys.obsInfo().telescope();
    2981             :         }
    2982           0 :         this->unlock();
    2983           0 :         MSAntennaColumns ac(ms_p->antenna());
    2984           0 :         Double dishDiam=ac.dishDiameter()(0);
    2985           0 :         if(!allEQ(ac.dishDiameter().getColumn(), dishDiam))
    2986             :           os << LogIO::WARN
    2987             :          << "The MS has multiple antenna diameters ..PB could be wrong "
    2988           0 :          << LogIO::POST;
    2989           0 :         return this->makePBImage(coordsys, telescope_p, image, false, dishDiam);
    2990           0 :       }
    2991             :       else{
    2992           0 :         Table vpTable(vpTableStr_p);
    2993           0 :         this->unlock();
    2994           0 :         return this->makePBImage(coordsys, vpTable, image);  
    2995           0 :       }
    2996             : 
    2997           0 :     }
    2998             :     else {
    2999           0 :       this->unlock();
    3000           0 :       os << LogIO::SEVERE << "Unknown image type " << type << LogIO::EXCEPTION;
    3001             : 
    3002           0 :       return false;
    3003             :     }
    3004             : 
    3005           0 :     if(doSD && (ftmachine_p == "ft")){
    3006             :       os << LogIO::SEVERE
    3007             :          << "To make single dish images, ftmachine in setoptions must be set to either sd or both"
    3008           0 :          << LogIO::EXCEPTION;
    3009             :     }
    3010             :     
    3011             :     // Now make the images. If we didn't specify the names then
    3012             :     // delete on exit.
    3013           0 :     String imageName(image);
    3014           0 :     if(image=="") {
    3015           0 :       imageName=Imager::imageName()+".image";
    3016             :     }
    3017           0 :     os << LogIO::NORMAL << "Image is : " << imageName << LogIO::POST; // Loglevel INFO
    3018           0 :     Bool keepImage=(image!="");
    3019           0 :     Bool keepComplexImage=(compleximage!="")||(type=="holography")||(type=="holography-observed");
    3020           0 :     String cImageName(compleximage);
    3021             : 
    3022           0 :     if(compleximage=="") {
    3023           0 :       cImageName=imageName+".compleximage";
    3024             :     }
    3025             : 
    3026           0 :     if(keepComplexImage) {
    3027           0 :       os << "Retaining complex image: " << compleximage << LogIO::POST;
    3028             :     }
    3029             : 
    3030           0 :     CoordinateSystem imagecoords;
    3031             :     //if(!imagecoordinates(imagecoords, false))
    3032           0 :     if(!imagecoordinates2(imagecoords, false))
    3033             :       {
    3034           0 :         return false;
    3035             :       }
    3036           0 :     make(imageName);
    3037           0 :     PagedImage<Float> imageImage(imageName);
    3038           0 :     imageImage.set(0.0);
    3039           0 :     imageImage.table().markForDelete();
    3040             :     
    3041             :     // Now set up the tile size, here we guess only
    3042           0 :     IPosition cimageShape(imageshape());
    3043           0 :     Int tilex=32;
    3044           0 :     if(imageTileVol_p >0){
    3045           0 :       tilex=static_cast<Int>(ceil(sqrt(imageTileVol_p/min(4,
    3046           0 :                                                           cimageShape(2))/min(32,
    3047           0 :                                                                               cimageShape(3)))));
    3048           0 :       if(tilex >0){
    3049           0 :         if(tilex > min(Int(cimageShape(0)), Int(cimageShape(1))))
    3050           0 :           tilex=min(Int(cimageShape(0)), Int(cimageShape(1)));
    3051             :         else
    3052           0 :           tilex=cimageShape(0)/Int(cimageShape(0)/tilex);
    3053             :       }
    3054             :       //Not too small in x-y tile
    3055           0 :       if(tilex < 10)
    3056           0 :         tilex=10;
    3057             :    
    3058             :     }
    3059           0 :     IPosition tileShape(4, min(tilex, cimageShape(0)), min(tilex, cimageShape(1)),
    3060           0 :                         min(4, cimageShape(2)), min(32, cimageShape(3)));
    3061           0 :     CoordinateSystem cimagecoords;
    3062             :     //if(!imagecoordinates(cimagecoords, false))
    3063           0 :     if(!imagecoordinates2(cimagecoords, false))
    3064             :       {
    3065           0 :         return false;
    3066             :       }
    3067             : 
    3068             : 
    3069             :     
    3070           0 :     PagedImage<Complex> cImageImage(TiledShape(cimageShape, tileShape),
    3071             :                                     cimagecoords,
    3072           0 :                                     cImageName);
    3073           0 :     cImageImage.set(Complex(0.0));
    3074           0 :     cImageImage.setMaximumCacheSize(cache_p/2);
    3075           0 :     cImageImage.table().markForDelete();
    3076             :     //
    3077             :     // Add the distance to the object: this is not nice. We should define the
    3078             :     // coordinates properly.
    3079             :     //
    3080           0 :     Record info(imageImage.miscInfo());
    3081           0 :     info.define("distance", distance_p.get("m").getValue());
    3082           0 :     cImageImage.setMiscInfo(info);
    3083             : 
    3084             :     
    3085           0 :     String ftmachine(ftmachine_p);
    3086           0 :     if (!ft_p)
    3087           0 :       createFTMachine();
    3088             :     
    3089             :     os << LogIO::DEBUG1 << "FTMachine is : " << ftmachine 
    3090           0 :        << " (" << ft_p << ")" << LogIO::POST;
    3091             :     
    3092             :     
    3093             :     // Now make the required image
    3094           0 :     Matrix<Float> weight;
    3095           0 :     ft_p->makeImage(seType, *rvi_p, cImageImage, weight);
    3096           0 :     StokesImageUtil::To(imageImage, cImageImage);
    3097             :     //
    3098             :     // Dirty way to set the proper unit to SD image
    3099             :     //
    3100           0 :     String msunit("");
    3101           0 :     String imunit;
    3102           0 :     if ( ms_p->tableDesc().isColumn("DATA") ){
    3103           0 :       msunit = ms_p->columnUnit(MS::DATA);
    3104           0 :       if (msunit == String("")) {
    3105           0 :         ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("DATA"));
    3106           0 :         if (dataColDesc.keywordSet().isDefined("UNIT"))
    3107           0 :           msunit = dataColDesc.keywordSet().asString("UNIT");
    3108           0 :       }
    3109           0 :     } else if ( ms_p->tableDesc().isColumn("FLOAT_DATA")) {
    3110           0 :       msunit = ms_p->columnUnit(MS::FLOAT_DATA);
    3111           0 :       if (msunit == String("")) {
    3112           0 :         ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("FLOAT_DATA"));
    3113           0 :         if (dataColDesc.keywordSet().isDefined("UNIT"))
    3114           0 :           msunit = dataColDesc.keywordSet().asString("UNIT");
    3115           0 :       }
    3116             :     }
    3117           0 :     msunit.upcase();
    3118           0 :     if (msunit == String("K"))
    3119           0 :       imunit = "K";
    3120             :     else
    3121           0 :       imunit = "Jy/beam";
    3122           0 :     imageImage.setUnits(Unit(imunit));
    3123           0 :     cImageImage.setUnits(Unit(imunit));
    3124             : //     imageImage.setUnits(Unit("Jy/beam"));
    3125             : //     cImageImage.setUnits(Unit("Jy/beam"));
    3126             : 
    3127           0 :     if(keepImage) {
    3128           0 :       imageImage.table().unmarkForDelete();
    3129             :     }
    3130           0 :     if(keepComplexImage) {
    3131           0 :       cImageImage.table().unmarkForDelete();
    3132             :     }
    3133           0 :     this->unlock();
    3134           0 :     return true;
    3135           0 :   } catch (AipsError x) {
    3136           0 :     this->unlock();
    3137           0 :     throw(x);
    3138             :     return false;
    3139           0 :   }
    3140           0 :   catch(...){
    3141             :     //Unknown exception...
    3142           0 :     throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    3143           0 :   }
    3144             :   this->unlock();
    3145             : 
    3146             :   return true;
    3147           0 : }  
    3148             : 
    3149             : // Restore: at least one model must be supplied
    3150           0 : Bool Imager::restore(const Vector<String>& model,
    3151             :                      const String& complist,
    3152             :                      const Vector<String>& image,
    3153             :                      const Vector<String>& residual)
    3154             : {
    3155             :   
    3156           0 :   if(!valid()) return false;
    3157           0 :   LogIO os(LogOrigin("imager", "restore()", WHERE));
    3158             :   
    3159           0 :   this->lock();
    3160             :   try {
    3161           0 :     if(!assertDefinedImageParameters()) return false;
    3162             :     
    3163           0 :     if(image.nelements()>model.nelements()) {
    3164           0 :       this->unlock();
    3165             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3166           0 :          << LogIO::EXCEPTION;
    3167           0 :       return false;
    3168             :     }
    3169             :     else {
    3170             :       os << LogIO::NORMAL // Loglevel PROGRESS
    3171           0 :          << "Restoring " << model.nelements() << " models" << LogIO::POST;
    3172             :     }
    3173             : 
    3174             :     ///if the skymodel is already set...no need to get rid of the psf and ftmachine state
    3175             :     //as long as the images match
    3176           0 :     if(!redoSkyModel_p){
    3177           0 :       Bool coordMatch=true; 
    3178           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3179           0 :         CoordinateSystem cs=(sm_p->image(thismodel)).coordinates();
    3180           0 :         coordMatch= coordMatch || checkCoord(cs, model(thismodel));
    3181           0 :       }
    3182           0 :       if(!coordMatch)
    3183           0 :         destroySkyEquation();
    3184             :     }
    3185             :     
    3186           0 :     if(redoSkyModel_p){
    3187           0 :       Vector<String> imageNames(image);
    3188           0 :       if(image.nelements()<model.nelements()) {
    3189           0 :         imageNames.resize(model.nelements());
    3190           0 :         for(Int i=0;i<Int(model.nelements()); ++i) {
    3191           0 :           imageNames(i)="";
    3192             :         }
    3193             :       }
    3194             :       
    3195           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3196           0 :         if(imageNames(thismodel)=="") {
    3197           0 :           imageNames(thismodel)=model(thismodel)+".restored";
    3198             :         }
    3199           0 :         removeTable(imageNames(thismodel));
    3200           0 :         if(imageNames(thismodel)=="") {
    3201           0 :           this->unlock();
    3202             :           os << LogIO::SEVERE << "Illegal name for output image "
    3203           0 :              << imageNames(thismodel) << LogIO::EXCEPTION;
    3204           0 :           return false;
    3205             :         }
    3206           0 :         if(!clone(model(thismodel), imageNames(thismodel))) return false;
    3207             :       }
    3208             :       
    3209           0 :       Vector<String> residualNames(residual);
    3210           0 :       if(residual.nelements()<model.nelements()) {
    3211           0 :         residualNames.resize(model.nelements());
    3212           0 :         for(Int i=0;i<Int(model.nelements());++i) {
    3213           0 :           residualNames(i)="";
    3214             :         }
    3215             :       }
    3216             : 
    3217           0 :       for (Int thismodel=0;thismodel<Int(model.nelements()); ++thismodel) {
    3218           0 :         if(residualNames(thismodel)=="")
    3219           0 :           residualNames(thismodel)=model(thismodel)+".residual";
    3220           0 :         removeTable(residualNames(thismodel));
    3221           0 :         if(residualNames(thismodel)=="") {
    3222           0 :           this->unlock();
    3223             :           os << LogIO::SEVERE << "Illegal name for output residual "
    3224           0 :              << residualNames(thismodel) << LogIO::EXCEPTION;
    3225           0 :           return false;
    3226             :         }
    3227           0 :         if(!clone(model(thismodel), residualNames(thismodel))) return false;
    3228             :       }
    3229             :     
    3230           0 :       if(beamValid_p) {
    3231           0 :         os << LogIO::NORMAL << "Using previous beam fit" << LogIO::POST; // Loglevel INFO
    3232             :       }
    3233             :       else {
    3234             :         os << LogIO::NORMAL // Loglevel INFO
    3235           0 :            << "Calculating PSF using current parameters" << LogIO::POST;
    3236           0 :         String psf;
    3237           0 :         psf=imageNames(0)+".psf";
    3238           0 :         if(!clone(imageNames(0), psf)) return false;
    3239           0 :         Imager::makeimage("psf", psf);
    3240           0 :         fitpsf(psf, beam_p);
    3241           0 :         beamValid_p=true;
    3242           0 :       }
    3243             : 
    3244             :       //      if (!se_p)
    3245           0 :       if(!createSkyEquation(model, complist)) return false;
    3246             :       
    3247           0 :       addResiduals(residualNames);
    3248           0 :     }
    3249           0 :     sm_p->solveResiduals(*se_p);
    3250           0 :     for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3251           0 :       residuals_p[k]->copyData(sm_p->getResidual(k));
    3252             :     }
    3253           0 :     restoreImages(image);
    3254             :     
    3255           0 :     this->unlock();
    3256           0 :     return true;
    3257           0 :   } catch (AipsError x) {
    3258           0 :     this->unlock();
    3259           0 :     throw(x);
    3260             :     return false;
    3261           0 :   } 
    3262             :   this->unlock();
    3263             :   return true;
    3264           0 : }
    3265             : 
    3266           0 : Bool Imager::updateresidual(const Vector<String>& model,
    3267             :                      const String& complist,
    3268             :                      const Vector<String>& image,
    3269             :                      const Vector<String>& residual)
    3270             : {
    3271             :   
    3272           0 :   if(!valid()) return false;
    3273           0 :   LogIO os(LogOrigin("imager", "updateresidual()", WHERE));
    3274             :   
    3275           0 :   this->lock();
    3276             :   try {
    3277           0 :     if(!assertDefinedImageParameters()) return false;
    3278             :     
    3279           0 :     if(image.nelements()>model.nelements()) {
    3280           0 :       this->unlock();
    3281             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3282           0 :          << LogIO::EXCEPTION;
    3283           0 :       return false;
    3284             :     }
    3285             :     else {
    3286             :       os << LogIO::NORMAL // Loglevel PROGRESS
    3287           0 :          << "updating and restoring " << model.nelements() << " models" << LogIO::POST;
    3288             :     }
    3289             : 
    3290           0 :     if(redoSkyModel_p)
    3291           0 :       throw(AipsError("use restore instead of updateresidual"));
    3292           0 :     if(!updateSkyModel(model, complist))
    3293           0 :         throw(AipsError("Could not do an updateresidual please use restore"));      
    3294           0 :     addResiduals(residual);
    3295           0 :     for (Int thismodel=0;thismodel<Int(residuals_p.nelements());++thismodel) {
    3296           0 :       if(!residuals_p[thismodel].null()) 
    3297           0 :         sm_p->addResidual(thismodel, *residuals_p[thismodel]);   
    3298             :     }
    3299           0 :     sm_p->solveResiduals(*se_p);
    3300             :     /*for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3301             :       residuals_p[k]->copyData(sm_p->getResidual(k));
    3302             :     }
    3303             :     */
    3304           0 :     restoreImages(image);
    3305             :     
    3306             : 
    3307           0 :     this->unlock();
    3308           0 :     return true;
    3309           0 :   } catch (AipsError x) {
    3310           0 :     this->unlock();
    3311           0 :     throw(x);
    3312             :     return false;
    3313           0 :   } 
    3314             :   this->unlock();
    3315             :   return true;
    3316           0 : }
    3317             : 
    3318             : // Residual
    3319           0 : Bool Imager::residual(const Vector<String>& model,
    3320             :                       const String& complist,
    3321             :                       const Vector<String>& image)
    3322             : {
    3323             :   
    3324           0 :   if(!valid()) return false;
    3325           0 :   LogIO os(LogOrigin("imager", "residual()", WHERE));
    3326             :   
    3327           0 :   this->lock();
    3328             :   try {
    3329           0 :     if(!assertDefinedImageParameters()) return false;
    3330             :     os << LogIO::NORMAL // Loglevel INFO
    3331           0 :        << "Calculating residual image using full sky equation" << LogIO::POST;
    3332           0 :     Vector<String> theModels=model;
    3333             : 
    3334           0 :     Bool deleteModel=false;
    3335             : 
    3336           0 :     if(model.nelements()==1 && model[0]=="" && complist != "" 
    3337           0 :        && image.nelements()==1){
    3338             : 
    3339             :       //      A component list with no model passed...
    3340           0 :       theModels.resize(1);
    3341           0 :       theModels[0]="Imager_Scratch_model";
    3342           0 :       make(theModels[0]);
    3343           0 :       deleteModel=true;
    3344             :     }
    3345             : 
    3346           0 :     if(image.nelements()>theModels.nelements()) {
    3347           0 :       this->unlock();
    3348             :       os << LogIO::SEVERE << "Cannot specify more output images than models"
    3349           0 :          << LogIO::EXCEPTION;
    3350           0 :       return false;
    3351             :     }
    3352             :     else {
    3353             :       os << LogIO::NORMAL << "Finding residuals for " << theModels.nelements() // Loglevel INFO
    3354           0 :          << " models" << LogIO::POST;
    3355             :     }
    3356             :     
    3357           0 :     Vector<String> imageNames(image);
    3358           0 :     if(image.nelements()<theModels.nelements()) {
    3359           0 :       imageNames.resize(model.nelements());
    3360           0 :       for(Int i=Int(image.nelements());i<Int(theModels.nelements());++i) {
    3361           0 :         imageNames(i)="";
    3362             :       }
    3363             :     }
    3364             : 
    3365           0 :     for (Int thismodel=0;thismodel<Int(theModels.nelements()); ++thismodel) {
    3366           0 :       if(imageNames(thismodel)=="")
    3367           0 :         imageNames(thismodel)=model(thismodel)+".residual";
    3368           0 :       removeTable(imageNames(thismodel));
    3369           0 :       if(imageNames(thismodel)=="") {
    3370           0 :         this->unlock();
    3371             :         os << LogIO::SEVERE << "Illegal name for output image "
    3372           0 :            << imageNames(thismodel) << LogIO::EXCEPTION;
    3373           0 :         return false;
    3374             :       }
    3375           0 :       if(!clone(theModels(thismodel), imageNames(thismodel))) return false;
    3376             :     }
    3377           0 :     destroySkyEquation();
    3378           0 :     if(!createSkyEquation(theModels, complist)) return false;
    3379             :     
    3380           0 :     addResidualsToSkyEquation(imageNames);
    3381             :     
    3382           0 :     sm_p->solveResiduals(*se_p);
    3383           0 :     destroySkyEquation();
    3384           0 :     if(deleteModel) 
    3385           0 :       removeTable(theModels[0]);
    3386           0 :     this->unlock();
    3387           0 :     return true;
    3388           0 :   } catch (AipsError x) {
    3389           0 :     this->unlock();
    3390           0 :     throw(x);
    3391             :     return false;
    3392           0 :   } 
    3393             :   this->unlock();
    3394             :   return true;
    3395           0 : }
    3396             : 
    3397             : // Residual
    3398           0 : Bool Imager::approximatepsf(const String& psf)
    3399             : {
    3400             :   
    3401           0 :   if(!valid()) return false;
    3402           0 :   LogIO os(LogOrigin("imager", "approximatepsfs()", WHERE));
    3403             :   
    3404           0 :   this->lock();
    3405             :   try {
    3406           0 :     if(!assertDefinedImageParameters()) return false;
    3407             :     os << LogIO::NORMAL // Loglevel INFO
    3408           0 :        << "Calculating approximate PSFs using full sky equation" << LogIO::POST;
    3409             :     
    3410             :  
    3411           0 :     if(psf==""){
    3412           0 :       this->unlock();
    3413             :       os << LogIO::SEVERE << "Illegal name for output psf "
    3414           0 :          << psf << LogIO::EXCEPTION;
    3415           0 :       return false;
    3416             :     } 
    3417           0 :     removeTable(psf);
    3418           0 :     make(psf);
    3419             :     
    3420           0 :     Vector<String>onepsf(1,psf);
    3421             :     // Previous SkyEquation if they exist is not useful
    3422           0 :     destroySkyEquation();
    3423             :     //    if (!se_p)
    3424             :     // As we are not going to make any use of a useful model and to economize 
    3425             :     // temporary image...using the psf itself as model...
    3426             :     // need to change this if you donot destroy the skyequation after you're done.
    3427           0 :     if(!createSkyEquation(onepsf)) return false;
    3428             :     
    3429           0 :     sm_p->makeApproxPSFs(*se_p);
    3430             :     
    3431             : 
    3432           0 :     PagedImage<Float> elpsf(psf);
    3433           0 :     elpsf.copyData(sm_p->PSF(0));
    3434           0 :     ImageBeamSet mbeam;
    3435           0 :     StokesImageUtil::FitGaussianPSF(elpsf, mbeam);
    3436           0 :     LatticeExprNode sumPSF = sum(elpsf);
    3437           0 :     Float volume=sumPSF.getFloat();
    3438           0 :     GaussianBeam elbeam=mbeam(0,0);
    3439             :     os << LogIO::NORMAL << "Approximate PSF  "  << ": size " // Loglevel INFO
    3440             :        << elbeam.getMajor("arcsec") << " by "
    3441             :        << elbeam.getMinor("arcsec") << " (arcsec) at pa "
    3442           0 :        << elbeam.getPA(Unit("deg")) << " (deg)" << endl
    3443           0 :        << "and volume = " << volume << " pixels " << LogIO::POST;
    3444             :     
    3445             :     
    3446           0 :     destroySkyEquation();
    3447           0 :     if(ft_p)
    3448           0 :       delete ft_p;
    3449           0 :     ft_p=0;
    3450             : 
    3451           0 :     this->unlock();
    3452           0 :     return true;
    3453           0 :   } catch (AipsError x) {
    3454           0 :     this->unlock();
    3455           0 :     throw(x);
    3456             :     return false;
    3457           0 :   } 
    3458             :   this->unlock();
    3459             :   return true;
    3460           0 : }
    3461             : 
    3462           0 : Bool Imager::smooth(const Vector<String>& model, 
    3463             :                     const Vector<String>& image, Bool usefit, 
    3464             :                     ImageBeamSet& mbeam,
    3465             :                     Bool normalizeVolume)
    3466             : {
    3467           0 :   if(!valid()) return false;
    3468           0 :   LogIO os(LogOrigin("imager", "smooth()", WHERE));
    3469             :   
    3470           0 :   this->lock();
    3471             :   try {
    3472           0 :     if(!assertDefinedImageParameters()) return false;
    3473             :     
    3474           0 :     os << LogIO::NORMAL << "Smoothing image" << LogIO::POST; // Loglevel PROGRESS
    3475             :     
    3476           0 :     if(model.nelements()>0) {
    3477           0 :       for ( uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
    3478           0 :         if(model(thismodel)=="") {
    3479           0 :           this->unlock();
    3480           0 :           os << LogIO::SEVERE << "Need a name for model " << thismodel << LogIO::POST;
    3481           0 :           return false;
    3482             :         }
    3483             :       }
    3484             :     }
    3485             :     
    3486           0 :     if(image.nelements()>model.nelements()) {
    3487           0 :       this->unlock();
    3488           0 :       os << LogIO::SEVERE << "Cannot specify more output images than models" << LogIO::POST;
    3489           0 :       return false;
    3490             :     }
    3491             :     
    3492           0 :     if(usefit) {
    3493           0 :       if(beamValid_p) {
    3494           0 :         os << LogIO::NORMAL << "Using previous beam" << LogIO::POST; // Loglevel INFO
    3495           0 :         mbeam = beam_p;
    3496             : 
    3497             :       }
    3498             :       else {
    3499             :         os << LogIO::NORMAL // Loglevel INFO
    3500           0 :            << "Calculating PSF using current parameters" << LogIO::POST;
    3501           0 :         String psf;
    3502           0 :         psf=model(0)+".psf";
    3503           0 :         if(!clone(model(0), psf)) return false;
    3504           0 :         Imager::makeimage("psf", psf);
    3505           0 :         fitpsf(psf, mbeam);
    3506           0 :         beam_p = mbeam;
    3507           0 :         beamValid_p=true;
    3508           0 :       }
    3509             :     }
    3510             :     
    3511             :     // Smooth all the images
    3512           0 :     Vector<String> imageNames(image);
    3513           0 :     for (Int thismodel=0;thismodel<Int(image.nelements()); ++thismodel) {
    3514           0 :       if(imageNames(thismodel)=="") {
    3515           0 :         imageNames(thismodel)=model(thismodel)+".smoothed";
    3516             :       }
    3517           0 :       PagedImage<Float> modelImage(model(thismodel));
    3518           0 :       PagedImage<Float> imageImage(TiledShape(modelImage.shape(), 
    3519           0 :                                               modelImage.niceCursorShape()),
    3520             :                                    modelImage.coordinates(),
    3521           0 :                                    imageNames(thismodel));
    3522           0 :       imageImage.table().markForDelete();
    3523           0 :       imageImage.copyData(modelImage);
    3524           0 :       StokesImageUtil::Convolve(imageImage, mbeam,
    3525             :                                 normalizeVolume);
    3526             :       
    3527           0 :       ImageInfo ii = imageImage.imageInfo();
    3528             :       //ii.setRestoringBeam(mbeam);
    3529           0 :       ii.setBeams(mbeam);
    3530           0 :       imageImage.setImageInfo(ii);
    3531           0 :       imageImage.setUnits(Unit("Jy/beam"));
    3532           0 :       imageImage.table().unmarkForDelete();
    3533           0 :     }
    3534             :     
    3535           0 :     this->unlock();
    3536           0 :     return true;
    3537           0 :   } catch (AipsError x) {
    3538           0 :     this->unlock();
    3539           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    3540           0 :     return false;
    3541           0 :   } 
    3542             :   this->unlock();
    3543             :   return true;
    3544           0 : }
    3545             : 
    3546             : // Clean algorithm
    3547           0 : Record Imager::clean(const String& algorithm,
    3548             :                    const Int niter, 
    3549             :                    const Float gain,
    3550             :                    const Quantity& threshold, 
    3551             :                    const Bool /*displayProgress*/,
    3552             :                    const Vector<String>& model, const Vector<Bool>& fixed,
    3553             :                    const String& complist,
    3554             :                    const Vector<String>& mask,
    3555             :                    const Vector<String>& image,
    3556             :                    const Vector<String>& residual,
    3557             :                    const Vector<String>& psfnames,
    3558             :                    const Bool firstrun)
    3559             : {
    3560             :   ////////////////////////
    3561             :   //Double wtime0=omp_get_wtime();
    3562             :   //////////////////////
    3563             : 
    3564             : 
    3565           0 :   Record retval;
    3566           0 :   Bool converged=true;
    3567           0 :   retval.define("converged", false);
    3568           0 :   retval.define("iterations", Int(0));
    3569           0 :   retval.define("maxresidual", Float(0.0));
    3570             :   
    3571             : 
    3572             : 
    3573             :   //ROVisibilityIterator::AsyncEnabler enabler (rvi_p);
    3574             : 
    3575           0 :   if(!valid())
    3576             :     {
    3577           0 :       return retval;
    3578             :     }
    3579           0 :   logSink_p.clearLocally();
    3580           0 :   LogIO os(LogOrigin("imager", "clean()"),logSink_p);
    3581             :   
    3582           0 :   this->lock();
    3583             :   try {
    3584           0 :     if(!assertDefinedImageParameters()) 
    3585             :       {
    3586           0 :         return retval;
    3587             :       }
    3588             :     
    3589           0 :     Int nmodels=model.nelements();
    3590             :     os << LogIO::DEBUG1
    3591           0 :        << "Found " << nmodels << " specified model images" << LogIO::POST;
    3592             :     
    3593           0 :     if(model.nelements()>0) {
    3594           0 :       for (uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
    3595           0 :         if(model(thismodel)=="") {
    3596           0 :           this->unlock();
    3597             :           os << LogIO::SEVERE << "Need a name for model "
    3598           0 :              << thismodel << LogIO::POST;
    3599             : 
    3600           0 :           return retval;
    3601             :         }
    3602             :       }
    3603             :     }
    3604             :     
    3605           0 :     Vector<String> modelNames=model;
    3606             :     // Make first image with the required shape and coordinates only if
    3607             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    3608           0 :     if(modelNames(0)=="") modelNames(0)=imageName()+".clean";
    3609           0 :     if(!Table::isWritable(modelNames(0))) {
    3610           0 :       make(modelNames(0));
    3611             :     }
    3612             :     else{
    3613           0 :       Bool coordMatch=false;
    3614           0 :       CoordinateSystem coordsys;
    3615             :       //imagecoordinates(coordsys, firstrun);
    3616           0 :       imagecoordinates2(coordsys, firstrun);
    3617           0 :       for (uInt modelNum=0; modelNum < modelNames.nelements(); ++modelNum){
    3618           0 :         if(Table::isWritable(modelNames(modelNum))){
    3619           0 :           coordMatch= coordMatch || 
    3620           0 :             (this->checkCoord(coordsys, modelNames(modelNum)));
    3621             :                                      
    3622             :         }
    3623             :           
    3624             :       } 
    3625           0 :       if(!coordMatch){
    3626             :         os << LogIO::WARN << "The model(s) image exists on disk " 
    3627           0 :            << LogIO::POST;
    3628             :         os << LogIO::WARN 
    3629             :            << "The coordinates or shape were found not to match the one "
    3630             :            << "defined by setimage " 
    3631           0 :            << LogIO::POST;
    3632             : 
    3633             :         os << LogIO::WARN 
    3634             :            << "Cleaning process is going to ignore setimage parameters and "
    3635             :            << "continue cleaning from from model on disk " 
    3636           0 :            << LogIO::POST;
    3637             :       }
    3638           0 :     }
    3639           0 :     Vector<String> maskNames(nmodels);
    3640           0 :     if(Int(mask.nelements())==nmodels) {
    3641           0 :       maskNames=mask;
    3642             :     }
    3643             :     else {
    3644             :       /* For msmfs, the one input mask PER FIELD must be replicated for all 
    3645             :          Taylor-planes PER FIELD */
    3646           0 :       if(algorithm=="msmfs" && (Int(mask.nelements())>=(nmodels/ntaylor_p)) ){
    3647           0 :        for(Int tay=0;tay<nmodels;tay++)
    3648             :          {
    3649           0 :            maskNames[tay] = mask[ tay%(nmodels/ntaylor_p)  ];
    3650             :          }
    3651             :       }
    3652             :       else {
    3653             :          /* No mask */
    3654           0 :          maskNames="";
    3655             :       }
    3656             :     }
    3657             : 
    3658           0 :     if(sm_p){
    3659           0 :       if( sm_p->getAlgorithm() != "clean") destroySkyEquation();
    3660           0 :       if(images_p.nelements() != uInt(nmodels)){
    3661           0 :         destroySkyEquation();
    3662             :       }
    3663             :       else{
    3664           0 :         for (Int k=0; k < nmodels ; ++k){
    3665           0 :           if(!(images_p[k]->name().contains(modelNames[k]))) destroySkyEquation();
    3666             :         }
    3667             :       }
    3668             :     }
    3669             : 
    3670             :     // Always fill in the residual images
    3671           0 :     Vector<String> residualNames(nmodels);
    3672           0 :     if(Int(residual.nelements())==nmodels) {
    3673           0 :         residualNames=residual;
    3674             :     }
    3675             :     else {
    3676           0 :       residualNames="";       
    3677             :     }
    3678           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3679           0 :       if(residualNames[thismodel]=="")
    3680           0 :         residualNames(thismodel)=modelNames(thismodel)+".residual";
    3681             :     }
    3682           0 :     if(redoSkyModel_p){
    3683           0 :       for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    3684           0 :         removeTable(residualNames(thismodel));
    3685           0 :         if(!clone(model(thismodel), residualNames(thismodel)))
    3686             :           {
    3687           0 :             return retval;
    3688             :           }
    3689             :       }
    3690             :     }
    3691             : 
    3692             :     
    3693             :     // Make an ImageSkyModel with the specified polarization representation
    3694             :     // (i.e. circular or linear)
    3695             : 
    3696           0 :     if( redoSkyModel_p || !sm_p){
    3697           0 :       if(sm_p) delete sm_p;
    3698           0 :       if(algorithm.substr(0,5)=="clark") {
    3699             :         // Support serial and parallel specializations
    3700           0 :         setClarkCleanImageSkyModel();
    3701           0 :         if(algorithm.contains("stokes"))
    3702           0 :           sm_p->setJointStokesClean(false);
    3703             :         os << LogIO::NORMAL // Loglevel INFO.        Stating the algo is more for
    3704           0 :            << "Using Clark clean" << LogIO::POST; // the logfile than the window.
    3705             :       }
    3706           0 :       else if (algorithm=="hogbom") {
    3707           0 :         sm_p = new HogbomCleanImageSkyModel();
    3708             :         os << LogIO::NORMAL // Loglevel INFO.         Stating the algo is more for
    3709           0 :            << "Using Hogbom clean" << LogIO::POST; // the logfile than the window.
    3710             :       }
    3711           0 :       else if (algorithm=="wfhogbom") {
    3712           0 :         setWFCleanImageSkyModel();
    3713           0 :         sm_p->setSubAlgorithm("hogbom");
    3714           0 :         doMultiFields_p = true;
    3715           0 :         doMultiFields_p = false;
    3716             :         os << LogIO::NORMAL // Loglevel INFO
    3717           0 :            << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
    3718             :       }
    3719           0 :       else if (algorithm=="multiscale") {
    3720           0 :         if (!scaleInfoValid_p) {
    3721           0 :           this->unlock();
    3722           0 :           os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
    3723           0 :           return retval;
    3724             :         }
    3725           0 :         if (scaleMethod_p=="uservector") {    
    3726           0 :           sm_p = new MSCleanImageSkyModel(userScaleSizes_p, stoplargenegatives_p, 
    3727           0 :                                             stoppointmode_p, smallScaleBias_p);
    3728             :         } else {
    3729           0 :           sm_p = new MSCleanImageSkyModel(nscales_p, stoplargenegatives_p, 
    3730           0 :                                             stoppointmode_p, smallScaleBias_p);
    3731             :         }
    3732           0 :         if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    3733           0 :           sm_p->setSubAlgorithm("full");
    3734             :         os << LogIO::NORMAL // Loglevel INFO.             Stating the algo is more for
    3735           0 :            << "Using multiscale clean" << LogIO::POST; // the logfile than the window.
    3736             :       }
    3737           0 :       else if (algorithm.substr(0,7)=="mfclark" || algorithm=="mf") {
    3738           0 :         sm_p = new MFCleanImageSkyModel();
    3739           0 :         sm_p->setSubAlgorithm("clark");
    3740           0 :         if(algorithm.contains("stokes"))
    3741           0 :           sm_p->setJointStokesClean(false);
    3742             : 
    3743           0 :         doMultiFields_p = true;
    3744           0 :         os << LogIO::NORMAL << "Using multifield Clark clean" << LogIO::POST; // Loglevel INFO
    3745             :       }
    3746           0 :       else if (algorithm=="csclean" || algorithm=="cs") {
    3747           0 :         sm_p = new CSCleanImageSkyModel();
    3748           0 :         doMultiFields_p = true;
    3749           0 :         os << LogIO::NORMAL << "Using Cotton-Schwab Clean" << LogIO::POST; // Loglevel INFO
    3750             :       }
    3751           0 :       else if (algorithm=="csfast" || algorithm=="csf") {
    3752           0 :         sm_p = new CSCleanImageSkyModel();
    3753           0 :         sm_p->setSubAlgorithm("fast");
    3754           0 :         doMultiFields_p = true;
    3755             :         os << LogIO::NORMAL // Loglevel INFO
    3756           0 :            << "Using Cotton-Schwab Clean (optimized)" << LogIO::POST;
    3757             :       }
    3758           0 :       else if (algorithm=="mfhogbom") {
    3759           0 :         sm_p = new MFCleanImageSkyModel();
    3760           0 :         sm_p->setSubAlgorithm("hogbom");
    3761           0 :         doMultiFields_p = true;
    3762           0 :         os << LogIO::NORMAL << "Using multifield Hogbom clean" << LogIO::POST; // Loglevel INFO
    3763             :       }
    3764           0 :       else if (algorithm=="mfmultiscale") {
    3765           0 :         if (!scaleInfoValid_p) {
    3766           0 :           this->unlock();
    3767           0 :           os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
    3768           0 :           return retval;
    3769             :         }
    3770           0 :         if (scaleMethod_p=="uservector") {
    3771           0 :           sm_p = new MFMSCleanImageSkyModel(userScaleSizes_p, 
    3772             :                                             stoplargenegatives_p, 
    3773             :                                             stoppointmode_p,
    3774           0 :                                             smallScaleBias_p);
    3775             :         } else {
    3776           0 :           sm_p = new MFMSCleanImageSkyModel(nscales_p, 
    3777             :                                             stoplargenegatives_p, 
    3778             :                                             stoppointmode_p,
    3779           0 :                                             smallScaleBias_p);
    3780             :         }
    3781             :         //      if(ftmachine_p=="mosaic"|| ftmachine_p=="wproject")
    3782             :         // For some reason  this does not seem to work without full
    3783           0 :         sm_p->setSubAlgorithm("full");
    3784             : 
    3785           0 :         doMultiFields_p = true;
    3786             :         os << LogIO::NORMAL << "Using multifield multi-scale clean"  // Loglevel INFO
    3787           0 :            << LogIO::POST;
    3788             :       } 
    3789           0 :       else if (algorithm=="wfclark" || algorithm=="wf") {
    3790             :         // Support serial and parallel specializations
    3791           0 :         setWFCleanImageSkyModel();
    3792           0 :         sm_p->setSubAlgorithm("clark");
    3793           0 :         doMultiFields_p = false;
    3794             :         os << LogIO::NORMAL // Loglevel INFO
    3795           0 :            << "Using wide-field algorithm with Clark clean" << LogIO::POST;
    3796             :       }
    3797           0 :       else if (algorithm=="wfhogbom") {
    3798             :         // Support serial and parallel specializations
    3799           0 :         setWFCleanImageSkyModel();
    3800           0 :         sm_p->setSubAlgorithm("hogbom");
    3801           0 :         doMultiFields_p = false;
    3802             :         os << LogIO::NORMAL // Loglevel INFO
    3803           0 :            << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
    3804             :       }
    3805           0 :       else if (algorithm=="msmfs") {
    3806           0 :         doMultiFields_p = false;
    3807           0 :         doWideBand_p = true;
    3808             : 
    3809             :         // check for wrong ftmachine specs.
    3810           0 :         if ( (ftmachine_p != "ft") && (ftmachine_p != "wproject") && 
    3811           0 :              (ftmachine_p != "wbawp") && (ftmachine_p != "nift") &&
    3812           0 :              (ftmachine_p != "mosaic") && (ftmachine_p != "awproject") ) {
    3813             :           os << LogIO::SEVERE
    3814             :              << "Multi-scale Multi-frequency Clean currently works only with ft, wproject and mosaic (and wbawp,nift,awproject)"
    3815           0 :              << LogIO::POST;
    3816           0 :           return retval;
    3817             :         }
    3818             :         
    3819           0 :         useNewMTFT_p=false;
    3820           0 :         if( ftmachine_p == "awproject" ) { useNewMTFT_p=true; }
    3821             : 
    3822             : 
    3823           0 :         if (!scaleInfoValid_p) {
    3824           0 :           this->unlock();
    3825           0 :           os << LogIO::WARN << "Scales not yet set, using power law" << LogIO::POST;
    3826           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p, 1 ,reffreq_p);
    3827             :         }
    3828           0 :         if (scaleMethod_p=="uservector") {    
    3829           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p,userScaleSizes_p,reffreq_p);
    3830             :         } else {
    3831           0 :           sm_p = new WBCleanImageSkyModel(ntaylor_p,nscales_p,reffreq_p);
    3832             :         }
    3833             :         os << LogIO::NORMAL // Loglevel INFO
    3834           0 :            << "Using multi frequency synthesis algorithm" << LogIO::POST;
    3835           0 :         ((WBCleanImageSkyModel*)sm_p)->imageNames = Vector<String>(image);
    3836             :         /* Check masks. Should be only one per field. Duplicate the name ntaylor_p times 
    3837             :            Note : To store taylor-coefficients, msmfs uses the same data structure as for
    3838             :                   multi-field imaging. In the case of multifield and msmfs, the list of 
    3839             :                   images is nested and follows a field-major ordering.
    3840             :                   All taylor-coeffs for a single field should have the same mask (for now).
    3841             :            For now, since only single-field is allowed for msmfs, we have the following.*/
    3842             :       }
    3843             :       else {
    3844           0 :         this->unlock();
    3845             :         os << LogIO::SEVERE << "Unknown algorithm: " << algorithm 
    3846           0 :            << LogIO::POST;
    3847             :         
    3848           0 :         return retval;
    3849             :       }
    3850             :    
    3851           0 :       AlwaysAssert(sm_p, AipsError);
    3852           0 :       sm_p->setAlgorithm("clean");
    3853             : 
    3854             :       //    if (!se_p)
    3855           0 :       if(!createSkyEquation(modelNames, fixed, maskNames, complist)) 
    3856             :         {
    3857             :         
    3858           0 :           return retval;
    3859             :         }
    3860           0 :       os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
    3861           0 :     }
    3862             :     else{
    3863             :       //adding or modifying mask associated with skyModel
    3864           0 :       addMasksToSkyEquation(maskNames,fixed);
    3865             :     }
    3866             :     //No need to add residuals will let sm_p use tmpimage ones and we'll copy them in restore 
    3867           0 :     if(!addResiduals(residualNames))
    3868           0 :        throw(AipsError("Problem in attaching to residual images")); 
    3869             :     // The old plot that showed how much flux was being incorporated in each
    3870             :     // scale.   No longer available, slated for removal.
    3871             :     // if (displayProgress) {
    3872             :     //   sm_p->setDisplayProgress(true);
    3873             :     //   sm_p->setPGPlotter( getPGPlotter() );
    3874             :     // }
    3875             : 
    3876             : 
    3877             : 
    3878           0 :     sm_p->setGain(gain);
    3879           0 :     sm_p->setNumberIterations(niter);
    3880           0 :     sm_p->setThreshold(threshold.get("Jy").getValue());
    3881           0 :     sm_p->setCycleFactor(cyclefactor_p);
    3882           0 :     sm_p->setCycleSpeedup(cyclespeedup_p);
    3883           0 :     sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p);
    3884             :     {
    3885           0 :       ostringstream oos;
    3886           0 :       oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
    3887           0 :           << threshold;
    3888           0 :       os << LogIO::NORMAL << String(oos) << LogIO::POST; // More for the
    3889             :                                                          // logfile than the
    3890             :                                                          // log window.
    3891           0 :     }
    3892             : 
    3893             :     os << LogIO::NORMAL << (firstrun ? "Start" : "Continu")
    3894           0 :        << "ing deconvolution" << LogIO::POST; // Loglevel PROGRESS
    3895           0 :     if(se_p->solveSkyModel()) {
    3896             :       os << LogIO::NORMAL
    3897             :          << (niter == 0 ? "Image OK" : "Successfully deconvolved image")
    3898           0 :          << LogIO::POST; // Loglevel PROGRESS
    3899             :     }
    3900             :     else {
    3901           0 :       converged=false;
    3902           0 :       os << LogIO::NORMAL << "Threshhold not reached yet." << LogIO::POST; // Loglevel PROGRESS
    3903             :     }
    3904             :     
    3905             : 
    3906           0 :     printbeam(sm_p, os, firstrun);
    3907             :     
    3908           0 :     if(((algorithm.substr(0,5)=="clark") || algorithm=="hogbom" ||
    3909           0 :         algorithm=="multiscale") && (niter != 0))
    3910             :       //write the model visibility to ms for now 
    3911           0 :       sm_p->solveResiduals(*se_p, true);
    3912             :     
    3913           0 :     for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    3914           0 :       (residuals_p[k])->copyData(sm_p->getResidual(k));
    3915             :     }
    3916             :     /////////////
    3917             : 
    3918             :     //cerr << "Time taken " << omp_get_wtime()-wtime0 << endl;
    3919             :     ////////////
    3920           0 :     retval.define("maxresidual", (sm_p->threshold()));
    3921           0 :     retval.define("iterations", (sm_p->numberIterations()));
    3922           0 :     retval.define("converged", converged);
    3923           0 :     savePSF(psfnames);
    3924           0 :     redoSkyModel_p=false;
    3925           0 :     writeFluxScales(fluxscale_p);
    3926             :     // restoreImages(image); // Moved to iClean so that it happens only once.
    3927             :     
    3928             :     
    3929           0 :     this->unlock();
    3930             : 
    3931           0 :     return retval;
    3932           0 :   }
    3933           0 :   catch (PSFZero&  x)
    3934             :     {
    3935             :       //os << LogIO::WARN << x.what() << LogIO::POST;
    3936           0 :       savePSF(psfnames);
    3937           0 :       this->unlock();
    3938           0 :       throw(AipsError(String("PSFZero  ")+ x.getMesg() + String(" : Please check that the required data exists and is not flagged.")));
    3939             :       return retval;
    3940           0 :     }  
    3941           0 :   catch (exception &x) { 
    3942           0 :     this->unlock();
    3943           0 :     destroySkyEquation();
    3944           0 :     throw(AipsError(x.what()));
    3945             : 
    3946             :     return retval;
    3947           0 :   } 
    3948             : 
    3949           0 :   catch(...){
    3950           0 :     this->unlock();
    3951           0 :     destroySkyEquation();
    3952             :     //Unknown exception...
    3953           0 :     throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    3954           0 :   }
    3955             :   this->unlock();
    3956             : 
    3957             :   os << LogIO::NORMAL << "Exiting Imager::clean" << LogIO::POST; // Loglevel PROGRESS
    3958             :   return retval;
    3959           0 : }
    3960             : 
    3961             : // Mem algorithm
    3962           0 : Bool Imager::mem(const String& algorithm,
    3963             :                  const Int niter, 
    3964             :                  const Quantity& sigma, 
    3965             :                  const Quantity& targetFlux,
    3966             :                  const Bool constrainFlux,
    3967             :                  const Bool displayProgress, 
    3968             :                  const Vector<String>& model, 
    3969             :                  const Vector<Bool>& fixed,
    3970             :                  const String& complist,
    3971             :                  const Vector<String>& prior,
    3972             :                  const Vector<String>& mask,
    3973             :                  const Vector<String>& image,
    3974             :                  const Vector<String>& residual)
    3975             : {
    3976           0 :    if(!valid())
    3977             :     {
    3978           0 :       return false;
    3979             :     }
    3980           0 :    logSink_p.clearLocally();
    3981           0 :    LogIO os(LogOrigin("imager", "mem()"), logSink_p);
    3982             :   
    3983           0 :   this->lock();
    3984             :   try {
    3985           0 :     if(!assertDefinedImageParameters()) 
    3986             :       {
    3987           0 :         return false;
    3988             :       }
    3989           0 :     os << LogIO::NORMAL << "Deconvolving images with MEM" << LogIO::POST; // Loglevel PROGRESS
    3990             :     
    3991           0 :     Int nmodels=model.nelements();
    3992             :     os << LogIO::NORMAL  // Loglevel INFO
    3993           0 :        << "Found " << nmodels << " specified model images" << LogIO::POST;
    3994             :     
    3995           0 :     if(model.nelements()>0) {
    3996           0 :       for (uInt thismodel=0;thismodel<model.nelements();++thismodel) {
    3997           0 :         if(model(thismodel)=="") {
    3998           0 :           this->unlock();
    3999             :           os << LogIO::SEVERE << "Need a name for model "
    4000           0 :              << thismodel << LogIO::POST;
    4001           0 :           return false;
    4002             :         }
    4003             :       }
    4004             :     }
    4005             :     
    4006           0 :     Vector<String> modelNames=model;
    4007             :     // Make first image with the required shape and coordinates only if
    4008             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    4009           0 :     if(modelNames(0)=="") modelNames(0)=imageName()+".mem";
    4010           0 :     if(!Table::isWritable(modelNames(0))) {
    4011           0 :       make(modelNames(0));
    4012             :     }
    4013             :     
    4014           0 :     Vector<String> maskNames(nmodels);
    4015           0 :     if(Int(mask.nelements())==nmodels) {
    4016           0 :       maskNames=mask;
    4017           0 :       for(Int k=0; k < nmodels; ++k){
    4018           0 :         if(mask(k)!=""&& !Table::isReadable(mask(k))) {
    4019             :           os << LogIO::WARN 
    4020             :              << "Mask" << mask(k) 
    4021             :              << " is unreadable; ignoring masks altogether " 
    4022           0 :              << LogIO::POST;
    4023           0 :           maskNames.resize(1);
    4024           0 :           maskNames(0)="";
    4025             :         }
    4026             :       }
    4027             :     }
    4028             :     else {
    4029           0 :       maskNames.resize(1);
    4030           0 :       maskNames(0)="";
    4031             :     }
    4032             :     
    4033             :     // Always fill in the residual images
    4034           0 :     Vector<String> residualNames(nmodels);
    4035           0 :     if(Int(residual.nelements())==nmodels) {
    4036           0 :       residualNames=residual;
    4037             :     }
    4038             :     else {
    4039           0 :       residualNames="";
    4040             :     }
    4041           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4042           0 :       if(residualNames(thismodel)=="") {
    4043           0 :         residualNames(thismodel)=modelNames(thismodel)+".residual";
    4044             :       }
    4045           0 :       removeTable(residualNames(thismodel));
    4046           0 :       if(!clone(model(thismodel), residualNames(thismodel)))
    4047             :         {
    4048           0 :           return false;
    4049             :         }
    4050             :     }
    4051             :     
    4052             :     // Make an ImageSkyModel with the specified polarization representation
    4053             :     // (i.e. circular or linear)
    4054           0 :     if(algorithm=="entropy") {
    4055           0 :       sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
    4056           0 :                                     targetFlux.get("Jy").getValue(),
    4057             :                                     constrainFlux,
    4058             :                                     prior,
    4059           0 :                                     algorithm);
    4060             :       os << LogIO::NORMAL // Loglevel INFO
    4061           0 :          << "Using single-field algorithm with Maximum Entropy" << LogIO::POST;
    4062           0 :       if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4063           0 :         sm_p->setSubAlgorithm("full");
    4064             :     }
    4065           0 :     else if (algorithm=="emptiness") {
    4066           0 :       sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
    4067           0 :                                     targetFlux.get("Jy").getValue(),
    4068             :                                     constrainFlux,
    4069             :                                     prior,
    4070           0 :                                     algorithm);
    4071             :       os << LogIO::NORMAL // Loglevel INFO
    4072           0 :          << "Using single-field algorithm with Maximum Emptiness" << LogIO::POST;
    4073           0 :       if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4074           0 :         sm_p->setSubAlgorithm("full");
    4075             :     }
    4076           0 :     else if (algorithm=="mfentropy") {
    4077           0 :       sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
    4078           0 :                                       targetFlux.get("Jy").getValue(),
    4079             :                                       constrainFlux,
    4080             :                                       prior,
    4081           0 :                                       algorithm);
    4082           0 :       doMultiFields_p = true;
    4083           0 :       os << LogIO::NORMAL << "Using Maximum Entropy" << LogIO::POST; // Loglevel INFO
    4084             :       //   if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4085           0 :       sm_p->setSubAlgorithm("full");
    4086           0 :     } else if (algorithm=="mfemptiness") {
    4087           0 :       sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
    4088           0 :                                       targetFlux.get("Jy").getValue(),
    4089             :                                       constrainFlux,
    4090             :                                       prior,
    4091           0 :                                       algorithm);
    4092           0 :       doMultiFields_p = true;
    4093           0 :       os << LogIO::NORMAL << "Using Maximum Emptiness" << LogIO::POST; // Loglevel INFO
    4094             :       // if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
    4095           0 :       sm_p->setSubAlgorithm("full");
    4096             :     } else {
    4097           0 :       this->unlock();
    4098           0 :       os << LogIO::SEVERE << "Unknown algorithm: " << algorithm << LogIO::POST;
    4099           0 :       return false;
    4100             :     }
    4101           0 :     AlwaysAssert(sm_p, AipsError);
    4102           0 :     sm_p->setAlgorithm("mem");
    4103           0 :     if (displayProgress) {
    4104           0 :       sm_p->setDisplayProgress(true);
    4105             :     }
    4106           0 :     sm_p->setNumberIterations(niter);
    4107           0 :     sm_p->setCycleFactor(cyclefactor_p);   // used by mf algs
    4108           0 :     sm_p->setCycleSpeedup(cyclespeedup_p); // used by mf algs
    4109           0 :     sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p); // used by mf algs
    4110             : 
    4111             :     {
    4112           0 :       ostringstream oos;
    4113           0 :       oos << "MEM algorithm = " <<algorithm<<", Niter = "<<niter<<", Sigma = "
    4114           0 :           <<sigma << ", Target Flux = " << targetFlux;
    4115           0 :       os << LogIO::DEBUG1 << String(oos) << LogIO::POST;
    4116           0 :     }
    4117             :  
    4118             :     //    if (!se_p)
    4119           0 :     if(!createSkyEquation(modelNames, fixed, maskNames, complist)) 
    4120             :       {
    4121           0 :         return false;
    4122             :       }
    4123           0 :     os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
    4124             :     
    4125           0 :     addResidualsToSkyEquation(residualNames);
    4126             : 
    4127           0 :     os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4128           0 :     if(se_p->solveSkyModel()) {
    4129           0 :       os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
    4130             :     }
    4131             :     else {
    4132           0 :       os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
    4133             :     }
    4134             : 
    4135             :     // Get the PSF fit while we are here
    4136           0 :     if(!beamValid_p){
    4137           0 :       ImageBeamSet beam=sm_p->beam(0);
    4138           0 :       if(beam.nelements() > 0){
    4139             :         /*beam_p.setMajorMinor(
    4140             :                         Quantity(abs(beam(0)), "arcsec"), Quantity(abs(beam(1)), "arcsec")
    4141             :                 );
    4142             :           beam_p.setPA(Quantity(beam(2), "deg"));
    4143             :         */
    4144           0 :         beam_p=beam;
    4145           0 :         beamValid_p=true;
    4146             :       }
    4147           0 :     }
    4148           0 :     if(algorithm=="entropy" || algorithm=="emptiness" )
    4149           0 :       sm_p->solveResiduals(*se_p, true);
    4150           0 :     writeFluxScales(fluxscale_p); 
    4151           0 :     restoreImages(image);
    4152           0 :     destroySkyEquation();  
    4153           0 :     this->writeHistory(os);
    4154             :     try{
    4155             :       { // write data processing history into image logtable
    4156           0 :         LoggerHolder imagelog (false);
    4157           0 :         LogSink& sink = imagelog.sink();
    4158           0 :         LogOrigin lor( String("imager"), String("mem()") );
    4159           0 :         LogMessage msg(lor);
    4160           0 :         sink.postLocally(msg);
    4161           0 :         MSHistoryColumns msHis(ms_p->history());
    4162           0 :         transferHistory(imagelog, msHis);
    4163           0 :         for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4164             :           PagedImage<Float> restoredImage(image(thismodel),
    4165           0 :                                           TableLock(TableLock::UserLocking));
    4166           0 :           LoggerHolder& log = restoredImage.logger();
    4167           0 :           log.append(imagelog);
    4168           0 :           log.flush();
    4169           0 :         }
    4170           0 :       }
    4171             :     }
    4172           0 :     catch(exception& x){
    4173             :       
    4174           0 :       os << LogIO::WARN << "Caught exception: " << x.what()
    4175           0 :          << LogIO::POST;
    4176             :       os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
    4177           0 :          <<LogIO::POST; 
    4178             :       //continue and wrap up this function as normal
    4179             :       
    4180           0 :     }
    4181           0 :     catch(...){
    4182             :       //Unknown exception...
    4183           0 :       throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
    4184           0 :     }
    4185             :     
    4186           0 :     this->unlock();
    4187             : 
    4188           0 :     return true;
    4189           0 :   } catch (exception& x) {
    4190           0 :     this->unlock();
    4191           0 :     throw(AipsError(x.what()));
    4192             : 
    4193             :     return false;
    4194           0 :   } 
    4195             :   this->unlock();
    4196             :   return true;
    4197             : 
    4198           0 : }
    4199             : 
    4200             :     
    4201             : // NNLS algorithm
    4202           0 : Bool Imager::nnls(const String&,  const Int niter, const Float tolerance, 
    4203             :                   const Vector<String>& model, const Vector<Bool>& fixed,
    4204             :                   const String& complist,
    4205             :                   const Vector<String>& fluxMask,
    4206             :                   const Vector<String>& dataMask,
    4207             :                   const Vector<String>& residual,
    4208             :                   const Vector<String>& image)
    4209             : {
    4210           0 :   if(!valid()) return false;
    4211           0 :   LogIO os(LogOrigin("imager", "nnls()", WHERE));
    4212             :   
    4213           0 :   this->lock();
    4214             :   try {
    4215           0 :     if(!assertDefinedImageParameters()) return false;
    4216             :     
    4217           0 :     os << LogIO::NORMAL << "Performing NNLS deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4218             :     
    4219           0 :     if(niter<0) {
    4220           0 :       this->unlock();
    4221           0 :       os << LogIO::SEVERE << "Number of iterations must be positive" << LogIO::POST;
    4222           0 :       return false;
    4223             :     }
    4224           0 :     if(tolerance<0.0) {
    4225           0 :       this->unlock();
    4226           0 :       os << LogIO::SEVERE << LogIO::SEVERE << "Tolerance must be positive" << LogIO::POST;
    4227           0 :       return false;
    4228             :     }
    4229             :     
    4230             :     // Add the images to the ImageSkyModel
    4231           0 :     Int nmodels=model.nelements();
    4232           0 :     if(nmodels>1) os<< "Can only process one model" << LogIO::POST;
    4233             :     
    4234           0 :     if(model(0)=="") {
    4235           0 :       this->unlock();
    4236           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    4237           0 :       return false;
    4238             :     }
    4239             :     
    4240           0 :     if(!Table::isWritable(model(0))) {
    4241           0 :       make(model(0));
    4242           0 :       this->lock();
    4243             :     }
    4244             :     
    4245             :     // Always fill in the residual images
    4246           0 :     Vector<String> residualNames(nmodels);
    4247           0 :     if(Int(residual.nelements())==nmodels) {
    4248           0 :       residualNames=residual;
    4249             :     }
    4250             :     else {
    4251           0 :       residualNames="";
    4252             :     }
    4253           0 :     for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    4254           0 :       if(residualNames(thismodel)=="") {
    4255           0 :         residualNames(thismodel)=model(thismodel)+".residual";
    4256             :       }
    4257           0 :       removeTable(residualNames(thismodel));
    4258           0 :       if(!clone(model(thismodel), residualNames(thismodel))) return false;
    4259             :     }
    4260             :     
    4261             :     // Now make the NNLS ImageSkyModel
    4262           0 :     sm_p= new NNLSImageSkyModel();
    4263           0 :     sm_p->setNumberIterations(niter);
    4264           0 :     sm_p->setTolerance(tolerance);
    4265           0 :     sm_p->setAlgorithm("nnls");
    4266             :     os << LogIO::DEBUG1
    4267           0 :        << "NNLS Niter = " << niter << ", Tolerance = " << tolerance << LogIO::POST;
    4268             : 
    4269             :     //    if (!se_p)
    4270           0 :     if(!createSkyEquation(model, fixed, dataMask, fluxMask, complist)) return false;
    4271             : 
    4272           0 :     addResidualsToSkyEquation(residualNames);
    4273             :     
    4274           0 :     os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
    4275             : 
    4276           0 :     if(se_p->solveSkyModel()) {
    4277           0 :       os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
    4278             :     }
    4279             :     else {
    4280           0 :       os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
    4281             :     }
    4282             :     
    4283             :     // Get the PSF fit while we are here
    4284           0 :     StokesImageUtil::FitGaussianPSF(sm_p->PSF(0), beam_p);
    4285           0 :     beamValid_p=true;
    4286             :    
    4287             :     
    4288             :     // Restore the image
    4289           0 :     restoreImages(image);
    4290             : 
    4291           0 :     destroySkyEquation();
    4292           0 :     this->unlock();
    4293           0 :     return true;
    4294           0 :   } catch (AipsError x) {
    4295           0 :     this->unlock();
    4296           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4297           0 :     return false;
    4298           0 :   } 
    4299             :   this->unlock();
    4300             :   return true;
    4301           0 : }
    4302             : 
    4303             : // Fourier transform the model and componentlist
    4304           0 : Bool Imager::ft(const Vector<String>& model, const String& complist,
    4305             :                 const Bool incremental, const Double phaseCenTime)
    4306             : {
    4307           0 :   if(!valid()) return false;
    4308             :   
    4309           0 :   LogIO os(LogOrigin("imager", "ft()", WHERE));
    4310             : 
    4311           0 :   if (wvi_p==NULL)
    4312           0 :     os << LogIO::WARN << "Please make sure MS is writable when using Imager::ft" << LogIO::EXCEPTION;
    4313             :   
    4314           0 :   this->lock();
    4315             :   try {
    4316             :     
    4317           0 :     if(!redoSkyModel_p){
    4318             :       //let us try to update the sm_p then
    4319             :       //so as to keep the state and psf's etc if they have been calculated
    4320             :       //useful when cleaning, modify/clip model then predict, selfcal and clean again
    4321           0 :       if(!updateSkyModel(model, complist))
    4322           0 :         destroySkyEquation();
    4323             :     }
    4324             : 
    4325             :     os << LogIO::NORMAL // Loglevel INFO
    4326           0 :        << String("Fourier transforming: ") + 
    4327           0 :       (incremental ? String("adding to "): String("replacing "))+ 
    4328           0 :       (useModelCol_p ? String("MODEL_DATA column") : String("visibility model header")) << LogIO::POST;
    4329             :    
    4330           0 :     if (redoSkyModel_p){
    4331           0 :       if(!createSkyEquation(model, complist)) return false;
    4332             :     }
    4333           0 :     if(incremental){
    4334           0 :       for (Int mod=0; mod < (sm_p->numberOfModels()); ++mod){
    4335           0 :         (sm_p->deltaImage(mod)).copyData(sm_p->image(mod));
    4336             :       }
    4337             :     }
    4338           0 :     se_p->setPhaseCenterTime(phaseCenTime);
    4339           0 :     se_p->predict(incremental);
    4340             :     
    4341             :     // destroySkyEquation();
    4342             :     
    4343           0 :     this->unlock();
    4344           0 :     return true;
    4345           0 :   } catch (AipsError x) {
    4346           0 :     this->unlock();
    4347           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4348           0 :     return false;
    4349           0 :   } 
    4350             :   this->unlock();
    4351             :   return true;
    4352           0 : }
    4353             : 
    4354           0 : Bool Imager::setjy(const Int fieldid, 
    4355             :                    const Int spectralwindowid,
    4356             :                    const Vector<Double>& fluxDensity, const String& standard)
    4357             : {
    4358             :   // the old interface to new interface
    4359           0 :   String fieldnames="";
    4360           0 :   String spwstring="";
    4361           0 :   Vector<Int>fldids(1,fieldid);
    4362           0 :   Vector<Int>spwids(1,spectralwindowid);
    4363           0 :   return setjy(fldids, spwids, fieldnames, spwstring, fluxDensity, standard);
    4364             : 
    4365           0 : }
    4366             : 
    4367           0 : Bool Imager::setjy(const Vector<Int>& /*fieldid*/,
    4368             :                    const Vector<Int>& /*spectralwindowid*/,
    4369             :                    const String& fieldnames, const String& spwstring,
    4370             :                    const Vector<Double>& fluxDensity, const String& standard)
    4371             : {
    4372           0 :   if(!valid()) return false;
    4373           0 :   logSink_p.clearLocally();
    4374           0 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    4375           0 :   this->lock();
    4376             : 
    4377           0 :   String tempCL;
    4378             :   try {
    4379           0 :     Bool precompute=(fluxDensity(0) <= 0);
    4380             : 
    4381             :     // Figure out which fields/spws to treat
    4382           0 :     Record selrec=ms_p->msseltoindex(spwstring, fieldnames);
    4383           0 :     Vector<Int> fldids(selrec.asArrayInt("field"));
    4384           0 :     Vector<Int> spwids(selrec.asArrayInt("spw"));
    4385             : 
    4386           0 :     expand_blank_sel(spwids, ms_p->spectralWindow().nrow());
    4387           0 :     expand_blank_sel(fldids, ms_p->field().nrow());
    4388             : 
    4389             :     // Loop over field id. and spectral window id.
    4390           0 :     Vector<Double> fluxUsed(4);
    4391           0 :     String fluxScaleName;
    4392           0 :     Bool matchedScale=false;
    4393             :     Int spwid, fldid;
    4394           0 :     MSColumns msc(*ms_p);
    4395           0 :     ConstantSpectrum cspectrum;
    4396             :     // TT
    4397           0 :     Double meantime = msc.time()(0);
    4398           0 :     meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    4399           0 :     MEpoch mtime(msc.timeMeas()(0));
    4400           0 :     mtime.set(Quantity(meantime, "s"));
    4401             : 
    4402             : 
    4403           0 :     for (uInt kk=0; kk<fldids.nelements(); ++kk) {
    4404           0 :       fldid=fldids[kk];
    4405             :       // Extract field name and field center position 
    4406           0 :       MDirection position=msc.field().phaseDirMeas(fldid, meantime);
    4407           0 :       String fieldName=msc.field().name()(fldid);
    4408             : 
    4409           0 :       for (uInt jj=0; jj< spwids.nelements(); ++jj) {
    4410           0 :         spwid=spwids[jj];
    4411             : 
    4412             :         // Determine spectral window center frequency
    4413           0 :         IPosition ipos(1,0);
    4414           0 :         MFrequency mfreq=msc.spectralWindow().chanFreqMeas()(spwid)(ipos);
    4415           0 :         Array<Double> freqArray;
    4416           0 :         msc.spectralWindow().chanFreq().get(spwid, freqArray, true);
    4417           0 :         Double medianFreq=median(freqArray);
    4418           0 :         mfreq.set(MVFrequency(medianFreq));
    4419             : 
    4420           0 :         fluxUsed=fluxDensity;
    4421           0 :         fluxScaleName="user-specified";
    4422           0 :         if (precompute) {
    4423             :           // Pre-compute flux density for standard sources if not specified
    4424             :           // using the specified flux scale standard or catalog.
    4425             : 
    4426             : 
    4427             :           FluxStandard::FluxScale fluxScaleEnum;
    4428           0 :           matchedScale=FluxStandard::matchStandard(standard, fluxScaleEnum, 
    4429             :                                                    fluxScaleName);
    4430             :           (void)matchedScale;
    4431           0 :           FluxStandard fluxStd(fluxScaleEnum);
    4432           0 :           Flux<Double> returnFlux, returnFluxErr;
    4433             : 
    4434           0 :           if (fluxStd.compute(fieldName, position, mfreq, mtime, returnFlux, returnFluxErr)) {
    4435             :             // Standard reference source identified
    4436           0 :             returnFlux.value(fluxUsed);
    4437             :           } 
    4438             : 
    4439             :           // dgoscha, NCSA, 02 May, 2002
    4440             :           // this else condtion is to handle the case where the user
    4441             :           // specifies standard='SOURCE' in the setjy argument.  This will
    4442             :           // then look into the SOURCE_MODEL column of the SOURCE subtable
    4443             :           // for a table-record entry that points to a component list with the
    4444             :           // model information in it.
    4445             : 
    4446             : 
    4447           0 :           else if (standard==String("SOURCE")) {
    4448             :                 // Look in the SOURCE_MODEL column of the SOURCE subtable for 
    4449             :                 // the name of the CL which contains the model.
    4450             : 
    4451             :                 // First test to make sure the SOURCE_MODEL column exists.
    4452           0 :                 if (ms_p->source().tableDesc().isColumn("SOURCE_MODEL")) {
    4453           0 :                         TableRecord modelRecord;
    4454           0 :                         msc.source().sourceModel().get(0, modelRecord);
    4455             :         
    4456             :                         // Get the name of the model component list from the table record
    4457             :                         Table modelRecordTable = 
    4458           0 :                                 modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
    4459           0 :                         String modelCLName = modelRecordTable.tableName();
    4460           0 :                         modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
    4461             : 
    4462             :                         // Now grab the flux from the model component list and use.
    4463           0 :                         ComponentList modelCL = ComponentList(Path(modelCLName), true);
    4464           0 :                         SkyComponent fluxComponent = modelCL.component(fldid);
    4465             : 
    4466           0 :                         fluxUsed = 0;
    4467           0 :                         fluxUsed = real(fluxComponent.flux().value());
    4468           0 :                         fluxScaleName = modelCLName;
    4469           0 :                 }
    4470             :                 else {
    4471             :                         os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
    4472             :                            << LogIO::SEVERE << "Using default, I=1.0"
    4473           0 :                            << LogIO::POST;
    4474           0 :                         fluxUsed = 0;
    4475           0 :                         fluxUsed(0) = 1.0;
    4476             :                 }
    4477             :           }
    4478             : 
    4479             :           else {
    4480             :             // Source not found; use Stokes I=1.0 Jy for now
    4481           0 :             fluxUsed=0;
    4482           0 :             fluxUsed(0)=1.0;
    4483           0 :             fluxScaleName="default";
    4484             :           };
    4485           0 :         }
    4486             : 
    4487             :         // Set the component flux density
    4488           0 :         Flux<Double> fluxval;
    4489           0 :         fluxval.setValue(fluxUsed);
    4490             : 
    4491             :         // Create a point component at the field center
    4492             :         // with the specified flux density
    4493           0 :         PointShape point(position);
    4494           0 :         SkyComponent skycomp(fluxval, point, cspectrum);
    4495             : 
    4496             :         // Create a component list containing this entry
    4497           0 :         String baseString=msname_p + "." + fieldName + ".spw" +
    4498           0 :           String::toString(spwid);
    4499           0 :         tempCL=baseString + ".tempcl";
    4500             : 
    4501             :         // Force a call to the ComponentList destructor
    4502             :         // using scoping rules.
    4503             :         { 
    4504           0 :           ComponentList cl;
    4505           0 :           cl.add(skycomp);
    4506           0 :           cl.rename(tempCL, Table::New);
    4507           0 :         }
    4508             : 
    4509             :         // Select the uv-data for this field and spw. id.;
    4510             :         // all frequency channels selected.
    4511           0 :         Vector<Int> selectSpw(1), selectField(1);
    4512           0 :         selectSpw(0)=spwid;
    4513           0 :         selectField(0)=fldid;
    4514           0 :         String msSelectString = "";
    4515           0 :         Vector<Int> numDeChan(1);
    4516           0 :         numDeChan[0]=0;
    4517           0 :         Vector<Int> begin(1);
    4518           0 :         begin[0]=0;
    4519           0 :         Vector<Int> stepsize(1);
    4520           0 :         stepsize[0]=1;
    4521           0 :         setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(), 
    4522           0 :                 MRadialVelocity(),
    4523           0 :                 selectSpw, selectField, msSelectString, "", "", Vector<Int>(), 
    4524             :                 "", "", "", "", "", "",true);
    4525             : 
    4526           0 :         if (!nullSelect_p) {
    4527             : 
    4528             :           // Transform the component model table
    4529           0 :           Vector<String> model;
    4530           0 :           ft(model, tempCL, false);
    4531             : 
    4532             :           // Log flux density used for this field and spectral window
    4533           0 :           os.output().width(12);
    4534           0 :           os << fieldName << "  spwid=";
    4535           0 :           os.output().width(3);
    4536           0 :           os << (spwid) << "  ";
    4537           0 :           os.output().width(0);
    4538           0 :           os.output().precision(4);
    4539           0 :           os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    4540           0 :           os << "Q=" << fluxUsed(1) << ", ";
    4541           0 :           os << "U=" << fluxUsed(2) << ", ";
    4542           0 :           os << "V=" << fluxUsed(3) << "] Jy, ";
    4543           0 :           os << ("(" + fluxScaleName + ")") << LogIO::POST;
    4544           0 :         };
    4545             :           
    4546             :         // Delete the temporary component list and image tables
    4547           0 :         TableUtil::deleteTable(tempCL);
    4548             : 
    4549           0 :       }
    4550           0 :     }
    4551           0 :     this->writeHistory(os);
    4552           0 :     this->unlock();
    4553           0 :     return true;
    4554             : 
    4555           0 :   } catch (AipsError x) {
    4556           0 :     this->unlock();
    4557           0 :     if(TableUtil::canDeleteTable(tempCL)) TableUtil::deleteTable(tempCL);
    4558           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    4559           0 :     return false;
    4560           0 :   } 
    4561             :   return true;
    4562           0 : }
    4563             : 
    4564             : // This is the one used by im.setjy() (because it has a model arg).
    4565             : // CURRENT SETJY CODE
    4566           0 : Record Imager::setjy(const Vector<Int>& /*fieldid*/,
    4567             :                    const Vector<Int>& /*spectralwindowid*/,
    4568             :                    const String& fieldnames, const String& spwstring,
    4569             :                    const String& model,
    4570             :                    const Vector<Double>& fluxDensity, 
    4571             :                    const String& standard, const Bool chanDep,
    4572             :                    //const Double spix, const MFrequency& reffreq,
    4573             :                    const Vector<Double>& spix, const MFrequency& reffreq,
    4574             :                    const Vector<Double>& pipars,const Vector<Double>& papars, 
    4575             :                    const Double& rotMeas,
    4576             :                    const String& timerange, const String& scanstr,
    4577             :                    const String& intentstr, const String& obsidstr,
    4578             :                    const String& interpolation)
    4579             : {
    4580             :   //if(!valid())
    4581             :     //return false;
    4582             : 
    4583             :   //Bool didAnything = false;
    4584             :   
    4585           0 :   Record retval;
    4586           0 :   if(!valid()) {
    4587           0 :     retval.define("process",false);
    4588           0 :     return retval;
    4589             :   }
    4590             : 
    4591           0 :   logSink_p.clearLocally();
    4592           0 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    4593           0 :   this->lock();
    4594             : 
    4595             :   // user specified flux densities (IQUV), global to the spws and fields
    4596           0 :   Vector<Double> fluxdens = fluxDensity;
    4597           0 :   if(fluxDensity.nelements() < 4){
    4598           0 :     fluxdens.resize(4,true);
    4599           0 :     for(Int i = fluxDensity.nelements(); i < 4; ++i)
    4600           0 :       fluxdens[i] = 0.0;
    4601             :   }
    4602             : 
    4603           0 :   Vector<String> tempCLs;
    4604           0 :   TempImage<Float> *tmodimage(NULL);
    4605             : 
    4606             :   try{
    4607           0 :     Bool precompute = fluxdens[0] < 0.0;
    4608             : 
    4609             :     // Figure out which fields/spws to treat
    4610             :     // including intent info 
    4611           0 :     MSSelection mssel;
    4612           0 :     mssel.setFieldExpr(fieldnames);
    4613           0 :     mssel.setSpwExpr(spwstring);
    4614           0 :     mssel.setStateExpr(intentstr);
    4615           0 :     TableExprNode exprNode = mssel.toTableExprNode(&(*ms_p));
    4616             :     //Vector<Int> fldids;
    4617           0 :     Vector<Int> fldids(mssel.getFieldList());
    4618           0 :     Vector<Int> selToRawSpwIds(mssel.getSpwList());
    4619             :     // if intent is given try to do AND with fieldIds
    4620           0 :     if (intentstr!="") {
    4621           0 :       mssel_p = new MeasurementSet((*ms_p)(exprNode), &(*ms_p));
    4622           0 :       MSColumns tmpmsc(*mssel_p);
    4623           0 :       Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
    4624           0 :       if (fldidv.nelements()==0) 
    4625           0 :         throw(AipsError("No field ids were selected, please check input parameters"));
    4626           0 :       std::set<Int> ufldids(fldidv.begin(),fldidv.end());
    4627           0 :       std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
    4628           0 :       fldids.resize(tmpv.size());
    4629           0 :       uInt count=0;
    4630           0 :       for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
    4631             :       {
    4632           0 :          fldids(count) = *it;
    4633           0 :          count++;
    4634             :       }
    4635           0 :     }
    4636             :     //else {
    4637             :     //  fldids(mssel.getFieldList());
    4638             :     //}
    4639             :     //cerr<<"fldids.nelements()="<<fldids.nelements()<<endl;
    4640             :     //for (uInt i = 0; i < fldids.nelements(); i++) {
    4641             :     //    cerr<<"fldids="<<fldids(i)<<endl;
    4642             :     //}
    4643             :     //Record selrec = ms_p->msseltoindex(spwstring, fieldnames);
    4644             :     //Vector<Int> fldids(selrec.asArrayInt("field"));
    4645             :     //Vector<Int> selToRawSpwIds(selrec.asArrayInt("spw"));
    4646             :  
    4647           0 :     expand_blank_sel(selToRawSpwIds, ms_p->spectralWindow().nrow());
    4648           0 :     expand_blank_sel(fldids, ms_p->field().nrow());
    4649             : 
    4650             :     // Warn against multiple fields in some circumstances.
    4651           0 :     if (fldids.nelements() > 1 && (model != "" || !precompute)) {
    4652           0 :       String errmsg("setjy is applying a single ");
    4653             : 
    4654           0 :       if(model != ""){
    4655           0 :         errmsg += "modimage";
    4656           0 :         if(!precompute)
    4657           0 :           errmsg += " or ";
    4658             :       }
    4659             : 
    4660           0 :       if(!precompute)
    4661           0 :         errmsg += "fluxdensity";
    4662             : 
    4663           0 :       errmsg += " to multiple fields!\n";
    4664             :       os << LogIO::WARN
    4665             :          << errmsg
    4666             :          << "This could be a user error, but sometimes a single name will\n"
    4667             :          << "resolve to > 1 field index.\n"
    4668           0 :          << LogIO::POST;
    4669             :       //throw(AipsError(errmsg));
    4670           0 :     }
    4671             : 
    4672           0 :     os << LogIO::NORMAL;
    4673           0 :     if(precompute || spix[0] != 0.0)
    4674           0 :       os << "Using " << ((chanDep || (!precompute && spix[0] != 0.0)) ? "channel" : 
    4675           0 :                          "spw") << " dependent flux densities";
    4676             :     else
    4677           0 :       os << "The applied flux density does not depend on frequency.";
    4678           0 :     os << LogIO::POST;
    4679             : 
    4680             :     // Ignore user polarization if using an image.
    4681           0 :     if(model != "" &&
    4682           0 :        (fluxdens[1] != 0.0 || fluxdens[2] != 0.0 || fluxdens[3] != 0.0)){
    4683             :       os << LogIO::WARN
    4684             :          << "Using model image, so zeroing user QUV flux densities."
    4685           0 :          << LogIO::POST;
    4686           0 :       fluxdens[1] = fluxdens[2] = fluxdens[3] = 0.0;
    4687           0 :       writeHistory(os);
    4688             :     }
    4689             : 
    4690             :     // Loop over field id. and spectral window id.
    4691             :     //Vector<Double> fluxUsed(4);
    4692           0 :     String fluxScaleName("user-specified");
    4693             :     FluxStandard::FluxScale fluxScaleEnum;
    4694           0 :     if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
    4695           0 :       throw(AipsError(standard + " is not a recognized flux density scale"));
    4696             : 
    4697           0 :     FluxStandard fluxStd(fluxScaleEnum);
    4698           0 :     if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 || 
    4699           0 :         fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017 ) {
    4700           0 :       fluxStd.setInterpMethod(interpolation);
    4701             :     }
    4702             : 
    4703             :     // Setup the frequency, Flux, and ComponentList arrays.
    4704           0 :     uInt nspws = selToRawSpwIds.nelements();
    4705           0 :     Vector<Vector<Flux<Double> > > returnFluxes(nspws), returnFluxErrs(nspws);
    4706           0 :     Vector<Vector<MFrequency> > mfreqs(nspws);
    4707           0 :     Vector<Vector<Double> > fluxUsed(nspws); // fluxesUsed(nspws,4) 
    4708           0 :     MSColumns msc(*ms_p);
    4709           0 :     MEpoch aveEpoch=MEpoch(msc.timeMeas()(0));
    4710             :     const Unit freqUnit = sjy_setup_arrs(returnFluxes, returnFluxErrs, fluxUsed, tempCLs, mfreqs,
    4711           0 :                                          msc.spectralWindow(), nspws, selToRawSpwIds,
    4712           0 :                                          chanDep);
    4713             :     // Processing for each field ***************************************************
    4714           0 :     for(Int fldInd = fldids.nelements(); fldInd--;){
    4715           0 :       Int fldid = fldids[fldInd];
    4716             :       // Extract field name and field center position 
    4717           0 :       MDirection fieldDir = msc.field().phaseDirMeas(fldid, msc.time()(0));
    4718           0 :       String fieldName = msc.field().name()(fldid);
    4719           0 :       Bool foundSrc = false;
    4720             :     
    4721             :       //for returned flux densities
    4722             :       
    4723           0 :       Record retvalperField;
    4724             :       //
    4725             :       //fluxUsed = fluxdens;
    4726           0 :       fluxUsed(0) = fluxdens;
    4727             :       //if(precompute){
    4728             :         // Pre-compute flux density for standard sources if not specified
    4729             :         // using the specified flux scale standard or catalog.
    4730             :         //
    4731             :         // The flux densities are calculated for all spws at once to avoid
    4732             :         // repeatedly digging up the flux model (and possibly the ephemeris).
    4733             :         //
    4734             :         // TT: moving this outside of if(precompute) since selected ms (mssel_p)
    4735             :         // will be needed for other cases to clear the model using 
    4736             :         // VisModelData::ClearModel()
    4737             :         
    4738           0 :         Vector<Int> selectField(1);
    4739           0 :         selectField[0] = fldid;
    4740           0 :         Vector<Int> numDeChan(1);
    4741           0 :         numDeChan[0] = 0;
    4742           0 :         Vector<Int> begin(1);
    4743           0 :         begin[0] = 0;
    4744           0 :         Vector<Int> stepsize(1);
    4745           0 :         stepsize[0] = 1;
    4746           0 :         String msSelectString = "";
    4747           0 :         setdata("none", numDeChan, begin, stepsize, MRadialVelocity(), 
    4748           0 :                 MRadialVelocity(),
    4749             :                 selToRawSpwIds, selectField, msSelectString, timerange, "",
    4750           0 :                 Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
    4751           0 :         if(nullSelect_p){
    4752           0 :           os << ((timerange == "" && scanstr == ""
    4753           0 :                   && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
    4754             :              << "No data was selected for field " << fldid << "."
    4755           0 :              << LogIO::POST;
    4756           0 :           continue;
    4757             :         }
    4758           0 :       if(precompute){
    4759             :         // Make componentlist for each spw.
    4760             :         // Pre-compute flux density for standard sources if not specified
    4761             :         // using the specified flux scale standard or catalog.
    4762             :         //
    4763             :         // The flux densities are calculated for all spws at once to avoid
    4764             :         // repeatedly digging up the flux model (and possibly the ephemeris).
    4765             :         //
    4766           0 :         MSColumns msselc(*mssel_p);
    4767             :         //if(nullSelect_p || msselc.nrow() < 1){
    4768           0 :         if(!nullSelect_p and  msselc.nrow() < 1){
    4769           0 :           os << ((timerange == "" && scanstr == ""
    4770           0 :                   && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
    4771             :              << "No data was selected for field " << fldid << "."
    4772           0 :              << LogIO::POST;
    4773           0 :           continue;
    4774             :         }
    4775             : 
    4776             :         // chnage to return cocantenated CL?
    4777           0 :         foundSrc = sjy_computeFlux(os, fluxStd, returnFluxes, returnFluxErrs, tempCLs,
    4778             :                                    fluxUsed, fluxScaleName, aveEpoch, mfreqs, model, fieldName,
    4779             :                                    msselc, fldid, fieldDir, selToRawSpwIds, standard);
    4780             :         (void)foundSrc;
    4781           0 :       }
    4782             :       
    4783             :       //*************** For loop about spw starts here ****************************
    4784           0 :       Vector<Double>  freqscaling;
    4785           0 :       Vector<Double> freqsOfScale;
    4786           0 :       Vector<Int> rawspwids(nspws);
    4787             :       // make raw spw id list
    4788           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4789           0 :         Int rawspwid = selToRawSpwIds[selspw];
    4790           0 :         rawspwids[selspw]=rawspwid;
    4791             :       } 
    4792             : 
    4793             :         // move inside sjy_computeFlux  - TT, 2014.06.13 
    4794             :         /***
    4795             :         if(foundSrc){
    4796             :           // Log fluxes found from the standard catalog database to HISTORY table 
    4797             :           // get I-flux density for the selected spw (returnFluxes[nspw][4]) 
    4798             :           // Read this as fluxUsed = returnFluxes[selspw][0].value().
    4799             :           os << "CHECK: foundSrc....."<<LogIO::POST;
    4800             :           returnFluxes[selspw][0].value(fluxUsed);
    4801             :             
    4802             :           // Log flux density found for this field and spectral window
    4803             :           os.output().width(12);
    4804             :           os << fieldName;
    4805             :           os.output().width(2);
    4806             :           os << " (fld ind " << fldid << ") spw ";
    4807             :           os << rawspwid << "  ";
    4808             :           os.output().width(0);
    4809             :           os.output().precision(5);
    4810             :           os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    4811             :           os << "Q=" << fluxUsed(1) << ", ";
    4812             :           os << "U=" << fluxUsed(2) << ", ";
    4813             :           os << "V=" << fluxUsed(3) << "] Jy, ";
    4814             :           os << ("(" + fluxScaleName + ")") << LogIO::POST;
    4815             :           writeHistory(os);
    4816             :         }
    4817             :           
    4818             :         // If a model image has been specified, 
    4819             :         //  rescale it according to the I f.d. determined above
    4820             : 
    4821             :         //Vector<Double> freqscaling;
    4822             :         //Vector<Double> freqsOfScale;
    4823             : 
    4824             :         //MEpoch mtime = msc.field().timeMeas()(fldid);
    4825             : 
    4826             :       } //spw for-loop end
    4827             :       ****/
    4828             :       
    4829           0 :       MEpoch mtime = msc.field().timeMeas()(fldid);
    4830             : 
    4831             :       // model image prep. changed to do all spws at once - TT, 2014.06.13
    4832           0 :       if(model != ""){
    4833             : 
    4834           0 :         tmodimage = sjy_prepImage(os, fluxStd, fluxUsed[0], freqsOfScale, freqscaling, model, msc.spectralWindow(),
    4835             :        // tmodimage = sjy_prepImage(os, fluxStd, fluxUsed, freqsOfScale, freqscaling, model, msc.spectralWindow(),
    4836             :       //                          rawspwid, chanDep, mfreqs, selspw, fieldName,
    4837             :                                   selToRawSpwIds, chanDep, mfreqs, fieldName,
    4838             :                                   fieldDir, freqUnit, fluxdens, precompute, spix,
    4839             :                                   reffreq, aveEpoch, fldid);
    4840             :           
    4841             :       }
    4842           0 :       else if (!precompute) {
    4843             :         // do it in sjy_makeComponentList()
    4844             :         // TODO: add polindex, polangle, rm handling
    4845             :         // for now ignore circular polarization
    4846             :         //Vector<Double> cppars(1,0.0);
    4847           0 :         Vector<Double> checkfluxes;
    4848           0 :         sjy_makeComponentList(os, tempCLs, returnFluxes, fluxUsed[0], selToRawSpwIds, mfreqs, fieldName, fieldDir, 
    4849             :                             spix, pipars, papars, rotMeas, reffreq, aveEpoch, fldid);
    4850           0 :         returnFluxes[0][0].value(checkfluxes);
    4851           0 :       }
    4852             :       /*** moved to sjy_makeComponentList()
    4853             :       // make componentlist using flux densities from the user specfied fluxdensity(per-spw) 
    4854             :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4855             :         Int rawspwid = selToRawSpwIds[selspw];
    4856             :         rawspwids[selspw]=rawspwid;
    4857             :         if(model == "" && !precompute){
    4858             :           // **** inside spw for-loop
    4859             :           // fluxUsed was supplied by the user instead of FluxStandard, so
    4860             :           // make a component list for it now, for use in ft.
    4861             : 
    4862             :           // Set the component flux density
    4863             :           Flux<Double> fluxval;
    4864             :           Flux<Double> fluxerr;
    4865             :           fluxval.setValue(fluxUsed[0]);
    4866             :           // Create a point component at the field center
    4867             :           // with the specified flux density 
    4868             :           // - obviously this does not correct for solar objects... 
    4869             :           PointShape point(fieldDir);
    4870             :           SpectralIndex siModel;
    4871             :           if(reffreq.getValue().getValue() > 0.0){
    4872             :             MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
    4873             :             MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
    4874             :             siModel.setRefFrequency(reffreq);
    4875             :             siModel.setIndex(spix);
    4876             :             returnFluxes[selspw][0].setValue(fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][0])));
    4877             :           }
    4878             :           else{
    4879             :             if(spix != 0.0){            // If not the default, complain and quit.
    4880             :               os << LogIO::SEVERE
    4881             :                  << "spix cannot be nonzero with reffreq = 0!"
    4882             :                  << LogIO::POST;
    4883             :               //return false;
    4884             :             }
    4885             :             siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
    4886             :             siModel.setIndex(0.0);
    4887             :           }
    4888             : 
    4889             :           // No worries about varying fluxes or sizes here, so any time will do.
    4890             :           // Moved this line up (TT 2013/05/09) 
    4891             :           //MEpoch mtime = msc.field().timeMeas()(fldid);
    4892             :           tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    4893             :                                                             mfreqs[selspw][0],
    4894             :                                                             mtime, fluxval, point,
    4895             :                                                             siModel,
    4896             :           // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
    4897             :                                                             ms_p->tableName() +
    4898             :                                                             "_setjy_spw" +
    4899             :                                                             String::toString(selspw) +
    4900             :                                                             "_");
    4901             :         }
    4902             :         ***/
    4903             : 
    4904             :         // clear existing model for the selected field and for all selected spws 
    4905             :         // outside spw loop
    4906             :         //if (!useModelCol_p && selspw==0) {
    4907           0 :         if (!useModelCol_p) {
    4908           0 :           String tmpspwstring=spwstring;
    4909           0 :           if (tmpspwstring=="") tmpspwstring="*";
    4910             :           os << LogIO::NORMAL
    4911             :              << "Will clear any existing model with matching field="
    4912             :              << fieldName
    4913             :              << " and spw=" << tmpspwstring
    4914           0 :              << LogIO::POST;
    4915             : 
    4916           0 :           String fldidstr = String::toString(fldid); 
    4917             :           // use field id due to possible MSSelection bug for handing field name with blanks
    4918             :           //VisModelData::clearModel(*mssel_p, fieldName, spwstring)
    4919           0 :           VisModelData::clearModel(*mssel_p, fldidstr, spwstring);
    4920           0 :         }
    4921             :         // TODO: do it for all spw at once............
    4922             :         //sjy_make_visibilities(tmodimage, os, rawspwid, fldid, tempCLs[selspw],
    4923             :         //                      timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    4924             :         
    4925             :         /***
    4926             :         if(tmodimage)
    4927             :           delete tmodimage;
    4928             :         tmodimage = NULL;
    4929             :         //      if (Table::canDeleteTable("temp.setjy.image")) Table::deleteTable("temp.setjy.image");
    4930             : 
    4931             :         if(tempCLs[selspw] != ""){
    4932             :           String errmsg;
    4933             : 
    4934             :           //didAnything = true;
    4935             :           // commentted out for testing of concatCLs, may need to uncommentted later!!!!!!
    4936             : 
    4937             :           if(Table::canDeleteTable(errmsg, tempCLs[selspw]))
    4938             :             Table::deleteTable(tempCLs[selspw]);
    4939             :           else
    4940             :             os << LogIO::WARN
    4941             :                << "Could not rm " << tempCLs[selspw]
    4942             :                << " because the " << errmsg << "."
    4943             :                << LogIO::POST;
    4944             :         }
    4945             :         ***/
    4946             : 
    4947           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4948           0 :         Record subrec;
    4949             :         //store fluxd actually used to scale (not input fluxdensity)
    4950           0 :         Vector<Double> finalFluxUsed;
    4951             :         // Flux of first chan
    4952           0 :         returnFluxes[selspw][0].value(finalFluxUsed);
    4953           0 :         subrec.define("fluxd",finalFluxUsed);
    4954             :         // TODO: add fluxd error when the flux density uncertainties 
    4955             :         //       are corrrectly filled.
    4956             :         //
    4957             :         //retvalperField.defineRecord(String::toString(rawspwid),subrec);
    4958           0 :         retvalperField.defineRecord(String::toString(selToRawSpwIds[selspw]),subrec);
    4959           0 :       }   // for selspw end **********************************************
    4960             :       //retval.defineRecord(fieldName,retvalperField);
    4961           0 :       retvalperField.define("fieldName",fieldName);
    4962           0 :       retval.defineRecord(String::toString(fldid),retvalperField);
    4963             : 
    4964             :       // cocatenate componentlists - not yet used....
    4965             :       //if (tempCLs[0]!="") {
    4966             :         // concatcl name should contains field name mjd etc...
    4967             :       //  ostringstream oss;
    4968             :       //  oss<< ms_p->tableName() << "_setjy_"
    4969             :       //     << fieldName << "_" << mtime.get("d").getValue()
    4970             :       //     << "d.cl";
    4971             :       //  String concatcl(oss);
    4972             :       //  sjy_concatComponentLists(os, tempCLs, concatcl);
    4973             :       //}
    4974             : 
    4975             :       //sjy_make_visibilities(tmodimage, os, rawspwids, fldid, concatcl,
    4976             :       //                      timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    4977             :       //
    4978             :       //### Uncomment above once setjyFTMachine can handle multi-row componentlist ############# 
    4979             : 
    4980           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4981           0 :         sjy_make_visibilities(tmodimage, os, rawspwids[selspw], fldid, tempCLs[selspw],
    4982             :                             timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
    4983             :       }
    4984             :       // #######################################################################################
    4985             :       // clean-up
    4986             :       //  
    4987           0 :       if(tmodimage)
    4988           0 :         delete tmodimage;
    4989           0 :       tmodimage = NULL;
    4990             : 
    4991           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw){
    4992           0 :         if(tempCLs[selspw] != ""){
    4993           0 :           String errmsg;
    4994             : 
    4995             :           //didAnything = true;
    4996             : 
    4997           0 :           if(TableUtil::canDeleteTable(errmsg, tempCLs[selspw]))
    4998           0 :             TableUtil::deleteTable(tempCLs[selspw]);
    4999             :           else
    5000             :             os << LogIO::WARN
    5001           0 :                << "Could not rm " << tempCLs[selspw]
    5002             :                << " because the " << errmsg << "."
    5003           0 :                << LogIO::POST;
    5004             : 
    5005             :           //if(Table::canDeleteTable(errmsg, concatcl))
    5006             :           //  Table::deleteTable(concatcl);
    5007           0 :         }
    5008             :       }
    5009             :       
    5010           0 :     }   // End of loop over fields.
    5011             :     // add a format info for the returned flux densities (Record)
    5012             :     //retval.define("format","{field name: {spw Id: {fluxd: [I,Q,U,V] in Jy}}}");
    5013           0 :     retval.define("format","{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}");
    5014             : 
    5015           0 :     if(!precompute && spix[0] != 0.0 && reffreq.getValue().getValue() > 0.0){
    5016             :       os << LogIO::NORMAL
    5017             :          << "Flux density as a function of frequency (channel 0 of each spw):\n"
    5018             :          << "  Frequency (GHz)    Flux Density (Jy, Stokes I)"
    5019           0 :          << LogIO::POST;
    5020           0 :       for(uInt selspw = 0; selspw < nspws; ++selspw)
    5021           0 :         os << "     " << mfreqs[selspw][0].get("GHz").getValue() << "         "
    5022           0 :            << returnFluxes[selspw][0].value(Stokes::I).getValue()
    5023           0 :            << LogIO::POST;
    5024             :     }
    5025             : 
    5026           0 :     this->writeHistory(os);
    5027           0 :     this->unlock();
    5028             :     //return true;
    5029           0 :   }
    5030           0 :   catch (AipsError x){
    5031           0 :     this->unlock();
    5032           0 :     for(Int i = tempCLs.nelements(); i--;){
    5033           0 :       if(tempCLs[i] != "")
    5034           0 :         TableUtil::deleteTable(tempCLs[i]);
    5035             :     }
    5036           0 :     if (tmodimage) delete tmodimage; tmodimage=NULL;
    5037           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    5038             :     //return false;
    5039           0 :   } 
    5040             :   //return didAnything;
    5041           0 :   return retval;
    5042           0 : }
    5043             : 
    5044           0 : String Imager::make_comp(const String& objName,
    5045             :                          const String& standard,
    5046             :                          const MEpoch& mtime, const Vector<MFrequency>& freqv,
    5047             :                          const String& prefix)
    5048             : {
    5049           0 :   Bool foundSrc = false;
    5050           0 :   logSink_p.clearLocally();
    5051           0 :   LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
    5052             : 
    5053           0 :   Vector<String> clistnames(1);
    5054             :   try{
    5055             :     FluxStandard::FluxScale fluxScaleEnum;
    5056           0 :     String fluxScaleName("user-specified");
    5057             : 
    5058           0 :     if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
    5059           0 :       throw(AipsError(standard + " is not a recognized flux density scale"));
    5060             : 
    5061           0 :     FluxStandard fluxStd(fluxScaleEnum);
    5062             : 
    5063           0 :     Vector<Vector<Flux<Double> > > returnFluxes(1), returnFluxErrs(1);
    5064           0 :     Vector<Vector<MFrequency> > mfreqs(1);
    5065           0 :     uInt nfreqs = freqv.nelements();
    5066             : 
    5067           0 :     mfreqs[0] = freqv;
    5068           0 :     returnFluxes[0].resize(nfreqs);
    5069           0 :     returnFluxErrs[0].resize(nfreqs);
    5070             : 
    5071           0 :     MDirection objDir;
    5072             :     
    5073           0 :     if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 || 
    5074           0 :         fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017) 
    5075             :     { 
    5076           0 :       fluxStd.setInterpMethod("nearest");
    5077             :     }
    5078           0 :     foundSrc = fluxStd.computeCL(objName, mfreqs, mtime, objDir,
    5079             :                                  returnFluxes, returnFluxErrs,
    5080             :                                  clistnames, prefix);
    5081           0 :   }
    5082           0 :   catch(AipsError x){
    5083           0 :     os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
    5084           0 :     RETHROW(x);
    5085           0 :   }  
    5086           0 :   return foundSrc ? clistnames[0] : "";
    5087           0 : }
    5088             : 
    5089           0 : Unit Imager::sjy_setup_arrs(Vector<Vector<Flux<Double> > >& returnFluxes,
    5090             :                             Vector<Vector<Flux<Double> > >& returnFluxErrs,
    5091             :                             Vector<Vector<Double> >& fluxUsed,
    5092             :                             Vector<String>& tempCLs,
    5093             :                             Vector<Vector<MFrequency> >& mfreqs,
    5094             :                             const MSSpWindowColumns& spwcols, const uInt nspws,
    5095             :                             const Vector<Int>& selToRawSpwIds, const Bool chanDep)
    5096             : {
    5097             :   // .getUnits() is a little confusing - it seems to return a Vector which is
    5098             :   // a list of all the units, not the unit for each row.
    5099             : 
    5100             :   
    5101           0 :   const Unit freqUnit(spwcols.chanFreqQuant().getUnits()[0]);
    5102             : 
    5103           0 :   IPosition ipos(1, 0);
    5104             : 
    5105           0 :   tempCLs.resize(nspws);
    5106           0 :   for(uInt selspw = 0; selspw < nspws; ++selspw){
    5107           0 :     Int rawspwid = selToRawSpwIds[selspw];
    5108             : 
    5109           0 :     if(chanDep){
    5110           0 :       mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid);
    5111           0 :       uInt nchan = mfreqs[selspw].nelements();
    5112           0 :       returnFluxes[selspw].resize(nchan);
    5113           0 :       returnFluxErrs[selspw].resize(nchan);
    5114             :     }
    5115             :     else{
    5116           0 :       mfreqs[selspw].resize(1);
    5117           0 :       returnFluxes[selspw].resize(1);
    5118           0 :       returnFluxErrs[selspw].resize(1);
    5119             : 
    5120             :       // Determine spectral window center frequency
    5121           0 :       Double medianFreq = median(spwcols.chanFreq()(rawspwid));
    5122           0 :       mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid)(ipos);
    5123           0 :       mfreqs[selspw].set(MVFrequency(Quantum<Double>(medianFreq, freqUnit)));
    5124             :     }
    5125             :     // initialize fluxUsed to 0 
    5126           0 :     Vector<Double> iquvF(4,0.0);
    5127           0 :     fluxUsed[selspw]=iquvF;
    5128           0 :   }
    5129             : 
    5130           0 :   return freqUnit;
    5131           0 : }
    5132             : // new signature should be...
    5133             : /***
    5134             : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
    5135             :                                    const Vector<Int>& rawspwids, const Int fldid,
    5136             :                                    const String& clname, const String& timerange,
    5137             :                                    const String& scanstr, const String& intentstr, const String& obsidstr,
    5138             :                                    const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
    5139             : ***/
    5140           0 : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
    5141             :                                    const Int rawspwid, const Int fldid,
    5142             :                                    const String& clname, const String& timerange,
    5143             :                                    const String& scanstr, const String& intentstr, const String& obsidstr,
    5144             :                                    const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
    5145             : {
    5146           0 :   Bool made_visibilities = false;
    5147             : 
    5148             :   // Select the uv-data for this field and spw. id.;
    5149             :   // all frequency channels selected.
    5150           0 :   Vector<Int> selectSpw(1), selectField(1);
    5151             :   // for the new 
    5152             :   //Vector<Int> selectSpw, selectField(1);
    5153             :   //selectSpw.resize(rawspwids.nelements());
    5154             :   //selectSpw = rawspwids;
    5155             :   //
    5156           0 :   selectSpw[0] = rawspwid;
    5157           0 :   selectField[0] = fldid;
    5158           0 :   String msSelectString = "";
    5159           0 :   Vector<Int> numDeChan(1);
    5160           0 :   numDeChan[0] = 0;
    5161           0 :   Vector<Int> begin(1);
    5162           0 :   begin[0] = 0;
    5163           0 :   Vector<Int> stepsize(1);
    5164           0 :   stepsize[0] = 1;
    5165             :   //TempImage<Float> tmodimage = tmodimages[0];
    5166           0 :   if(tmodimage || clname != "") {
    5167             :   //if(!tmodimages[0].null() || clname != "")
    5168           0 :     setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(), 
    5169           0 :             MRadialVelocity(),
    5170             :             selectSpw, selectField, msSelectString, timerange, "",
    5171           0 :             Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
    5172             :   }
    5173           0 :   if(!nullSelect_p){
    5174             :     // Use ft to form visibilities
    5175           0 :     Vector<String> modelv;
    5176             :  
    5177           0 :     if(tmodimage){
    5178             :     //if(!tmodimages[0].null()){
    5179             :       //for (uInt imod=0; imod<tmodimages.nelements();imod++) {
    5180             :       //if(!tmodimages[imod].null()) {
    5181           0 :       if(sm_p)
    5182           0 :         destroySkyEquation();
    5183             :       // do if for each spw?
    5184           0 :       if(freqsOfScale.nelements() > 0){
    5185             :       //if(freqsOfScales[imod].nelements() > 0){
    5186           0 :         delete ft_p;
    5187           0 :         ft_p=NULL;
    5188           0 :         ftmachine_p="SetJyGridFT";
    5189           0 :         createFTMachine();
    5190           0 :         (static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScale, freqscaling);
    5191             :         //(static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScales[imod], freqscalings[imod]);
    5192             :       }
    5193           0 :       if(!ft_p)
    5194           0 :         createFTMachine();
    5195           0 :       sm_p = new CleanImageSkyModel();
    5196             :       // loop over for multiple spw model images
    5197           0 :       sm_p->add(*tmodimage, 1);
    5198             :       //sm_p->add(*(tmodimages[imod]), 1);
    5199             :       //} //if-tmodimages..
    5200             :       //} //for loop
    5201             :       // this has no effect (SetJyGridFT hardcoded to use linear now, Aug. 2016)
    5202             :       //ft_p->setFreqInterpolation("nearest");
    5203           0 :       setSkyEquation();
    5204           0 :       se_p->predict(false);
    5205           0 :       destroySkyEquation();
    5206             : 
    5207           0 :       made_visibilities = true;
    5208             :     }
    5209           0 :     else if(clname != ""){
    5210             :       //made_visibilities = ft(modelv, clname, false);
    5211           0 :       made_visibilities = ft(modelv, clname, false);
    5212           0 :       destroySkyEquation();
    5213             :     }
    5214             :     else
    5215             :       os << LogIO::NORMAL
    5216             :          << "Skipping an empty component list for spw " << rawspwid
    5217             :      // for new one
    5218             :      //    << "Skipping an empty component list for spw " << rawspwids
    5219           0 :          << LogIO::POST;
    5220           0 :   }
    5221           0 :   return made_visibilities;
    5222           0 : }
    5223             : 
    5224             : 
    5225           0 : Bool Imager::sjy_concatComponentLists(LogIO& os, const Vector<String>& tempCLs, const String& outTempCL)
    5226             : {
    5227           0 :   ComponentList concatCL;
    5228             :   try {
    5229           0 :     for (uInt icl=0; icl<tempCLs.nelements(); icl++) {
    5230           0 :       if (tempCLs[icl]!="") {
    5231             :         // expected format _setjy_spw#_...
    5232           0 :         String::size_type spos=tempCLs[icl].find(String("spw"));
    5233           0 :         String::size_type epos=tempCLs[icl].find_first_of("_",spos);
    5234           0 :         String clab = tempCLs[icl].substr(spos,epos-spos);
    5235           0 :         Path clname(tempCLs[icl]);
    5236           0 :         os <<LogIO::DEBUG1 << " tempCLs["<<icl<<"]="<<tempCLs[icl]<<LogIO::POST;
    5237           0 :         ComponentList tempcl(clname, true);
    5238           0 :         Vector<Int> which(1,0);
    5239           0 :         tempcl.setLabel(which,clab);
    5240           0 :         os << LogIO::DEBUG1 << "adding "<<tempCLs[icl]<<" to "<<outTempCL<<LogIO::POST;
    5241           0 :         concatCL.addList(tempcl);
    5242           0 :       }
    5243             :     }  
    5244           0 :     concatCL.rename(outTempCL, Table::New);
    5245           0 :     return true;
    5246           0 :   } catch (AipsError x) {
    5247             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    5248           0 :        << LogIO::EXCEPTION;
    5249           0 :     return false;
    5250           0 :   }
    5251           0 : }
    5252             : 
    5253           0 : Bool Imager::sjy_computeFlux(LogIO& os, FluxStandard& fluxStd,
    5254             :                              Vector<Vector<Flux<Double> > >& returnFluxes,
    5255             :                              Vector<Vector<Flux<Double> > >& returnFluxErrs,
    5256             :                              Vector<String>& tempCLs, 
    5257             :                              //Vector<Double>& fluxUsed,
    5258             :                              Vector<Vector<Double> >& fluxUsed,
    5259             :                              String& fluxScaleName, MEpoch& aveEpoch,
    5260             :                              const Vector<Vector<MFrequency> >& mfreqs,
    5261             :                              const String& model, const String& fieldName, 
    5262             :                              const MSColumns& msc, const Int fldid, 
    5263             :                              const MDirection& fieldDir, const Vector<Int>& selToRawSpwIds,
    5264             :                              const String& standard)
    5265             : {
    5266           0 :   Bool foundSrc = false;
    5267             :    
    5268           0 :   Double meantime = msc.time()(0);
    5269           0 :   meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    5270           0 :   MEpoch mtime(msc.timeMeas()(0));
    5271           0 :   mtime.set(Quantity(meantime, "s"));
    5272           0 :   if(model != ""){
    5273             :     // Just get the fluxes and their uncertainties for scaling the image.
    5274             :     //foundSrc = fluxStd.compute(fieldName, mfreqs, returnFluxes,
    5275             :      //                          returnFluxErrs);
    5276           0 :     foundSrc = fluxStd.compute(fieldName, fieldDir, mfreqs, mtime, returnFluxes,
    5277             :                               returnFluxErrs);
    5278             :   }
    5279             :   else{
    5280             :     // Go ahead and get FluxStandard to make the ComponentList, since
    5281             :     // it knows what type of component to use. 
    5282             : 
    5283             :     // This is _a_ time.  It would be more accurate and safer, but
    5284             :     // slower, to use the weighted average of the times at which this
    5285             :     // source was observed, and to use the range of times in the
    5286             :     // estimate of the error introduced by using a single time.
    5287             :     //
    5288             :     // Obviously that would be overkill if the source does not vary.
    5289             :     //
    5290             :     /***
    5291             :     Double meantime = msc.time()(0);
    5292             :     meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
    5293             :     MEpoch mtime(msc.timeMeas()(0));
    5294             :     mtime.set(Quantity(meantime, "s"));
    5295             :     ***/
    5296             :             
    5297           0 :     aveEpoch=mtime;
    5298             : 
    5299           0 :     foundSrc = fluxStd.computeCL(fieldName, mfreqs, mtime, fieldDir,
    5300             :                                  returnFluxes, returnFluxErrs,
    5301           0 :                                  tempCLs, ms_p->tableName()+"_setjy_");
    5302             :   }
    5303           0 :   if(!foundSrc){
    5304           0 :     if(standard == String("SOURCE")){
    5305             :       // *** THIS MODE IS NOT USED IN CURRENT SETJY ***
    5306             :       // dgoscha, NCSA, 02 May, 2002
    5307             :       // this else condtion is to handle the case where the user
    5308             :       // specifies standard='SOURCE' in the setjy argument.  This will
    5309             :       // then look into the SOURCE_MODEL column of the SOURCE subtable
    5310             :       // for a table-record entry that points to a component list with the
    5311             :       // model information in it.
    5312             : 
    5313             :       // Look in the SOURCE_MODEL column of the SOURCE subtable for 
    5314             :       // the name of the CL which contains the model.
    5315             : 
    5316             :       // First test to make sure the SOURCE_MODEL column exists.
    5317           0 :       if(ms_p->source().tableDesc().isColumn("SOURCE_MODEL")){
    5318           0 :         TableRecord modelRecord;
    5319           0 :         msc.source().sourceModel().get(0, modelRecord);
    5320             :         
    5321             :         // Get the name of the model component list from the table record
    5322             :         Table modelRecordTable = 
    5323           0 :           modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
    5324           0 :         String modelCLName = modelRecordTable.tableName();
    5325           0 :         modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
    5326             : 
    5327             :         // Now grab the flux from the model component list and use.
    5328           0 :         ComponentList modelCL = ComponentList(Path(modelCLName), true);
    5329           0 :         SkyComponent fluxComponent = modelCL.component(fldid);
    5330             : 
    5331             :         //fluxUsed = 0;
    5332           0 :         fluxUsed(0) = 0;
    5333             :         //fluxUsed = real(fluxComponent.flux().value());
    5334           0 :         fluxUsed(0) = real(fluxComponent.flux().value());
    5335           0 :         fluxScaleName = modelCLName;
    5336           0 :       }
    5337             :       else {
    5338             :         os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
    5339             :            << LogIO::SEVERE << "Continuing with the default, I = 1.0 Jy"
    5340           0 :            << LogIO::POST;
    5341             :         //fluxUsed = 0;
    5342           0 :         fluxUsed(0) = 0;
    5343             :         //fluxUsed(0) = 1.0;
    5344           0 :         fluxUsed(0)(0) = 1.0;
    5345             :       }
    5346             :     }
    5347             :     else {
    5348             :       // Source not found; use Stokes I=1.0 Jy for now
    5349             :       // (The flux standard already issued a complaint like this...)
    5350             :       // os << LogIO::WARN
    5351             :       //    << fieldName << " was not recognized by " << standard
    5352             :       //    << ".\nContinuing with the default, I = 1.0 Jy"
    5353             :       //    << LogIO::POST;
    5354             :       //fluxUsed = 0;
    5355           0 :       fluxUsed(0) = 0;
    5356             :       //fluxUsed(0) = 1.0;
    5357           0 :       fluxUsed(0)(0) = 1.0;
    5358           0 :       fluxScaleName = "default";
    5359             :     }
    5360             : 
    5361             :     // Currently, if !foundSrc, then the flux density is the same for all
    5362             :     // spws.
    5363             :     // Log the flux density found for this field.
    5364           0 :     os.output().width(12);
    5365           0 :     os << fieldName << "  ";
    5366           0 :     os.output().width(0);
    5367           0 :     os.output().precision(4);
    5368             :     /***
    5369             :     os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
    5370             :     os << "Q=" << fluxUsed(1) << ", ";
    5371             :     os << "U=" << fluxUsed(2) << ", ";
    5372             :     os << "V=" << fluxUsed(3) << "] Jy, ";
    5373             :     ***/
    5374           0 :     os << LogIO::NORMAL << "[I=" << fluxUsed(0)(0) << ", "; // Loglevel INFO
    5375           0 :     os << "Q=" << fluxUsed(0)(1) << ", ";
    5376           0 :     os << "U=" << fluxUsed(0)(2) << ", ";
    5377           0 :     os << "V=" << fluxUsed(0)(3) << "] Jy @ ";
    5378           0 :     os << mfreqs(0)(0).getValue()<<"Hz, ";
    5379           0 :     os << ("(" + fluxScaleName + ")") << LogIO::POST;
    5380           0 :     writeHistory(os);
    5381             :   }  // End of if(!foundSrc).
    5382             :   else {
    5383             :     // Logging/History for foundSrc=true (moved from the im.setjy method)
    5384           0 :     for (uInt selspw=0; selspw<selToRawSpwIds.nelements(); selspw++) {
    5385           0 :       returnFluxes[selspw][0].value(fluxUsed[selspw]);
    5386             :       // Log flux density found for this field and spectral window
    5387           0 :       os.output().width(12);
    5388           0 :       os << fieldName;
    5389           0 :       os.output().width(2);
    5390           0 :       os << " (fld ind " << fldid << ") spw ";
    5391           0 :       os << selToRawSpwIds[selspw] << "  ";
    5392           0 :       os.output().width(0);
    5393           0 :       os.output().precision(5);
    5394           0 :       os << LogIO::NORMAL << "[I=" << fluxUsed(selspw)(0) << ", "; // Loglevel INFO
    5395           0 :       os << "Q=" << fluxUsed(selspw)(1) << ", ";
    5396           0 :       os << "U=" << fluxUsed(selspw)(2) << ", ";
    5397           0 :       os << "V=" << fluxUsed(selspw)(3) << "] Jy @ ";
    5398           0 :       os << mfreqs(selspw)(0).getValue()<<"Hz, ";
    5399           0 :       os << ("(" + fluxScaleName + ")") << LogIO::POST;
    5400           0 :       writeHistory(os);
    5401             :     } 
    5402             :   }
    5403           0 :   return foundSrc;
    5404           0 : }
    5405             : 
    5406             : //make componentlist(s) with user specified flux density
    5407           0 : void Imager::sjy_makeComponentList(LogIO& os, Vector<String>& tempCLs,
    5408             :                               Vector<Vector<Flux<Double> > >& returnFluxes,
    5409             :                               const Vector<Double>& fluxUsed, 
    5410             :                               const Vector<Int>& selToRawSpwIds, 
    5411             :                               const Vector<Vector<MFrequency> >& mfreqs,
    5412             :                               const String& fieldName,
    5413             :                               const MDirection& fieldDir, 
    5414             :                               const Vector<Double>& spix,
    5415             :                               const Vector<Double>& pipars,
    5416             :                               const Vector<Double>& papars,
    5417             :                               const Double& rotMeas,
    5418             :                               // circ pol parameters
    5419             :                               //const Vector<Double>& cppars,
    5420             :                               const MFrequency& reffreq,
    5421             :                               const MEpoch& mtime,
    5422             :                               const Int /*fldid*/)
    5423             : {
    5424             : 
    5425           0 :   for(uInt selspw = 0; selspw < selToRawSpwIds.nelements(); ++selspw){
    5426             :     // fluxUsed was supplied by the user instead of FluxStandard, so
    5427             :     // make a component list for it now, for use in ft.
    5428             : 
    5429             :     // if spix is a float/double and q,u fluxes not set or pipars and papars not
    5430             :     // set => SpectralIndex 
    5431             :     // if spix is a float/double and q,u fluxes is set but not pipars and papers
    5432             :     // => spectralindex
    5433             :     // if spix is a float/double and q,u fluxes and pipars and papars are set
    5434             :     // => tabular
    5435             :     // if spix is a vector but qu fluxes nor pipars and papers are not set 
    5436             :     // => tabular
    5437             :     // if spix is a vector => tabular form
    5438             :     //
    5439             :     // Set the component flux density
    5440           0 :     Flux<Double> fluxval;
    5441           0 :     Flux<Double> fluxerr;
    5442           0 :     fluxval.setValue(fluxUsed);
    5443             :     // Create a point component at the field center
    5444             :     // with the specified flux density
    5445             :     // - obviously this does not correct for solar objects...
    5446           0 :     PointShape point(fieldDir);
    5447             : 
    5448           0 :     Bool useTabularFlux(false);
    5449             :     //check if to use tabular form or SpectralIndex model
    5450           0 :     if ( spix.nelements() > 1 ) {
    5451           0 :       useTabularFlux=true; 
    5452             :     }
    5453             :     else {
    5454             :       //if (pipars.nelements() > 1 || papars.nelements() > 1 || rotMeas != 0.0) {
    5455           0 :       if (pipars.nelements() > 1 || papars.nelements() > 1 ) {
    5456           0 :         useTabularFlux=true;
    5457             :       }
    5458             :     }
    5459           0 :     SpectralIndex siModel;
    5460             :     //Vector<Double> iflux;
    5461             :     //Vector<Double> qflux;
    5462             :     //Vector<Double> uflux;
    5463           0 :     Vector<Flux<Double> > fluxvalvec; 
    5464           0 :     Bool gotQUFlux(false);
    5465           0 :     Bool useFluxAsIs(false);
    5466             :     // 
    5467           0 :     if(reffreq.getValue().getValue() > 0.0){
    5468             :       //original code uses first time of the data but shouldn't be using the same time as for
    5469             :       //FluxStandard::makeComponentList?
    5470             :       //MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
    5471           0 :       MeasFrame mFrame(mtime, mLocation_p, fieldDir);
    5472           0 :       MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
    5473           0 :       siModel.setRefFrequency(reffreq);
    5474             :       // if spix is not array of double,do this otherwise need to set flux densities by tabular... 
    5475             :       //
    5476           0 :       Int nchn = mfreqs[selspw].nelements(); 
    5477           0 :       fluxvalvec.resize(nchn);
    5478           0 :       Vector<Double> iflux(nchn);
    5479           0 :       Vector<Double> qflux(nchn);
    5480           0 :       Vector<Double> uflux(nchn);
    5481           0 :       Vector<Double> vflux(nchn,0.0);
    5482             :       // circular polarization fraction
    5483           0 :       Double circpolFraction=0.0;
    5484           0 :       if ( fluxUsed[0] !=0.0 && fluxUsed[3] != 0.0 ) {
    5485           0 :         circpolFraction = fluxUsed[3]/fluxUsed[0]; 
    5486             :       }
    5487             : 
    5488           0 :       if (spix.nelements()==1) {
    5489             :         //siModel.setIndex(spix[0]);
    5490           0 :         Vector<Double> stokesindex(4);
    5491           0 :         stokesindex[0]=spix[0];
    5492           0 :         stokesindex[1]=0.0;
    5493           0 :         stokesindex[2]=rotMeas!=0.0? rotMeas: 0.0;
    5494           0 :         stokesindex[3]=0.0;
    5495           0 :         siModel.setStokesIndex(stokesindex);
    5496             :         // still use iflux if q,u flux=0 but polindex and polangle is set
    5497           0 :         for (uInt ichn = 0; ichn < uInt(nchn); ichn++) { 
    5498           0 :           iflux[ichn] = fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][ichn]));
    5499             :         }
    5500           0 :       }
    5501             :       else {
    5502             :       // tabular case   
    5503           0 :         sjy_calciflux(mfreqs[selspw],reffreq,fluxUsed[0],spix,iflux);
    5504             :       }
    5505             :       // linear pol
    5506           0 :       Vector<Double> inpipars;
    5507           0 :       Vector<Double> inpapars;
    5508           0 :       if ( pipars.nelements() > 0 || papars.nelements() > 0 ) {
    5509           0 :         inpipars.resize(pipars.nelements());
    5510           0 :         inpipars=pipars;
    5511           0 :         inpapars.resize(papars.nelements());
    5512           0 :         inpapars=papars;
    5513             :       }
    5514             : 
    5515             :       // Either Q or U non-zero, so use them
    5516           0 :       if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0) {
    5517             :         // if Q U flux densities are given use that as 0th coefficient
    5518           0 :         Double pi0 = sqrt(fluxUsed[1] * fluxUsed[1] + fluxUsed[2] * fluxUsed[2]) / fluxUsed[0];
    5519           0 :         Double pa0 = 0.5 * atan2(fluxUsed[2],fluxUsed[1]);
    5520             :         os<<LogIO::DEBUG1<<"Polindex c0="<<pi0<<", polangle c0="<<pa0
    5521           0 :           <<" determined from input flux densities are used"<<LogIO::POST;
    5522           0 :         if ( pipars.nelements() == 0 || papars.nelements() == 0 ) {
    5523           0 :           inpipars.resize(1);
    5524           0 :           inpapars.resize(1);
    5525             :         }
    5526           0 :         inpipars[0] = pi0;
    5527           0 :         inpapars[0] = pa0;
    5528             :       }
    5529             :       //if (useTabularFlux) { 
    5530           0 :       if (inpipars.nelements()!=0 && inpapars.nelements()!=0) { 
    5531             :       //  cerr<<"running sjy_calcquflux...."<<endl;
    5532             :       //     - returns qflux and uflux
    5533           0 :         gotQUFlux = sjy_calcquflux(inpipars, inpapars, iflux, rotMeas, mfreqs[selspw], reffreq, qflux, uflux);
    5534             :       }
    5535           0 :       else if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0 || fluxUsed[3] != 0.0) {
    5536           0 :         gotQUFlux=true;
    5537           0 :         useFluxAsIs=true;
    5538             :       }
    5539             :         /***
    5540             :         if ( !useTabularFlux ) {
    5541             :           Vector<Double> stokesIndex(4);
    5542             :           stokesIndex[0] = index[0];
    5543             :           //need to translate polindex ...etc to stokesIndex[1,2] 
    5544             :           siModel.setStokesIndex(spix);
    5545             :         }
    5546             :         ***/ 
    5547           0 :       for (uInt ichn=0; ichn < iflux.nelements(); ichn++) {
    5548           0 :         if (!gotQUFlux) {
    5549           0 :           qflux[ichn] = 0.0; 
    5550           0 :           uflux[ichn] = 0.0;
    5551             :         } 
    5552           0 :         else if(useFluxAsIs) {
    5553           0 :           qflux[ichn] = fluxUsed[1];
    5554           0 :           uflux[ichn] = fluxUsed[2];
    5555           0 :           vflux[ichn] = fluxUsed[3];
    5556             :         }
    5557           0 :         if ( circpolFraction != 0.0) vflux[ichn] = iflux[ichn]*circpolFraction;
    5558           0 :         Flux<Double> iquvflux(iflux[ichn],qflux[ichn],uflux[ichn],vflux[ichn]);
    5559           0 :         fluxvalvec[ichn] = iquvflux; 
    5560           0 :       }
    5561           0 :       returnFluxes[selspw][0]=fluxvalvec[0];
    5562           0 :     }
    5563             :     else{
    5564           0 :       if(spix[0] != 0.0){            // If not the default, complain and quit.
    5565             :         os << LogIO::SEVERE
    5566             :            << "spix cannot be nonzero with reffreq = 0!"
    5567           0 :            << LogIO::POST;
    5568             :            //return false;
    5569             :       }
    5570           0 :       siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
    5571           0 :       siModel.setIndex(0.0);
    5572             :     }
    5573             :     // TODO: call tabular form method for full pol specification....
    5574             :     //
    5575             :     // No worries about varying fluxes or sizes here, so any time will do.
    5576           0 :     if ( useTabularFlux ) {
    5577           0 :       tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    5578             :                                                      mfreqs[selspw],
    5579             :                                                      mtime, fluxvalvec, point,
    5580           0 :                                                      ms_p->tableName() +
    5581           0 :                                                      "_setjy_spw" +
    5582           0 :                                                      String::toString(selspw) +
    5583           0 :                                                      "_");
    5584             :     }
    5585             :     else {
    5586             :     //if simodel is set use this 
    5587             :       //cerr<<"NON-Tabular makeComponentList..."<<endl;
    5588             :       //if (fluxval.value(1) ==0.0 && fluxval.value(2) == 0.0 && gotQUFlux) {
    5589             : 
    5590             :       // fluxval is @ thefreq, make sure proper freq is used 
    5591             :       // Note that refreq in siModel will be overriden by thefreq 
    5592           0 :       MFrequency thefreq = reffreq;
    5593           0 :       if ( gotQUFlux) {
    5594           0 :         fluxval=fluxvalvec[0]; 
    5595           0 :         thefreq=mfreqs[selspw][0];
    5596             :       }   
    5597           0 :       tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
    5598             :                                  //                    mfreqs[selspw][0],
    5599             :                                                      thefreq,
    5600             :                                                      mtime, fluxval, point,
    5601             :                                                      siModel,
    5602             :     // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
    5603           0 :                                                      ms_p->tableName() +
    5604           0 :                                                      "_setjy_spw" +
    5605           0 :                                                      String::toString(selspw) +
    5606           0 :                                                      "_");
    5607           0 :     }
    5608           0 :   }
    5609           0 : }
    5610             : 
    5611             : // modified the input model image by regridding, scaling with a flux standard
    5612           0 : TempImage<Float>* Imager::sjy_prepImage(LogIO& os, FluxStandard& fluxStd,
    5613             :                                         Vector<Double>& fluxUsed, Vector<Double>& freqsOfScale, 
    5614             :                                         Vector<Double>& freqscale, const String& model,
    5615             :                                         const MSSpWindowColumns& spwcols,
    5616             :                                         //const Int rawspwid, const Bool chanDep,
    5617             :                                         const Vector<Int> rawspwids, const Bool chanDep,
    5618             :                                         const Vector<Vector<MFrequency> >& mfreqs,
    5619             :                                         //const uInt selspw, const String& fieldName,
    5620             :                                         const String& fieldName,
    5621             :                                         const MDirection& fieldDir,
    5622             :                                         const Unit& freqUnit,
    5623             :                                         const Vector<Double>& fluxdens,
    5624             :                                         const Bool precompute, 
    5625             :                                         //const Double spix,
    5626             :                                         const Vector<Double>& spix,
    5627             :                                         const MFrequency& reffreq,
    5628             :                                         const MEpoch& aveEpoch,
    5629             :                                         const Int fieldId)
    5630             : {
    5631           0 :   TempImage<Float>* tmodimage = NULL;
    5632             :   
    5633             :   Double freqMax, freqMin;
    5634           0 :   Vector<Vector<Int> >dummy;
    5635             :   // TT for MMS this may not work
    5636             :   //String msname=mssel_p->antenna().tableName();
    5637             :   //msname.erase(msname.length()-8);
    5638           0 :   String msname=ms_p->tableName();
    5639             :   //adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, String::toString(rawspwid));
    5640             :   // Get freqmin and freqmax in LSRK for the entire span of the selected spws
    5641           0 :   String selSpwsStr;
    5642           0 :   for (uInt ispw=0; ispw < rawspwids.nelements(); ispw++) {
    5643           0 :     if (selSpwsStr!="") selSpwsStr += ", ";
    5644           0 :     selSpwsStr += String::toString(rawspwids(ispw));
    5645             :   }
    5646           0 :   adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, selSpwsStr);
    5647             : 
    5648             :   // Find min channel width to increment to construct freqsofScale 
    5649           0 :   Double freqWidth = 0;
    5650             :   //
    5651           0 :   for (uInt ispw = 0; ispw<rawspwids.nelements(); ispw++) {
    5652           0 :     Vector<Double> freqWidths = spwcols.chanWidth()(rawspwids(ispw));
    5653             : 
    5654           0 :     Double minChanWidth = min(fabs(freqWidths));
    5655             :     // freqWidth init....
    5656           0 :     if (freqWidth == 0) 
    5657           0 :       freqWidth = minChanWidth;
    5658             :     else 
    5659           0 :       freqWidth = min(freqWidth,minChanWidth); 
    5660           0 :   }
    5661             :   
    5662             :   // ADDED for debug
    5663             :   //Int rawspwid = rawspwids[0];
    5664             :   //Vector<Double> freqArray = spwcols.chanFreq()(rawspwid);
    5665             :   //Int nchan=freqArray.shape()[0]   ;
    5666           0 :   Int nchan = Int(ceil(fabs(freqMax - freqMin)/freqWidth))+1;
    5667             :   //cerr<<"nchan="<<nchan<<" freqMax="<<freqMax<<" freqMin="<<freqMin<<" freqWidth="<<freqWidth<<endl; 
    5668             :   //Filling it with the LSRK values
    5669             :   // SetJyGridFT will trigger nearestNeighbour interpolation for nchan>=2
    5670           0 :   Vector<Double> freqArray(nchan);
    5671           0 :   if (nchan==1) {
    5672           0 :     freqArray[0] = freqMin;
    5673             :   }
    5674           0 :   else if (nchan==2) {
    5675           0 :     freqArray[0] = freqMin;
    5676           0 :     freqArray[1] = freqMax;
    5677             :   }
    5678           0 :   else if (nchan==3) {
    5679           0 :     freqArray[0] = freqMin - freqWidth;
    5680           0 :     freqArray[1] = freqMin;
    5681           0 :     freqArray[2] = freqMin + freqWidth;
    5682             :   }
    5683             :   else {
    5684           0 :     for (Int k =0;k < nchan; ++k){
    5685           0 :       freqArray[k]=freqMin+k*freqWidth;
    5686             :     }
    5687             :   }
    5688             :   //Vector<Double> freqInc = spwcols.chanWidth()(rawspwid);
    5689           0 :   Double medianFreq = median(freqArray);
    5690           0 :   freqsOfScale.resize();
    5691           0 :   freqscale.resize();
    5692             : 
    5693             :   // 2 bw channel extra
    5694             :   // UNCOMMENTED for debug
    5695             :   //freqWidth = fabs(freqMax - freqMin) + 2 * max(freqInc);
    5696           0 :   Matrix<Double> fluxUsedPerChan; // 4 rows nchan col ...will resize when needed
    5697             : 
    5698             :   // Set fluxUsedPerChan to the flux densities for each chan.
    5699           0 :   if(chanDep || (spix[0] != 0.0 && fluxdens[0] != 0.0)){
    5700           0 :     IPosition whichChan(1, 0);
    5701           0 :     Flux<Double> returnFlux;
    5702           0 :     Flux<Double> returnFluxErr;
    5703           0 :     Double reffreqInGHz = 1.0;
    5704             : 
    5705           0 :     Unit ghz("GHz");
    5706           0 :     if(!precompute)
    5707           0 :       reffreqInGHz = reffreq.get(ghz).getValue();
    5708             : 
    5709           0 :     fluxUsedPerChan.resize(4, freqArray.nelements());
    5710           0 :     for(uInt k = 0; k < freqArray.nelements(); ++k){
    5711           0 :       whichChan[0] = k;
    5712           0 :       if(precompute){
    5713             :         //fluxStd.compute(fieldName, spwcols.chanFreqMeas()(rawspwid)(whichChan),
    5714             :         //                returnFlux, returnFluxErr);
    5715           0 :         fluxStd.compute(fieldName, fieldDir, MFrequency(Quantity(freqArray[k], "Hz"), MFrequency::LSRK),
    5716             :                         aveEpoch, returnFlux, returnFluxErr);
    5717           0 :         returnFlux.value(fluxUsed);
    5718             :       }
    5719             :       else{
    5720             :         // spix: index = c0 + c1*log(f/fo) + c2*log(f/fo)^2+ ... 
    5721             :         //             = log(So) + alpha*log(f/fo) + curv1*log(f/f0)^2 ....
    5722           0 :         uInt order = spix.nelements();
    5723           0 :         Polynomial<Double> spixfunc(order);
    5724           0 :         Vector<Double> coeffs(order+1);
    5725           0 :         coeffs[0] = log10(fluxdens[0]); 
    5726           0 :         for (uInt ispix = 1; ispix < order+1; ispix++) {
    5727           0 :           coeffs[ispix] = spix[ispix-1];
    5728             :         }
    5729           0 :         spixfunc.setCoefficients(coeffs);
    5730             : 
    5731             :         //Double freq = spwcols.chanFreqMeas()(rawspwids(0))(whichChan).get(ghz).getValue();
    5732             :         //Double specfac = pow(freq / reffreqInGHz, spix);
    5733             :         // TT mod-06/11/14
    5734             :         // freqArray may or may not be exactly match with data chan frequencies
    5735             :         // so probably make sense to use  freqArray instead 
    5736             :         //Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spix);
    5737           0 :         Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spixfunc(freqArray[k]));
    5738             :         
    5739           0 :         for(uInt stokes = 0; stokes < 4; ++stokes)
    5740           0 :           fluxUsed[stokes] = fluxdens[stokes] * specfac;
    5741           0 :       }
    5742           0 :       fluxUsedPerChan.column(k) = fluxUsed;
    5743             :     }
    5744           0 :   }
    5745           0 :   PagedImage<Float> modimage(model);
    5746           0 :   modimage.table().unmarkForDelete();
    5747           0 :   IPosition imshape = modimage.shape();
    5748           0 :   CoordinateSystem csys(modimage.coordinates());
    5749           0 :   Int freqAxis = CoordinateUtil::findSpectralAxis(csys);
    5750           0 :   Vector<Stokes::StokesTypes> whichPols;
    5751           0 :   Int polAxis = CoordinateUtil::findStokesAxis(whichPols, csys);
    5752           0 :   Int icoord = csys.findCoordinate(Coordinate::SPECTRAL);
    5753           0 :   SpectralCoordinate spcsys = csys.spectralCoordinate(icoord);
    5754           0 :   MEpoch elEpoch; MDirection elDir; MFrequency::Types elTypes; MPosition elPos;
    5755           0 :   spcsys.getReferenceConversion(elTypes, elEpoch, elPos, elDir);
    5756           0 :   spcsys.setReferenceConversion(MFrequency::LSRK, aveEpoch, elPos, elDir);  
    5757           0 :   spcsys.setReferenceValue(Vector<Double>(1, medianFreq));
    5758           0 :   spcsys.setReferencePixel(Vector<Double>(1, 0.0));
    5759           0 :   spcsys.setWorldAxisUnits(Vector<String>(1,
    5760             :                                           //mfreqs[selspw][0].getUnit().getName()));
    5761           0 :                                           mfreqs[0][0].getUnit().getName()));
    5762             :   //make image freq. width wide enough for FTMachine to work correctly 
    5763           0 :   spcsys.setIncrement(Vector<Double>(1, 2*fabs(freqMax-freqMin)));
    5764             :   // make a cube model if the model is a cube already
    5765           0 :   if(modimage.shape()(freqAxis) >1){
    5766             :     // model image is a cube...just regrid it then
    5767             :     os << LogIO::NORMAL
    5768             :        << "The model image is a cube, so it is being regridded but without scaling the flux density."
    5769           0 :        << LogIO::POST;
    5770           0 :     spcsys = SpectralCoordinate(
    5771             :                                 //MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
    5772           0 :                                 MFrequency::castType(mfreqs[0][0].getRef().getType()),
    5773           0 :                                 freqArray, spcsys.restFrequency());
    5774           0 :     imshape(freqAxis)=freqArray.nelements();
    5775           0 :     csys.replaceCoordinate(spcsys, icoord);
    5776           0 :     tmodimage = new TempImage<Float>(imshape, csys);
    5777           0 :     sjy_regridCubeChans(tmodimage, modimage, freqAxis);
    5778             :     //return from here itself
    5779           0 :     return tmodimage;
    5780             :   }
    5781             :  
    5782           0 :   if(chanDep && (fluxUsedPerChan.ncolumn() > 1)){
    5783             :     //spcsys = SpectralCoordinate(
    5784             :     //                  MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
    5785             :     //                            freqArray, spcsys.restFrequency());
    5786           0 :     if(freqAxis < 2 || polAxis < 2)
    5787           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"));
    5788           0 :     freqscale.resize(freqArray.nelements());
    5789           0 :     freqsOfScale.resize(freqArray.nelements());
    5790           0 :     freqsOfScale=freqArray;
    5791           0 :     freqscale=1.0;
    5792           0 :     if(freqAxis == 2) {//pol and freq are swapped
    5793           0 :       imshape[2]=imshape[3];
    5794           0 :       imshape[3] = 1;      
    5795           0 :       Vector<Int> trans(4);
    5796           0 :       trans[0] = 0; trans[1] = 1; trans[2] = 3; trans[3] = 2;
    5797           0 :       csys.transpose(trans, trans);
    5798           0 :     }
    5799             :     else{
    5800           0 :       imshape(freqAxis) = 1;
    5801             :     }
    5802             :   } 
    5803           0 :   csys.replaceCoordinate(spcsys, icoord);
    5804           0 :   tmodimage = new TempImage<Float>(imshape, csys);
    5805           0 :   IPosition blcin(modimage.shape().nelements(), 0);
    5806           0 :   IPosition trcin=modimage.shape()-1;
    5807           0 :   IPosition blcout(imshape.nelements(), 0); 
    5808           0 :   IPosition trcout=imshape-1;
    5809             :   
    5810           0 :   for (uInt ipol=0; ipol < imshape[2]; ++ipol){
    5811           0 :     blcin[polAxis]=ipol;
    5812           0 :     trcin[polAxis]=ipol;
    5813           0 :     blcout[2]=ipol;
    5814           0 :     trcout[2]=ipol;
    5815           0 :     Slicer slin(blcin, trcin, Slicer::endIsLast);
    5816           0 :     Slicer slout(blcout, trcout, Slicer::endIsLast);
    5817           0 :     SubImage<Float> subimout(*tmodimage, slout, true);
    5818           0 :     SubImage<Float> subimin(modimage, slin, false);
    5819           0 :     subimout.copyData(subimin);
    5820           0 :   }
    5821             :   os << LogIO::DEBUG1
    5822             :      << "freqUnit.getName() = " << freqUnit.getName()
    5823           0 :      << LogIO::POST;
    5824             :   os << LogIO::DEBUG1
    5825             :      //<< "mfreqs[selspw].get(freqUnit).getValue() = "
    5826             :      //<< mfreqs[selspw][0].get(freqUnit).getValue()
    5827             :      << "mfreqs[0][0].get(freqUnit).getValue() = "
    5828           0 :      << mfreqs[0][0].get(freqUnit).getValue()
    5829           0 :      << LogIO::POST;
    5830             : 
    5831             :   // Check direction consistency (reported in log message below)
    5832           0 :   String err;
    5833           0 :   if(!CoordinateUtil::setDirectionConversion(err, csys, fieldDir.getRefString())){
    5834             :     os << "LogIO::WARN " 
    5835             :        << "Could not set direction conversion between flux image and " 
    5836           0 :        << fieldDir.getRefString() << LogIO::POST;
    5837             :   }
    5838           0 :   Int dircoord(csys.findCoordinate(Coordinate::DIRECTION));
    5839           0 :   DirectionCoordinate dircsys=csys.directionCoordinate(dircoord);
    5840           0 :   MVDirection mvd;
    5841           0 :   dircsys.toWorld(mvd,dircsys.referencePixel());
    5842           0 :   Double sep = fieldDir.getValue().separation(mvd,"\"").getValue();
    5843             :           
    5844             :   //Apply radius limit for 3C286,3C48,3C147 and 3C138
    5845           0 :   sjy_setRadiusLimit(tmodimage, modimage, model, dircsys);
    5846             : 
    5847             :   // for debugging
    5848             :   //PagedImage<Float> checkIm(TiledShape(modimage.shape(),
    5849             :   //                                        modimage.niceCursorShape()),
    5850             :   //                                  modimage.coordinates(),
    5851             :   //                                  "checkImage");
    5852             :   //checkIm.copyData((LatticeExpr<Float>)(*tmodimage));
    5853             : 
    5854           0 :   if(fluxdens[0] != 0.0){
    5855           0 :     Float sumI = 1.0;
    5856             : 
    5857             :     // ?: can't handle the different return types.
    5858           0 :     if(whichPols.nelements() > 1)
    5859             :       //sumI = sum(ImagePolarimetry(modimage).stokesI()).getFloat();
    5860           0 :       sumI = sum(ImagePolarimetry(*tmodimage).stokesI()).getFloat();
    5861             :     else
    5862             :       //sumI = sum(modimage).getFloat();
    5863           0 :       sumI = sum(*tmodimage).getFloat();
    5864             : 
    5865             :     //if(selspw == 0)
    5866             :       os << LogIO::NORMAL
    5867           0 :          << "Using model image " << modimage.name() // Loglevel INFO
    5868           0 :          << LogIO::POST;
    5869             : 
    5870             :     // scale the image
    5871           0 :     if(freqscale.nelements() > 0){
    5872           0 :       Int midchan = freqArray.nelements()/2;
    5873           0 :       if(modimage.shape()(freqAxis) == 1){
    5874             :         //     IPosition blc(imshape.nelements(), 0);
    5875             :         //IPosition trc = imshape - 1;
    5876             :         os << LogIO::NORMAL
    5877             :            //<< "Scaling spw " << selspw << "'s model image by channel to I = " 
    5878           0 :            << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image by channel to  I = " 
    5879           0 :            << fluxUsedPerChan.row(0)(0)<<", "
    5880           0 :            << fluxUsedPerChan.row(0)(midchan)<<", "
    5881           0 :            << fluxUsedPerChan.row(0)(nchan-1)
    5882             :            << " Jy @("
    5883           0 :            << freqArray(0)<<", "
    5884           0 :            << freqArray(midchan)<<", "
    5885           0 :            << freqArray(nchan-1)
    5886             :            <<")Hz (LSRK) for visibility prediction (a few representative values are shown)."
    5887           0 :            << LogIO::POST;
    5888           0 :         writeHistory(os);
    5889           0 :         for(uInt k = 0; k < fluxUsedPerChan.ncolumn(); ++k){
    5890           0 :           freqscale[k] = fluxUsedPerChan.column(k)(0)/sumI;
    5891             :           //blc[3] = k;
    5892             :           //trc[3] = k;
    5893             :           //Slicer sl(blc, trc, Slicer::endIsLast);
    5894             :           //SubImage<Float> subim(*tmodimage, sl, true);
    5895             :           //subim.copyData((LatticeExpr<Float>)(modimage*scale));
    5896             :         }
    5897             :         // for debug
    5898             :         //cerr<<"freqscale="<<freqscale<<endl;
    5899             :         //cerr<<"freqsOfScale="<<freqsOfScale<<endl;
    5900             :       }
    5901             :     }
    5902             :     else{
    5903             :       // Scale factor
    5904           0 :       Float scale = fluxUsed[0] / sumI;
    5905             :       //for addition of sjy_setRadiusLimit
    5906             :       //tmodimage->copyData( (LatticeExpr<Float>)(modimage * scale) ); 
    5907           0 :       tmodimage->copyData( (LatticeExpr<Float>)(*tmodimage * scale) ); 
    5908             :       os << LogIO::NORMAL
    5909             :      //    << "Scaling spw " << selspw << "'s model image to I = "
    5910           0 :          << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image to I = "
    5911           0 :          << fluxUsed[0] // Loglevel INFO
    5912             :          << " Jy @ "
    5913             :          //<< mfreqs[0][0].getValue()
    5914           0 :          << freqArray(0) 
    5915             :          << "Hz (LSRK) for visibility prediction."
    5916           0 :          << LogIO::POST;
    5917           0 :       writeHistory(os);
    5918             :     }
    5919             :   }
    5920             :   else{
    5921             :     os << LogIO::NORMAL                                  // Loglevel INFO
    5922             :  << "Using the model image's original unscaled flux density for visibility prediction."
    5923           0 :        << LogIO::POST;
    5924           0 :     writeHistory(os);
    5925             :     // included in sjy_setRadiusLimit
    5926             :     //tmodimage->copyData( (LatticeExpr<Float>)(modimage) );
    5927             :   }
    5928             :             
    5929             :   //if(selspw == 0){
    5930             :     os << LogIO::NORMAL // Loglevel INFO
    5931             :        << "The model image's reference pixel is " << sep 
    5932             :        << " arcsec from " << fieldName << "'s phase center."
    5933           0 :        << LogIO::POST;
    5934           0 :     writeHistory(os);
    5935             :   //}
    5936             : 
    5937           0 :   return tmodimage;
    5938           0 : }
    5939             : 
    5940           0 : Bool Imager::sjy_regridCubeChans(TempImage<Float>* tmodimage,
    5941             :                                  PagedImage<Float>& modimage, Int freqAxis)
    5942             : {
    5943           0 :   if(freqAxis != 3)
    5944           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"));
    5945           0 :   ImageRegrid<Float> ir;
    5946           0 :   IPosition axes(1, freqAxis);   // regrid the spectral only
    5947           0 :   ir.regrid(*tmodimage, Interpolate2D::LINEAR, axes, modimage);
    5948           0 :   return true;
    5949           0 : }
    5950             : 
    5951           0 : Bool Imager::sjy_setRadiusLimit(TempImage<Float>* tmodimage,
    5952             :                                 PagedImage<Float>& modimage, const String& model, DirectionCoordinate& dircsys)
    5953             : {
    5954           0 :   Path path(model);
    5955           0 :   String basename=path.baseName();
    5956             :   Float arad;
    5957             :   // radius limit in arcsec from AIPS
    5958           0 :   if (basename.find("3C286")==0) {
    5959           0 :       arad=3.0;
    5960             :   }
    5961           0 :   else if (basename.find("3C48")==0) {
    5962           0 :       arad=0.95;
    5963             :   }
    5964           0 :   else if (basename.find("3C147")==0) {
    5965           0 :       arad=0.85;
    5966             :   }
    5967           0 :   else if (basename.find("3C138")==0) {
    5968           0 :       arad=0.75;
    5969             :   }
    5970             :   else {
    5971           0 :       arad=0;
    5972           0 :       tmodimage->copyData(modimage);
    5973           0 :       return true;
    5974             :   }
    5975             :   try {
    5976           0 :     Quantity qrad(arad,"arcsec");
    5977           0 :     Float prad=Float(qrad.get(Unit("rad")).getValue()/abs(dircsys.increment()(0)));
    5978           0 :     Float radius = (prad >0.5 ? prad: 0.5);
    5979             :     //Add current ms name to avoid file access clash for MMS processing
    5980           0 :     String tempmaskname=ms_p->tableName()+"__tmp_mask_setjy_radiuslimit";
    5981           0 :     PagedImage<Float> maskImage(TiledShape(modimage.shape(),
    5982           0 :                                            modimage.niceCursorShape()),
    5983           0 :                                 modimage.coordinates(), tempmaskname);
    5984           0 :     maskImage.table().markForDelete();
    5985           0 :     Matrix<Float> circ(1,3);
    5986           0 :     Record *imrec=0;
    5987           0 :     Matrix<Quantity> blctrcs;
    5988           0 :     circ(0,0)=radius;
    5989           0 :     circ(0,1)=dircsys.referencePixel()(0);
    5990           0 :     circ(0,2)=dircsys.referencePixel()(1);
    5991           0 :     Imager::regionToImageMask(tempmaskname,imrec,blctrcs,circ,1.0);
    5992           0 :     PagedImage<Float> tmpmask(tempmaskname);
    5993           0 :     tmpmask.table().markForDelete();
    5994           0 :     tmodimage->copyData( (LatticeExpr<Float>)(tmpmask*modimage));
    5995           0 :   }
    5996           0 :   catch (...) {
    5997           0 :     return false;
    5998           0 :   }
    5999           0 :   return true;
    6000           0 : }
    6001             : 
    6002           0 : Bool Imager::sjy_calciflux(const Vector<MFrequency>& freqs, const MFrequency& reffreq, 
    6003             :                            const Double refflux, const Vector<Double>& vspix, Vector<Double>& iflux)
    6004             : {
    6005             :   try {
    6006             :     // assume polynomical is log(S) = c0 + alpha*log(f/fo) + curv1*log(f/fo)^2+
    6007             :     // vspix should contains [alpha, curv1, etc..] and c0 is calculated from refflux 
    6008           0 :     uInt porder = vspix.nelements();
    6009           0 :     Polynomial<Double> lf(porder);
    6010           0 :     Vector<Double> coeffs(porder+1);
    6011           0 :     coeffs[0] = log10(refflux);
    6012           0 :     for (uInt i = 1; i < vspix.nelements()+1; i++ ) {
    6013           0 :       coeffs[i] = vspix[i-1];
    6014             :     }
    6015           0 :     lf.setCoefficients(coeffs);
    6016           0 :     Int nf = freqs.nelements();
    6017           0 :     iflux.resize(nf);
    6018           0 :     Unit frequnit("GHz");
    6019           0 :     Double reffreqval = reffreq.get(frequnit).getValue();
    6020           0 :     for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
    6021           0 :       iflux[cfidx] = pow(10.0,lf(log10(freqs[cfidx].get(frequnit).getValue()/reffreqval))); 
    6022             :     }
    6023           0 :   }
    6024           0 :   catch (...) {
    6025           0 :     return false;
    6026           0 :   } 
    6027           0 :   return true; 
    6028             : }
    6029             : 
    6030           0 : Bool Imager::sjy_calcquflux(const Vector<Double>& pipars, const Vector<Double>& papars,
    6031             :                             const Vector<Double>& iflux, const Double rotMeas,
    6032             :                             const Vector<MFrequency>& freqs, 
    6033             :                             const MFrequency& reffreq, Vector<Double>& qflux,
    6034             :                             Vector<Double>& uflux)
    6035             : {
    6036             : 
    6037             :   try {
    6038           0 :     Int nf = freqs.nelements();
    6039             :     //polindex
    6040             :     // of the form, pi_o + c1*(f-fo)/fo + c2*(f-fo)/fo
    6041           0 :     Polynomial<Double> pipoly(pipars.nelements());
    6042           0 :     pipoly.setCoefficients(pipars);
    6043             :     //pangle
    6044           0 :     Polynomial<Double> papoly(papars.nelements());
    6045           0 :     papoly.setCoefficients(papars);
    6046           0 :     qflux.resize(nf);
    6047           0 :     uflux.resize(nf);
    6048           0 :     Unit ghz("Hz"); 
    6049           0 :     Double f0 = reffreq.get(ghz).getValue();
    6050             : 
    6051           0 :     for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
    6052           0 :       Double f = freqs[cfidx].get(ghz).getValue();
    6053           0 :       Double ipi = pipoly((f-f0)/f0);
    6054           0 :       Double ipa = papoly((f-f0)/f0);
    6055           0 :       Double iiflux = iflux[cfidx];
    6056           0 :       Double qfluxval = ipi * iiflux * cos(2.0*ipa);
    6057           0 :       Double ufluxval = ipi * iiflux * sin(2.0*ipa);
    6058             :       //debug
    6059             :       //if (cfidx<10) cerr<<"sjy_calcquflux:: poli="<<ipi<<" pola="<<ipa<<" qflux="<<qfluxval<<" uflux="<<ufluxval<<endl;
    6060           0 :       if (rotMeas!=0.0 ) {
    6061           0 :         Double rotangle = 2*rotMeas * C::c * C::c * (f0*f0-f*f)/(f*f*f0*f0);
    6062             :         //if (cfidx<10) cerr<<"rotangle="<<rotangle<<endl;
    6063           0 :         qflux[cfidx] = qfluxval*cos(rotangle) - ufluxval*sin(rotangle);
    6064           0 :         uflux[cfidx] = qfluxval*sin(rotangle) + ufluxval*cos(rotangle); 
    6065             :       }
    6066             :       else { 
    6067           0 :         qflux[cfidx] = qfluxval; 
    6068           0 :         uflux[cfidx] = ufluxval; 
    6069             :       }
    6070             :       //if (cfidx<10) cerr<<"uflux/qflux["<<cfidx<<"]="<<uflux[cfidx]/qflux[cfidx]<<endl;
    6071             :     }
    6072           0 :   }
    6073           0 :   catch (...) {
    6074           0 :     return false;
    6075           0 :   }
    6076           0 :   return true;
    6077             : }
    6078             : 
    6079             : 
    6080           0 : Bool Imager::clone(const String& imageName, const String& newImageName)
    6081             : {
    6082             :   //if(!valid()) return false;
    6083             :   // This is not needed if(!assertDefinedImageParameters()) return false;
    6084           0 :   LogIO os(LogOrigin("imager", "clone()", WHERE));
    6085             :   try {
    6086           0 :     PagedImage<Float> oldImage(imageName);
    6087           0 :     PagedImage<Float> newImage(TiledShape(oldImage.shape(), 
    6088           0 :                                           oldImage.niceCursorShape()), oldImage.coordinates(),
    6089           0 :                                newImageName);
    6090           0 :     newImage.set(0.0);
    6091           0 :     newImage.table().flush(true, true);
    6092           0 :   } catch (AipsError x) {
    6093           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6094           0 :     return false;
    6095           0 :   } 
    6096           0 :   return true;
    6097           0 : }
    6098             : 
    6099             : // Make an empty image
    6100           0 : Bool Imager::make(const String& model)
    6101             : {
    6102             : 
    6103           0 :   if(!valid())
    6104             :     {
    6105           0 :       return false;
    6106             :     }
    6107           0 :   LogIO os(LogOrigin("imager", "make()", WHERE));
    6108             :   
    6109           0 :   this->lock();
    6110             :   try {
    6111           0 :     if(!assertDefinedImageParameters())
    6112             :       {
    6113           0 :         return false;
    6114             :       }
    6115             :     
    6116             :     // Make an image with the required shape and coordinates
    6117           0 :     String modelName(model);
    6118           0 :     if(modelName=="") modelName=imageName()+".model";
    6119             :     os << LogIO::DEBUG1
    6120           0 :        << "Making empty image: " << modelName << LogIO::POST;
    6121             :     
    6122           0 :     removeTable(modelName);
    6123           0 :     CoordinateSystem coords;
    6124             :     //if(!imagecoordinates(coords, false)) 
    6125           0 :     if(!imagecoordinates2(coords, false)) 
    6126             :       {
    6127           0 :         this->unlock();
    6128           0 :         return false;
    6129             :       }
    6130           0 :     this->makeEmptyImage(coords, modelName, fieldid_p);
    6131           0 :     this->unlock();
    6132             :     
    6133           0 :     return true;
    6134           0 :   } catch (AipsError x) {
    6135           0 :     this->unlock();
    6136           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6137             : 
    6138           0 :     return false;    
    6139             : 
    6140           0 :   } 
    6141             :   this->unlock();
    6142             : 
    6143             :   return true;
    6144           0 : }
    6145             : 
    6146             : // Fit the psf. If psf is blank then make the psf first.
    6147           0 : Bool Imager::fitpsf(const String& psf, ImageBeamSet& mbeam) {
    6148             : 
    6149           0 :   if(!valid()) 
    6150             :     {
    6151           0 :       return false;
    6152             :     }
    6153           0 :   LogIO os(LogOrigin("imager", "fitpsf()", WHERE));
    6154             :   
    6155           0 :   this->lock();
    6156             :   try {
    6157           0 :     if(!assertDefinedImageParameters()) 
    6158             :       {
    6159           0 :         this->unlock();
    6160           0 :         return false;
    6161             :       }
    6162             :     
    6163           0 :     os << LogIO::NORMAL << "Fitting to psf" << LogIO::POST; // Loglevel PROGRESS
    6164             :     
    6165           0 :     String lpsf; lpsf=psf;
    6166           0 :     if(lpsf=="") {
    6167           0 :       lpsf=imageName()+".psf";
    6168           0 :       makeimage("psf", lpsf);
    6169             :     }
    6170             : 
    6171           0 :     if(!Table::isReadable(lpsf)) {
    6172           0 :       this->unlock();
    6173             :       os << LogIO::SEVERE << "PSF image " << lpsf << " does not exist"
    6174           0 :          << LogIO::POST;
    6175             : 
    6176           0 :       return false;
    6177             :     }
    6178             : 
    6179           0 :     PagedImage<Float> psfImage(lpsf);
    6180           0 :     StokesImageUtil::FitGaussianPSF(psfImage, mbeam);
    6181           0 :     beam_p = mbeam;
    6182           0 :     beamValid_p=true;
    6183             :     
    6184           0 :     GaussianBeam elbeam=beam_p(0,0);
    6185             :     os << LogIO::NORMAL // Loglevel INFO
    6186             :        << "  Beam fit: " << elbeam.getMajor("arcsec") << " by "
    6187             :        << elbeam.getMinor("arcsec") << " (arcsec) at pa "
    6188           0 :        << elbeam.getPA(Unit("deg")) << " (deg) " << endl;
    6189             : 
    6190           0 :     this->unlock();
    6191             :     
    6192           0 :     return true;
    6193           0 :   } catch (AipsError x) {
    6194           0 :     this->unlock();
    6195           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6196             : 
    6197           0 :      return false;
    6198           0 :   } 
    6199             :   this->unlock();
    6200             : 
    6201             :   return true;
    6202           0 : }
    6203             : 
    6204             : 
    6205           0 : Bool Imager::setscales(const String& scaleMethod,
    6206             :                             const Int inscales,
    6207             :                             const Vector<Float>& userScaleSizes)
    6208             : {
    6209           0 :   scaleMethod_p = scaleMethod;
    6210           0 :   userScaleSizes_p.resize(userScaleSizes.nelements());
    6211           0 :   userScaleSizes_p = userScaleSizes;
    6212           0 :   if (scaleMethod_p == "uservector") {
    6213           0 :     nscales_p =  userScaleSizes.nelements();
    6214             :   } else {
    6215           0 :     nscales_p = inscales;
    6216             :   }
    6217             :   //Force the creation of a new sm_p with the new scales
    6218           0 :   destroySkyEquation();
    6219           0 :   scaleInfoValid_p = true;  
    6220           0 :   return true;
    6221             : };
    6222             : 
    6223           0 : Bool Imager::setSmallScaleBias(const Float inbias)
    6224             : { 
    6225           0 :   smallScaleBias_p = inbias;
    6226           0 :   return true;
    6227             : }
    6228             : 
    6229             : // Added for wb algo.
    6230           0 : Bool Imager::settaylorterms(const Int intaylor,const Double inreffreq)
    6231             : {
    6232           0 :   ntaylor_p = intaylor;
    6233           0 :   reffreq_p = inreffreq;
    6234           0 :   return true;
    6235             : };
    6236             : 
    6237             : // Set the beam
    6238           0 : Bool Imager::setbeam(const ImageBeamSet& mbeam)
    6239             : {
    6240           0 :   if(!valid()) return false;
    6241             :   
    6242           0 :   LogIO os(LogOrigin("imager", "setbeam()", WHERE));
    6243           0 :   beam_p = ImageBeamSet(mbeam);
    6244           0 :   beamValid_p=true;
    6245             :     
    6246           0 :   return true;
    6247           0 : }
    6248             : 
    6249             : // Plot the uv plane
    6250           0 : Bool Imager::plotuv(const Bool rotate) 
    6251             : {
    6252             : 
    6253           0 :   if(!valid()) return false;
    6254             :   
    6255           0 :   LogIO os(LogOrigin("imager", "plotuv()", WHERE));
    6256             :   
    6257           0 :   this->lock();
    6258             :   try {
    6259             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6260           0 :        << "Plotting uv coverage for currently selected data" << LogIO::POST;
    6261             :     
    6262           0 :     ROVisIter& vi(*rvi_p);
    6263           0 :     VisBuffer vb(vi);
    6264             :     
    6265           0 :     uInt nVis = count_visibilities(rvi_p, true, true);
    6266             :     
    6267           0 :     if(nVis==0) {
    6268           0 :       this->unlock();
    6269           0 :       os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
    6270           0 :       return false;
    6271             :     }
    6272             :     
    6273           0 :     if(rotate) {
    6274             :       os << LogIO::NORMAL // Loglevel INFO
    6275           0 :          << "UVW will be rotated to specified phase center" << LogIO::POST;    
    6276             :     }
    6277             :     
    6278             :     
    6279           0 :     Vector<Float> u(nVis); u=0.0;
    6280           0 :     Vector<Float> v(nVis); v=0.0;
    6281           0 :     Vector<Float> uRotated(nVis); uRotated=0.0;
    6282           0 :     Vector<Float> vRotated(nVis); vRotated=0.0;
    6283           0 :     Float maxAbsUV=0.0;
    6284             :     
    6285           0 :     Int iVis=0;
    6286           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6287           0 :       for (vi.origin();vi.more();vi++) {
    6288           0 :         Int nRow=vb.nRow();
    6289           0 :         Int nChan=vb.nChannel();
    6290           0 :         Vector<Double> uvwRotated(3);
    6291           0 :         MeasFrame mFrame((MEpoch(Quantity(vb.time()(0), "s"))), mLocation_p);
    6292           0 :         UVWMachine uvwMachine(phaseCenter_p, vb.phaseCenter(), mFrame);
    6293           0 :         for (Int row=0; row<nRow; ++row) {
    6294           0 :           if(rotate) {
    6295           0 :             for (Int dim=0;dim<3;++dim) {
    6296           0 :               uvwRotated(dim)=vb.uvw()(row)(dim);
    6297             :             }
    6298           0 :             uvwMachine.convertUVW(uvwRotated);
    6299             :           }
    6300             :           
    6301           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6302           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6303           0 :               Float f=vb.frequency()(chn)/C::c;
    6304           0 :               u(iVis)=vb.uvw()(row)(0)*f;
    6305           0 :               v(iVis)=vb.uvw()(row)(1)*f;
    6306           0 :               if(abs(u(iVis))>maxAbsUV) maxAbsUV=abs(u(iVis));
    6307           0 :               if(abs(v(iVis))>maxAbsUV) maxAbsUV=abs(v(iVis));
    6308           0 :               if(rotate) {
    6309           0 :                 uRotated(iVis)=uvwRotated(0)*f;
    6310           0 :                 vRotated(iVis)=uvwRotated(1)*f;
    6311           0 :                 if(abs(uRotated(iVis))>maxAbsUV) maxAbsUV=abs(uRotated(iVis));
    6312           0 :                 if(abs(vRotated(iVis))>maxAbsUV) maxAbsUV=abs(vRotated(iVis));
    6313             :               }
    6314           0 :               ++iVis;
    6315             :             }
    6316             :           }
    6317             :         }
    6318           0 :       }
    6319             :     }
    6320             :     
    6321           0 :     if(maxAbsUV==0.0) {
    6322           0 :       this->unlock();
    6323           0 :       os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6324           0 :       return false;
    6325             :     }
    6326             :     else {
    6327           0 :       Quantity cell(0.5/maxAbsUV, "rad");
    6328             :       os << LogIO::NORMAL // Loglevel INFO
    6329           0 :          << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
    6330             :       os << LogIO::NORMAL // Loglevel INFO
    6331           0 :          << "Recommended cell size < " << cell.get("arcsec").getValue()
    6332           0 :          << " arcsec" << LogIO::POST;
    6333           0 :     }
    6334             :     
    6335             :    
    6336           0 :     return false;
    6337             : 
    6338             :     this->unlock();
    6339             :   
    6340           0 :   } 
    6341           0 :   catch (AipsError x) {
    6342           0 :     this->unlock();
    6343           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6344           0 :     return false;
    6345             :     
    6346           0 :   } 
    6347           0 :   catch (...) {
    6348           0 :     this->unlock();  
    6349           0 :   } 
    6350           0 :   this->unlock();
    6351             :   
    6352             :   
    6353             : 
    6354           0 :   return true;
    6355           0 : }
    6356             : 
    6357             : // Plot the visibilities
    6358           0 : Bool Imager::plotvis(const String& type, const Int increment) 
    6359             : {
    6360             : 
    6361           0 :   if(!valid()) return false;
    6362           0 :   LogIO os(LogOrigin("imager", "plotvis()", WHERE));
    6363             :   
    6364           0 :   this->lock();
    6365             :   try {
    6366             :     
    6367             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6368             :        << "Plotting Stokes I visibility for currently selected data"
    6369           0 :        << LogIO::POST;
    6370             :     
    6371             :     
    6372           0 :     MSColumns msc(*mssel_p);
    6373           0 :     Bool hasCorrected=!(msc.correctedData().isNull());
    6374           0 :     Bool hasModel= true; //with virtual model data service model data is always there
    6375             :     //why bother if it is not requested
    6376           0 :     if(!((type == "all") || (type=="model") || (type == "residual")))
    6377           0 :       hasModel=false;
    6378           0 :     if(!((type == "all") || (type=="corrected") || (type == "residual")))
    6379           0 :       hasCorrected=false;
    6380             :     
    6381             : 
    6382             : 
    6383           0 :     Bool twoPol=true;
    6384           0 :     Vector<String> polType=msc.feed().polarizationType()(0);
    6385           0 :     if (polType(0)!="X" && polType(0)!="Y" &&
    6386           0 :         polType(0)!="R" && polType(0)!="L") {
    6387           0 :       twoPol=false;
    6388             :     }
    6389             :     
    6390           0 :     ROVisIter& vi(*rvi_p);
    6391           0 :     VisBuffer vb(vi);
    6392             :     
    6393           0 :     Int nVis=0;
    6394           0 :     Int counter=0;
    6395           0 :     Float maxWeight=0;
    6396           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6397           0 :       for (vi.origin();vi.more();vi++) {
    6398           0 :         Int nRow=vb.nRow();
    6399           0 :         Int nChan=vb.nChannel();
    6400           0 :         maxWeight=max(maxWeight, max(vb.imagingWeight()));
    6401           0 :         for (Int row=0; row<nRow; ++row) {
    6402           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6403           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6404           0 :               ++counter;
    6405           0 :               if(counter==increment) {
    6406           0 :                 counter=0;
    6407           0 :                 ++nVis;
    6408             :               }
    6409             :             }
    6410             :           }
    6411             :         }
    6412             :       }
    6413             :     }
    6414             :     
    6415           0 :     if(nVis==0) {
    6416           0 :       os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
    6417           0 :       if(maxWeight <=0){
    6418             :         os << LogIO::SEVERE << "Max of imaging-weight is " << maxWeight 
    6419           0 :            << LogIO::POST;
    6420             :         os << LogIO::SEVERE << "Try setting it with the function weight"  
    6421           0 :            << LogIO::POST;
    6422             :       }
    6423           0 :       this->unlock();
    6424           0 :       return false;
    6425             :     }
    6426             :     
    6427           0 :     if(increment>1) {
    6428             :       os << LogIO::NORMAL << "For increment = " << increment << ", found " << nVis // Loglevel INFO
    6429           0 :          << " points for plotting" << endl;
    6430             :     }
    6431             :     else {
    6432           0 :       os << LogIO::NORMAL << "Found " << nVis << " points for plotting" << endl; // Loglevel INFO
    6433             :     }
    6434           0 :     Vector<Float> amp(nVis); amp=0.0;
    6435           0 :     Vector<Float> correctedAmp(nVis); correctedAmp=0.0;
    6436           0 :     Vector<Float> modelAmp(nVis); modelAmp=0.0;
    6437           0 :     Vector<Float> residualAmp(nVis); residualAmp=0.0;
    6438           0 :     Vector<Float> uvDistance(nVis); uvDistance=0.0;
    6439             :    
    6440           0 :     if(!hasModel)
    6441           0 :       modelAmp.resize();
    6442           0 :     if(!hasCorrected)
    6443           0 :       correctedAmp.resize();
    6444           0 :     if(!hasCorrected || !hasModel)
    6445           0 :       residualAmp.resize();
    6446             :     
    6447             : 
    6448           0 :     Float maxuvDistance=0.0;
    6449           0 :     Float maxAmp=0.0;
    6450           0 :     Float maxCorrectedAmp=0.0;
    6451           0 :     Float maxModelAmp=0.0;
    6452           0 :     Float maxResidualAmp=0.0;
    6453           0 :     Int iVis=0;
    6454           0 :     counter=0;
    6455           0 :     vi.originChunks();
    6456           0 :     vi.origin();
    6457           0 :     uInt numCorrPol=vb.nCorr();
    6458           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6459           0 :       for (vi.origin();vi.more();vi++) {
    6460           0 :         Int nRow=vb.nRow();
    6461           0 :         Int nChan=vb.nChannel();
    6462           0 :         for (Int row=0; row<nRow; ++row) {
    6463           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6464           0 :             if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6465           0 :               ++counter;
    6466           0 :               if(counter==increment) {
    6467           0 :                 counter=0;
    6468           0 :                 Float f=vb.frequency()(chn)/C::c;
    6469           0 :                 Float u=vb.uvw()(row)(0)*f; 
    6470           0 :                 Float v=vb.uvw()(row)(1)*f;
    6471           0 :                 uvDistance(iVis)=sqrt(square(u)+square(v));
    6472           0 :                 if(twoPol) {
    6473           0 :                   amp(iVis)=sqrt((square(abs(vb.visCube()(0,chn,row)))+
    6474           0 :                                   square(abs(vb.visCube()(numCorrPol,chn,row))))/2.0);
    6475           0 :                   if(hasCorrected)
    6476           0 :                     correctedAmp(iVis)=
    6477           0 :                       sqrt((square(abs(vb.correctedVisCube()(0,chn,row)))+
    6478           0 :                             square(abs(vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6479           0 :                   if(hasModel)
    6480           0 :                     modelAmp(iVis)=
    6481           0 :                       sqrt((square(abs(vb.modelVisCube()(0,chn,row)))+
    6482           0 :                             square(abs(vb.modelVisCube()(numCorrPol,chn,row))))/2.0);
    6483           0 :                   if(hasCorrected && hasModel)
    6484           0 :                     residualAmp(iVis)=
    6485           0 :                       sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
    6486           0 :                                        vb.correctedVisCube()(0,chn,row)))+
    6487           0 :                             square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
    6488           0 :                                        vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6489             :                 }
    6490             :                 else {
    6491           0 :                   amp(iVis)=abs(vb.visCube()(0,chn,row));
    6492           0 :                   if(hasCorrected)
    6493           0 :                     correctedAmp(iVis)=abs(vb.correctedVisCube()(0,chn,row));
    6494           0 :                    if(hasModel)
    6495           0 :                      modelAmp(iVis)=abs(vb.modelVisCube()(0,chn,row));
    6496           0 :                   if(hasCorrected && hasModel) 
    6497           0 :                     residualAmp(iVis)=
    6498           0 :                       abs(vb.modelVisCube()(0,chn,row)-
    6499           0 :                           vb.correctedVisCube()(0,chn,row));
    6500             :                 }
    6501           0 :                 if(uvDistance(iVis)>maxuvDistance) {
    6502           0 :                   maxuvDistance=uvDistance(iVis);
    6503             :                 }
    6504           0 :                 if(amp(iVis)>maxAmp) {
    6505           0 :                   maxAmp=amp(iVis);
    6506             :                 }
    6507           0 :                 if(hasCorrected && (correctedAmp(iVis)>maxCorrectedAmp)) {
    6508           0 :                   maxCorrectedAmp=correctedAmp(iVis);
    6509             :                 }
    6510           0 :                 if(hasModel && (modelAmp(iVis)>maxModelAmp)) {
    6511           0 :                   maxModelAmp=modelAmp(iVis);
    6512             :                 }
    6513           0 :                 if((hasModel&&hasCorrected) && (residualAmp(iVis)>maxResidualAmp)) {
    6514           0 :                   maxResidualAmp=residualAmp(iVis);
    6515             :                 }
    6516           0 :                 ++iVis;
    6517             :               }
    6518             :             }
    6519             :           }
    6520             :         }
    6521             :       }
    6522             :     }
    6523             :     
    6524             : 
    6525             : 
    6526           0 :     if(maxuvDistance==0.0) {
    6527           0 :       os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6528           0 :       this->unlock();
    6529           0 :       return false;
    6530             :     }
    6531             :     
    6532             : 
    6533             : 
    6534             :     
    6535             : 
    6536           0 :     Float Ymax(0.0);
    6537             : 
    6538           0 :     if (type.contains("corrected") && hasCorrected)
    6539           0 :       if(maxCorrectedAmp>Ymax) Ymax = maxCorrectedAmp;
    6540             : 
    6541           0 :     if (type.contains("model") && hasModel)
    6542           0 :       if(maxModelAmp>Ymax)     Ymax = maxModelAmp;
    6543             : 
    6544           0 :     if (type.contains("residual") && (hasModel && hasCorrected))
    6545           0 :       if(maxResidualAmp>Ymax)  Ymax = maxResidualAmp;
    6546             : 
    6547           0 :     if (type.contains("observed"))
    6548           0 :       if(maxAmp>Ymax)          Ymax = maxAmp;
    6549             : 
    6550           0 :     if ((type=="all") || (type == ""))
    6551             :       {
    6552           0 :         if (maxAmp > Ymax)       Ymax = maxAmp;
    6553           0 :         if(hasCorrected && (maxCorrectedAmp>Ymax)) Ymax = maxCorrectedAmp;
    6554           0 :         if(hasModel && (maxModelAmp>Ymax))     Ymax = maxModelAmp;
    6555           0 :         if((hasModel && hasCorrected) && maxResidualAmp>Ymax)  Ymax = maxResidualAmp;
    6556             :       }
    6557             :    
    6558             : 
    6559           0 :     return false;
    6560             : 
    6561             :     
    6562             :     this->unlock();
    6563             :     return true;
    6564           0 :   } catch (AipsError x) {
    6565           0 :     this->unlock();
    6566           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6567           0 :     return false;
    6568           0 :   } 
    6569             :   this->unlock();
    6570             : 
    6571             :   return true;
    6572           0 : }
    6573             : 
    6574             : // Plot the weights
    6575           0 : Bool Imager::plotweights(const Bool gridded, const Int increment) 
    6576             : {
    6577             : 
    6578           0 :   if(!valid()) return false;
    6579           0 :   LogIO os(LogOrigin("imager", "plotweights()", WHERE));
    6580             :   
    6581           0 :   this->lock();
    6582             :   try {
    6583             :     
    6584             :     
    6585             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6586             :        << "Plotting imaging weights for currently selected data"
    6587           0 :        << LogIO::POST;
    6588             :     
    6589           0 :     ROVisIter& vi(*rvi_p);
    6590           0 :     VisBuffer vb(vi);
    6591             :     
    6592           0 :     if(gridded) {
    6593           0 :       if(!assertDefinedImageParameters()) {this->unlock(); return false;}
    6594             :       // First find the gridded weights
    6595             :       Float uscale, vscale;
    6596             :       Int uorigin, vorigin;
    6597           0 :       uscale=(nx_p*mcellx_p.get("rad").getValue())/2.0;
    6598           0 :       vscale=(ny_p*mcelly_p.get("rad").getValue())/2.0;
    6599           0 :       uorigin=nx_p/2;
    6600           0 :       vorigin=ny_p/2;
    6601             :       
    6602             :       // Simply declare a big matrix 
    6603           0 :       Float maxWeight=0.0;
    6604           0 :       Matrix<Float> gwt(nx_p,ny_p);
    6605           0 :       gwt=0.0;
    6606             :       
    6607             :       Float u, v;
    6608           0 :       Float sumwt=0.0;
    6609           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6610           0 :         for (vi.origin();vi.more();vi++) {
    6611           0 :           Int nRow=vb.nRow();
    6612           0 :           Int nChan=vb.nChannel();
    6613           0 :           for (Int row=0; row<nRow; ++row) {
    6614           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6615           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6616           0 :                 Float f=vb.frequency()(chn)/C::c;
    6617           0 :                 u=vb.uvw()(row)(0)*f; 
    6618           0 :                 v=vb.uvw()(row)(1)*f;
    6619           0 :                 Int ucell=Int(uscale*u+uorigin);
    6620           0 :                 Int vcell=Int(vscale*v+vorigin);
    6621           0 :                 if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
    6622           0 :                   gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
    6623           0 :                   sumwt+=vb.imagingWeight()(chn,row);
    6624           0 :                   if(vb.imagingWeight()(chn,row)>maxWeight) {
    6625           0 :                     maxWeight=vb.imagingWeight()(chn,row);
    6626             :                   }
    6627             :                 }
    6628           0 :                 ucell=Int(-uscale*u+uorigin);
    6629           0 :                 vcell=Int(-vscale*v+vorigin);
    6630           0 :                 if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
    6631           0 :                   gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
    6632             :                 }
    6633             :               }
    6634             :             }
    6635             :           }
    6636             :         }
    6637             :       }
    6638             :       
    6639           0 :       if(sumwt>0.0) {
    6640           0 :         os << LogIO::NORMAL << "Sum of weights = " << sumwt << endl; // Loglevel INFO
    6641             :       }
    6642             :       else {
    6643           0 :         this->unlock();
    6644             :         os << LogIO::SEVERE << "Sum of weights is zero: perhaps you need to weight the data"
    6645           0 :            << LogIO::POST;
    6646           0 :           return false;
    6647             :       }
    6648             :      
    6649             :       
    6650             :       //Float umax=Float(nx_p/2)/uscale;
    6651             :       //Float vmax=Float(ny_p/2)/vscale;
    6652             : 
    6653             : 
    6654           0 :       return false;
    6655           0 :     }
    6656             :     else {
    6657             :       
    6658             :       // Now do the points plot
    6659           0 :       Int nVis=0;
    6660           0 :       Int counter=0;
    6661           0 :       Float maxWeight=0.0;
    6662           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6663           0 :         for (vi.origin();vi.more();vi++) {
    6664           0 :           Int nRow=vb.nRow();
    6665           0 :           Int nChan=vb.nChannel();
    6666           0 :           for (Int row=0; row<nRow; ++row) {
    6667           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6668           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6669           0 :                 ++counter;
    6670           0 :                 if(counter==increment) {
    6671           0 :                   counter=0;
    6672           0 :                   ++nVis;
    6673             :                 }
    6674             :               }
    6675             :             }
    6676             :           }
    6677             :         }
    6678             :       }
    6679             :       
    6680           0 :       if(increment>1) {
    6681             :         os << LogIO::NORMAL // Loglevel INFO
    6682             :            << "For increment = " << increment << ", found " << nVis
    6683           0 :            << " points for plotting" << endl;
    6684             :       }
    6685             :       else {
    6686             :         os << LogIO::NORMAL // Loglevel INFO
    6687           0 :            << "Found " << nVis << " points for plotting" << endl;
    6688             :       }
    6689             :       
    6690           0 :       Float maxuvDistance=0.0;
    6691           0 :       Vector<Float> weights(nVis);
    6692           0 :       Vector<Float> uvDistance(nVis);
    6693           0 :       weights=0.0;
    6694           0 :       uvDistance=0.0;
    6695             :       
    6696           0 :       Int iVis=0;
    6697           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6698           0 :         for (vi.origin();vi.more();vi++) {
    6699           0 :           Int nRow=vb.nRow();
    6700           0 :           Int nChan=vb.nChannel();
    6701           0 :           for (Int row=0; row<nRow; ++row) {
    6702           0 :             for (Int chn=0; chn<nChan; ++chn) {
    6703           0 :               if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
    6704           0 :                 ++counter;
    6705           0 :                 if(counter==increment) {
    6706           0 :                   Float f=vb.frequency()(chn)/C::c;
    6707           0 :                   Float u=vb.uvw()(row)(0)*f; 
    6708           0 :                   Float v=vb.uvw()(row)(1)*f;
    6709           0 :                   uvDistance(iVis)=sqrt(square(u)+square(v));
    6710           0 :                   weights(iVis)=vb.imagingWeight()(chn,row);
    6711           0 :                   if(vb.imagingWeight()(chn,row)>maxWeight) {
    6712           0 :                     maxWeight=vb.imagingWeight()(chn,row);
    6713             :                   }
    6714           0 :                   if(uvDistance(iVis)>maxuvDistance) {
    6715           0 :                     maxuvDistance=uvDistance(iVis);
    6716             :                   }
    6717           0 :                   counter=0;
    6718           0 :                   ++iVis;
    6719             :                 }
    6720             :               }
    6721             :             }
    6722             :           }
    6723             :         }
    6724             :       }
    6725             :       
    6726           0 :       if(maxuvDistance==0.0) {
    6727           0 :         this->unlock();
    6728           0 :         os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
    6729           0 :         return false;
    6730             :       }
    6731             : 
    6732             : 
    6733           0 :       return false;
    6734           0 :     }
    6735             :     
    6736             : 
    6737             :     
    6738             :     this->unlock();
    6739             :     return true;
    6740           0 :   } catch (AipsError x) {
    6741           0 :     this->unlock();
    6742           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6743           0 :     return false;
    6744           0 :   } 
    6745             :   this->unlock();
    6746             : 
    6747             :   return true;
    6748           0 : }
    6749             : 
    6750           0 : Bool Imager::clipvis(const Quantity& threshold) 
    6751             : {
    6752             : 
    6753           0 :   if(!valid()) return false;
    6754             :   
    6755           0 :   LogIO os(LogOrigin("imager", "clipvis()", WHERE));
    6756             :   
    6757           0 :   this->lock();
    6758             :   try {
    6759             :     
    6760           0 :     Float thres=threshold.get("Jy").getValue();
    6761             :     
    6762             :     os << LogIO::NORMAL // Loglevel PROGRESS
    6763             :        << "Clipping visibilities where residual visibility > "
    6764           0 :        << thres << " Jy" << LogIO::POST;
    6765           0 :     if(!wvi_p){
    6766             :       os << LogIO::WARN
    6767             :          << "Cannot clip visibilities in read only mode of ms" 
    6768           0 :          << LogIO::POST;
    6769           0 :       return false;
    6770             :     }
    6771           0 :     VisIter& vi(*wvi_p);
    6772           0 :     VisBuffer vb(vi);
    6773             :     
    6774             : 
    6775           0 :     vi.originChunks();
    6776           0 :     vi.origin();
    6777             : // Making sure picking LL for [RR RL LR LL] correlations or [RR LL] 
    6778           0 :     uInt numCorrPol=vb.modelVisCube().shape()(0) - 1 ; 
    6779           0 :     Int nBad=0;
    6780           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6781           0 :       for (vi.origin();vi.more();vi++) {
    6782           0 :         Int nRow=vb.nRow();
    6783           0 :         Int nChan=vb.nChannel();
    6784           0 :         for (Int row=0; row<nRow; ++row) {
    6785           0 :           for (Int chn=0; chn<nChan; ++chn) {
    6786           0 :             if(!vb.flag()(chn,row)) {
    6787             :               Float residualAmp=
    6788           0 :                 sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
    6789           0 :                                  vb.correctedVisCube()(0,chn,row)))+
    6790           0 :                       square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
    6791           0 :                                  vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
    6792           0 :               if(residualAmp>thres) {
    6793           0 :                 vb.flag()(chn,row)=true;
    6794           0 :                 ++nBad;
    6795             :               }
    6796             :             }
    6797             :           }
    6798             :         }
    6799           0 :         vi.setFlag(vb.flag());
    6800             :       }
    6801             :     }
    6802             :     
    6803           0 :     os << LogIO::NORMAL << "Flagged " << nBad << " points" << LogIO::POST; // Loglevel INFO
    6804             :     
    6805           0 :     this->unlock();
    6806           0 :     return true;
    6807           0 :   } catch (AipsError x) {
    6808           0 :     this->unlock();
    6809           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6810           0 :   } 
    6811           0 :   this->unlock();
    6812             : 
    6813           0 :   return true;
    6814           0 : }
    6815             : 
    6816             : // Plot various ids
    6817           0 : Bool Imager::plotsummary() 
    6818             : {
    6819             :   
    6820           0 :   if(!valid()) return false;
    6821             :   
    6822           0 :   LogIO os(LogOrigin("imager", "plotsummary()", WHERE));
    6823             :   
    6824           0 :   os << LogIO::WARN << "NOT implemented " << LogIO::POST;
    6825           0 :   return false;
    6826             : 
    6827             :   this->lock();
    6828             :   try {
    6829             :     /*
    6830             :     os << "Plotting field and spectral window ids for currently selected data" << LogIO::POST;
    6831             :     
    6832             :     ROVisIter& vi(*rvi_p);
    6833             :     VisBuffer vb(vi);
    6834             :     
    6835             :     Int nVis=0;
    6836             :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6837             :       for (vi.origin();vi.more();vi++) {
    6838             :         Int nRow=vb.nRow();
    6839             :         for (Int row=0; row<nRow; ++row) {
    6840             :           ++nVis;
    6841             :         }
    6842             :       }
    6843             :     }
    6844             :     
    6845             :     os << "Found " << nVis << " selected records" << LogIO::POST;
    6846             :     
    6847             :     Vector<Float> fieldId(nVis);
    6848             :     Vector<Float> spectralWindowId(nVis);
    6849             :     Vector<Double> t(nVis);
    6850             :     
    6851             :     Int maxFieldId=0;
    6852             :     Int maxSpectralWindowId=0;
    6853             :     Int iVis=0;
    6854             :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    6855             :       for (vi.origin();vi.more();vi++) {
    6856             :         Int nRow=vb.nRow();
    6857             :         for (Int row=0; row<nRow; ++row) {
    6858             :           t(iVis)=vb.time()(row);
    6859             :           fieldId(iVis)=vb.fieldId()+1.0;
    6860             :           spectralWindowId(iVis)=vb.spectralWindow()+1.003;
    6861             :           if(Int(fieldId(iVis))>maxFieldId) maxFieldId=Int(fieldId(iVis));
    6862             :           if(Int(spectralWindowId(iVis))>maxSpectralWindowId)
    6863             :             maxSpectralWindowId=Int(spectralWindowId(iVis));
    6864             :           ++iVis;
    6865             :         }
    6866             :       }
    6867             :     }
    6868             :     
    6869             :     Double tStart=t(0);
    6870             :     Vector<Float> timeFloat(nVis);
    6871             :     for(Int i=0;i<nVis;++i) {
    6872             :       timeFloat(i)=Float(t(i)-tStart);
    6873             :     }
    6874             :     
    6875             :     MSColumns msc(*ms_p);
    6876             :     PGPlotter plotter=getPGPlotter();
    6877             :     plotter.subp(1, 2);
    6878             :     plotter.page();
    6879             :     plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0, Float(maxFieldId)*1.1);
    6880             :     plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
    6881             :     String xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
    6882             :     plotter.lab(xLabel, "ID", "Field IDs for " +imageName());
    6883             :     plotter.sci(1);
    6884             :     for (Int fid=0;fid<maxFieldId;++fid) {
    6885             :       String fieldName=msc.field().name()(fid);
    6886             :       plotter.text(1.02*timeFloat(nVis-1), Float(fid+1), fieldName);
    6887             :     }
    6888             :     plotter.pt(timeFloat,fieldId,-1);
    6889             :     plotter.page();
    6890             :     plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0,
    6891             :                  Float(maxSpectralWindowId)*1.1);
    6892             :     plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
    6893             :     xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
    6894             :     plotter.lab(xLabel, "ID", "Spectral Window IDs for " +imageName());
    6895             :     plotter.sci(1);
    6896             :     for(Int spwId=0;spwId<maxSpectralWindowId;++spwId) {
    6897             :       Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spwId); 
    6898             :       ostringstream spwString;
    6899             :       spwString<<chanFreq(0)/1.0e9<<" GHz";
    6900             :       plotter.text(1.02*timeFloat(nVis-1), Float(spwId+1),
    6901             :                    spwString);
    6902             :     }
    6903             :     plotter.pt(timeFloat,spectralWindowId,-1);
    6904             :     plotter.iden();
    6905             :     this->unlock();
    6906             :     return true;
    6907             :     */
    6908             :   } catch (AipsError x) {
    6909             :     this->unlock();
    6910             :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    6911             :     return false;
    6912             :   } 
    6913             :     
    6914             :   this->unlock();
    6915             : 
    6916             :   return true;
    6917           0 : }
    6918             : 
    6919             : 
    6920           0 : Bool Imager::detached() const
    6921             : {
    6922           0 :   if (ms_p.null()) {
    6923           0 :     LogIO os(LogOrigin("imager", "detached()", WHERE));
    6924             :     os << LogIO::SEVERE << 
    6925             :       "imager is detached - cannot perform operation." << endl <<
    6926           0 :       "Call imager.open('filename') to reattach." << LogIO::POST;
    6927           0 :     return true;
    6928           0 :   }
    6929           0 :   return false;
    6930             : }
    6931             : 
    6932           0 : Bool Imager::makemodelfromsd(const String& sdImage, const String& modelImage, 
    6933             :                              const String& lowPSF, String& maskImage)
    6934             : {
    6935             : 
    6936           0 :  if(!valid()) return false;
    6937             :   
    6938           0 :   LogIO os(LogOrigin("imager", "makemodelfromsd()", WHERE));
    6939             :   
    6940             :   try {
    6941             :     
    6942           0 :     if(!Table::isReadable(sdImage)){
    6943             :       os << LogIO::SEVERE  << "Single Dish " << sdImage 
    6944           0 :          << "  image is not readable" << LogIO::EXCEPTION;
    6945             :       
    6946           0 :       return false;
    6947             :     }
    6948             : 
    6949             :     os << LogIO::NORMAL << "Creating an initial model image " << modelImage  // Loglevel INFO
    6950           0 :        << " from single dish image " << sdImage << LogIO::POST;
    6951             :     
    6952           0 :     CoordinateSystem coordsys;
    6953             :     //imagecoordinates(coordsys);
    6954           0 :     imagecoordinates2(coordsys);
    6955           0 :     String modelName=modelImage;
    6956           0 :     this->makeEmptyImage(coordsys, modelName, fieldid_p);
    6957             :     
    6958           0 :     PagedImage<Float> model(modelImage);
    6959           0 :     PagedImage<Float> low0(sdImage);
    6960           0 :     String sdObs=low0.coordinates().obsInfo().telescope();
    6961             : 
    6962           0 :     GaussianBeam lBeam;
    6963           0 :     ImageInfo lowInfo=low0.imageInfo();
    6964           0 :     lBeam=lowInfo.restoringBeam();
    6965             :   
    6966           0 :     Float beamFactor=-1.0;
    6967             : 
    6968             :     
    6969             :     // regrid the single dish image
    6970             :     {
    6971           0 :       ImageRegrid<Float> ir;
    6972           0 :       IPosition axes(3,0,1,3);   // if its a cube, regrid the spectral too
    6973           0 :       ir.regrid(model, Interpolate2D::LINEAR, axes, low0);
    6974           0 :     }
    6975             :     
    6976             :   
    6977             : 
    6978             :     // Will need to make a complex image to apply the beam
    6979           0 :     TempImage<Complex> ctemp(model.shape(), model.coordinates());
    6980           0 :     if(lowPSF=="") {
    6981             :       os << LogIO::NORMAL // Loglevel INFO
    6982             :          << "Using primary beam of single dish to determine flux scale"
    6983           0 :          << LogIO::POST;
    6984             : 
    6985           0 :       TempImage<Float> beamTemp(model.shape(), model.coordinates());
    6986             :       //Make the PB accordingly
    6987           0 :       if(lBeam.isNull()) {
    6988             :       
    6989           0 :         if (doDefaultVP_p) { 
    6990           0 :           if(telescope_p!=""){
    6991           0 :             ObsInfo myobsinfo=this->latestObsInfo();
    6992           0 :             myobsinfo.setTelescope(telescope_p);
    6993           0 :             coordsys.setObsInfo(myobsinfo);
    6994             :             
    6995           0 :           }
    6996             :           else{
    6997           0 :             if(sdObs != ""){
    6998           0 :               telescope_p=sdObs;
    6999           0 :               ObsInfo myobsinfo=this->latestObsInfo();
    7000           0 :               myobsinfo.setTelescope(telescope_p);
    7001           0 :               coordsys.setObsInfo(myobsinfo);
    7002           0 :             }
    7003             :             else{
    7004           0 :               telescope_p=coordsys.obsInfo().telescope();
    7005             :             }
    7006             :           }
    7007           0 :           beamTemp.setCoordinateInfo(coordsys);
    7008           0 :           this->makePBImage(beamTemp);
    7009             :          
    7010             :         }
    7011             :         else{
    7012           0 :           Table vpTable(vpTableStr_p);
    7013           0 :           this->makePBImage(vpTable, beamTemp);      
    7014           0 :         }
    7015           0 :         StokesImageUtil::FitGaussianPSF(beamTemp, lBeam);
    7016           0 :         LatticeExprNode sumImage = sum(beamTemp);
    7017           0 :         beamFactor=sumImage.getFloat();
    7018             :         
    7019           0 :       }
    7020             :       
    7021             :       
    7022           0 :     }
    7023             :     else {
    7024             :       os << LogIO::NORMAL // Loglevel INFO
    7025             :          << "Using specified low resolution PSF to determine sd flux scale"
    7026           0 :          << LogIO::POST;
    7027             :       // regrid the single dish psf
    7028           0 :       PagedImage<Float> lowpsf0(lowPSF);
    7029           0 :       TempImage<Float> lowpsf(model.shape(), model.coordinates());
    7030             :       {
    7031           0 :         ImageRegrid<Float> ir;
    7032           0 :         IPosition axes(2,0,1);   //
    7033           0 :         ir.regrid(lowpsf, Interpolate2D::LINEAR, axes, lowpsf0);
    7034           0 :       }
    7035           0 :       LatticeExprNode sumImage = sum(lowpsf);
    7036           0 :       beamFactor=sumImage.getFloat();
    7037           0 :       if(lBeam.isNull()) {
    7038           0 :         os << LogIO::NORMAL << "Finding SD beam from given PSF" << LogIO::POST; // Loglevel PROGRESS
    7039           0 :         StokesImageUtil::FitGaussianPSF(lowpsf0, lBeam);
    7040             :       }
    7041           0 :     }
    7042             :     
    7043             : 
    7044             :     // This factor comes from the beam volumes
    7045           0 :     if(sdScale_p!=1.0)
    7046             :       os << LogIO::DEBUG1
    7047             :          << "Multiplying single dish data by user specified factor "
    7048           0 :          << sdScale_p << LogIO::POST;
    7049           0 :     Float sdScaling  = sdScale_p;
    7050           0 :     if(! lBeam.isNull()) {
    7051           0 :       Int directionIndex=model.coordinates().findCoordinate(Coordinate::DIRECTION);
    7052             :       DirectionCoordinate
    7053           0 :         directionCoord=model.coordinates().directionCoordinate(directionIndex);
    7054           0 :       Vector<String> units(2); units.set("arcsec");
    7055           0 :       directionCoord.setWorldAxisUnits(units); 
    7056           0 :       Vector<Double> incr= directionCoord.increment();
    7057           0 :       if(beamFactor >0.0) {
    7058           0 :         beamFactor=1.0/beamFactor;
    7059             :       }
    7060             :       else{
    7061             :         //      beamFactor=
    7062             :         //        abs(incr(0)*incr(1))/(lBeam(0).get("arcsec").getValue()*lBeam(1).get("arcsec").getValue()*1.162);
    7063             :         //Brute Force for now.
    7064           0 :         IPosition imshape(4, nx_p, ny_p, 1, 1);
    7065           0 :         TempImage<Float> lowpsf(imshape, coordsys);
    7066           0 :         lowpsf.set(0.0);
    7067           0 :         IPosition center(4, Int((nx_p/4)*2), Int((ny_p/4)*2),0,0);
    7068           0 :         lowpsf.putAt(1.0, center);
    7069           0 :         StokesImageUtil::Convolve(lowpsf, lBeam, false);
    7070           0 :         LatticeExprNode sumImage = sum(lowpsf);
    7071           0 :         beamFactor=1.0/sumImage.getFloat();
    7072             : 
    7073             :         
    7074           0 :       }
    7075             :       os << LogIO::NORMAL << "Beam volume factor  " // Loglevel INFO
    7076           0 :          <<  beamFactor << LogIO::POST;
    7077           0 :       sdScaling*=beamFactor;
    7078           0 :     }
    7079             :     else {
    7080           0 :       os << LogIO::WARN << "Insufficient information to scale correctly" << LogIO::POST;
    7081             :     }
    7082             :  
    7083             :     //Convert to Jy/pixel
    7084           0 :     model.copyData(  (LatticeExpr<Float>)((model * sdScaling)));
    7085           0 :     model.setUnits(Unit("Jy/pixel"));
    7086             :     
    7087             :     //make a mask image
    7088           0 :     this->makeEmptyImage(coordsys, maskImage, fieldid_p);
    7089           0 :     PagedImage<Float> mask(maskImage);
    7090           0 :     mask.set(1.0);
    7091           0 :     ArrayLattice<Bool> sdMask(model.getMask());
    7092           0 :     mask.copyData( LatticeExpr<Float> (mask* ntrue(sdMask)*model));
    7093           0 :     StokesImageUtil::MaskFrom(mask, mask, Quantity(0.0, "Jy"));
    7094           0 :     model.copyData( LatticeExpr<Float> (mask*model));
    7095           0 :     return true;
    7096           0 :   } catch (AipsError x) {
    7097             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    7098           0 :        << LogIO::POST;
    7099           0 :     return false;
    7100           0 :   } 
    7101             :   
    7102             :   return true;
    7103             : 
    7104             : 
    7105           0 : }
    7106             : 
    7107             : 
    7108           0 : Int Imager::interactivemask(const String& image, const String& mask, 
    7109             :                             Int& niter, Int& ncycles, String& thresh, const Bool forceReload){
    7110             : 
    7111           0 :   LogIO os(LogOrigin("Imager", "interactivemask()", WHERE));
    7112           0 :    if(Table::isReadable(mask)) {
    7113           0 :     if (! Table::isWritable(mask)) {
    7114           0 :       os << LogIO::WARN << "Mask image is not modifiable " << LogIO::POST;
    7115           0 :       return false;
    7116             :     }
    7117             :     //we should regrid here if image and mask do not match
    7118             :    }
    7119             :    else{
    7120           0 :      clone(image, mask);
    7121             :    }
    7122             : #ifdef USE_GRPC
    7123           0 :    Quantity thr;
    7124           0 :    if ( ! Quantity::read(thr,thresh) ) thr = Quantity(0,"Jy");
    7125           0 :    float thold = (float) thr.get("Jy").getValue( );
    7126           0 :    grpcInteractiveClean::getManager( ).setControls( niter, ncycles, thold);
    7127             : #endif
    7128           0 :    return false;
    7129           0 : }
    7130             : 
    7131           0 :   Record Imager::iClean(const String& algorithm, const Int niter, const Double gain, 
    7132             :                       const Quantity& threshold,
    7133             :                       const Bool displayprogress,
    7134             :                       const Vector<String>& model,
    7135             :                       const Vector<Bool>& keepfixed, const String& complist,
    7136             :                       const Vector<String>& mask,
    7137             :                       const Vector<String>& image,
    7138             :                       const Vector<String>& residual,
    7139             :                       const Vector<String>& psfnames,
    7140             :                       const Bool interactive, const Int npercycle,
    7141             :                       const String& masktemplate)
    7142             :   {
    7143           0 :     Record rstat;
    7144             :       
    7145           0 :     logSink_p.clearLocally();
    7146           0 :     LogIO os(LogOrigin("imager", "iClean()"), logSink_p);
    7147             : 
    7148           0 :     if(!ms_p.null()) {
    7149             :       //try
    7150             :        {
    7151             :        
    7152           0 :         Vector<String> amodel(model);
    7153           0 :         Vector<Bool>   fixed(keepfixed);
    7154           0 :         Vector<String> amask(mask);
    7155           0 :         Vector<String> aimage(image);
    7156           0 :         Vector<String> aresidual(residual);
    7157           0 :         Vector<String> apsf(psfnames);
    7158             :         
    7159           0 :         if(String(algorithm) != "msmfs") ntaylor_p=1; /* masks increment by ntaylor_p only for msmfs */
    7160           0 :         uInt nmods = aresidual.nelements()/ntaylor_p;
    7161             : 
    7162           0 :         if( (apsf.nelements()==1) && apsf[0]==String(""))
    7163           0 :           apsf.resize();
    7164           0 :         if(!interactive){
    7165           0 :           rstat = clean(String(algorithm), niter, gain,  
    7166             :                         threshold, displayprogress, 
    7167           0 :                         amodel, fixed, String(complist), amask,  
    7168           0 :                         aimage, aresidual, apsf);
    7169             :         }
    7170             :         else{
    7171           0 :           if((amask.nelements()==0) || (amask[0]==String(""))){
    7172           0 :             amask.resize(amodel.nelements());
    7173           0 :             for (uInt k=0; k < amask.nelements(); ++k){
    7174           0 :               amask[k]=amodel[k]+String(".mask");
    7175             :             }
    7176             :           }
    7177           0 :           Vector<Bool> nointerac(nmods);
    7178           0 :           nointerac.set(false);
    7179           0 :           if(fixed.nelements() != nmods){
    7180           0 :             fixed.resize(nmods);
    7181           0 :             fixed.set(false);
    7182             :           }
    7183           0 :           Bool forceReload=true;
    7184           0 :           Int nloop=0;
    7185           0 :           if(npercycle != 0)
    7186           0 :             nloop=niter/npercycle;
    7187           0 :           Int continter=0;
    7188           0 :           Int elniter=npercycle;
    7189           0 :           ostringstream oos;
    7190           0 :           threshold.print(oos);
    7191           0 :           String thresh=String(oos);
    7192           0 :           if(String(masktemplate) != String("")){
    7193           0 :             continter=interactivemask(masktemplate, amask[0], 
    7194             :                                                  elniter, nloop, thresh);
    7195             :           }
    7196             :           else {
    7197             :             // do a zero component clean to get started
    7198           0 :             rstat=clean(String(algorithm), 0, gain, 
    7199             :                   threshold, displayprogress,
    7200           0 :                   amodel, fixed, String(complist), amask,  
    7201           0 :                   aimage, aresidual, Vector<String>(0), false);
    7202             :             
    7203           0 :             for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
    7204           0 :               if(Table::isReadable(aimage[nIm]) && Table::isWritable(aresidual[nIm]) ){
    7205           0 :                 PagedImage<Float> rest(aimage[nIm]);
    7206           0 :                 PagedImage<Float> resi(aresidual[nIm]);
    7207           0 :                 copyMask(resi, rest, "mask0");
    7208           0 :               }
    7209           0 :               forceReload=forceReload || (aresidual.nelements() >1);
    7210           0 :               continter=interactivemask(aresidual[nIm], amask[nIm], 
    7211             :                                                    elniter, nloop,thresh, forceReload);
    7212           0 :               forceReload=false;
    7213           0 :               if(continter>=1)
    7214           0 :                 nointerac(nIm)=true;
    7215           0 :               if(continter==2)
    7216           0 :                 fixed(nIm)=true;
    7217             :               
    7218             :             }
    7219           0 :             if(allEQ(nointerac, true)){
    7220           0 :               elniter=niter;
    7221             :               //make it do one more loop/clean but with all niter 
    7222           0 :               nloop=1;
    7223             :             }
    7224             :           }
    7225           0 :           for (Int k=0; k < nloop; ++k){
    7226             :             
    7227           0 :             casacore::Quantity thrsh;
    7228           0 :             if(!casacore::Quantity::read(thrsh, thresh)){
    7229             :               os << LogIO::WARN << "Error interpreting threshold" 
    7230           0 :                       << LogIO::POST;
    7231           0 :               thrsh=casacore::Quantity(0, "Jy");
    7232           0 :               thresh="0.0Jy";
    7233             :             }
    7234           0 :             Vector<String> elpsf(0);
    7235             :             //Need to save psfs in interactive only once and lets do it the 
    7236             :             //first time
    7237           0 :             if(k==0)
    7238           0 :               elpsf=apsf;
    7239           0 :             if(anyEQ(fixed, false)){
    7240           0 :               rstat = clean(String(algorithm), elniter, gain, 
    7241             :                             thrsh, 
    7242             :                             displayprogress,
    7243           0 :                             amodel, fixed, String(complist), 
    7244             :                             amask,  
    7245           0 :                             aimage, aresidual, elpsf, k == 0);
    7246             :               //if clean converged... equivalent to stop
    7247           0 :               if(rstat.asBool("converged")){
    7248           0 :                 continter=2;
    7249           0 :                 fixed.set(true);
    7250             :               }
    7251           0 :               if(anyEQ(fixed, false) && anyEQ(nointerac,false)){
    7252           0 :                 Int remainloop=nloop-k-1;
    7253           0 :                 for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
    7254           0 :                   if(!nointerac(nIm)){
    7255           0 :                     continter=interactivemask(aresidual[nIm], amask[nIm],
    7256             :                                               
    7257             :                                               elniter, remainloop, 
    7258           0 :                                               thresh, (aresidual.nelements() >1));
    7259           0 :                     if(continter>=1)
    7260           0 :                       nointerac(nIm)=true;
    7261           0 :                     if(continter==2)
    7262           0 :                       fixed(nIm)=true;
    7263             :                   }
    7264             :                 }
    7265           0 :                 k=nloop-remainloop-1;
    7266           0 :                 if(allEQ(nointerac,true)){
    7267           0 :                   elniter=niter-(k+1)*npercycle;
    7268             :                   //make it do one more loop/clean but with remaining niter 
    7269           0 :                   k=nloop-2;
    7270             :                 }
    7271             :               } 
    7272             :             }
    7273           0 :           }
    7274             :           //Unset the mask in the residual 
    7275             :           // Cause as requested in CAS-1768...
    7276           0 :           for (uInt nIm=0; nIm < aresidual.nelements(); ++nIm){
    7277           0 :             if(Table::isWritable(aresidual[nIm]) ){
    7278           0 :               PagedImage<Float> resi(aresidual[nIm]);
    7279           0 :               if(resi.hasRegion("mask0", RegionHandler::Masks)){
    7280           0 :                 resi.setDefaultMask("");
    7281             :               }
    7282           0 :             }
    7283             :           }
    7284             :           
    7285           0 :         }
    7286             : 
    7287           0 :         os << "Restoring Image(s) with the clean-beam" << LogIO::POST;
    7288           0 :         restoreImages(aimage, (niter>=0) );
    7289           0 :         this->writeHistory(os);
    7290             :         try{
    7291             :           // write data processing history into image logtable
    7292           0 :           LoggerHolder imagelog (false);
    7293           0 :           LogSink& sink = imagelog.sink();
    7294           0 :           LogOrigin lor( String("imager"), String("clean()") );
    7295           0 :           LogMessage msg(lor);
    7296           0 :           sink.postLocally(msg);
    7297           0 :           MSHistoryColumns msHis(ms_p->history());
    7298           0 :           transferHistory(imagelog, msHis);
    7299           0 :           for (Int thismodel=0;thismodel<Int(aimage.nelements());++thismodel) {
    7300           0 :             if(Table::isWritable(aimage(thismodel))){
    7301           0 :               PagedImage<Float> restoredImage(aimage(thismodel),
    7302           0 :                                               TableLock(TableLock::AutoNoReadLocking));
    7303           0 :               LoggerHolder& log = restoredImage.logger();
    7304           0 :               log.append(imagelog);
    7305           0 :               log.flush();
    7306           0 :               restoredImage.table().relinquishAutoLocks(true);
    7307           0 :             }
    7308             :           }
    7309           0 :         }
    7310           0 :         catch(exception& x){
    7311             :       
    7312           0 :           this->unlock();
    7313           0 :           destroySkyEquation();
    7314           0 :           os << LogIO::WARN << "Caught exception: " << x.what()
    7315           0 :              << LogIO::POST;
    7316             :           os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted;  you may consider deleting all the rows from this table"
    7317           0 :              <<LogIO::POST; 
    7318             :           //continue and wrap up this function
    7319             :           
    7320           0 :         }
    7321           0 :         catch(...){
    7322           0 :           this->unlock();
    7323           0 :           destroySkyEquation();
    7324           0 :           os << LogIO::WARN << "Caught unknown exception" <<  LogIO::POST;
    7325             :           os << LogIO::SEVERE << "The MS/HISTORY table may be corrupted;  you may consider deleting all the rows from this table"
    7326           0 :              <<LogIO::POST;
    7327             :           
    7328           0 :         }
    7329             : 
    7330             : 
    7331           0 :        } //catch  (AipsError x) {
    7332             :        //os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
    7333             :        //       RETHROW(x);
    7334             :        //  }
    7335             :     } else {
    7336           0 :       os << LogIO::SEVERE << "No MeasurementSet has been assigned, please run open." << LogIO::POST;
    7337             :     }
    7338           0 :     return rstat;
    7339           0 :   }
    7340             : 
    7341           0 : Bool Imager::adviseChanSelex(Double& freqStart, Double& freqEnd, 
    7342             :                        const Double& freqStep,  const MFrequency::Types& freqframe,
    7343             :                        Vector< Vector<Int> >& spw, Vector< Vector<Int> >& start,
    7344             :                              Vector< Vector<Int> >& nchan, const String& ms, const Int field_id, const Bool getFreqRange, const String spwselection){
    7345             : 
    7346           0 :   LogIO os(LogOrigin("imager", "adviseChanSelex"));
    7347           0 :   if(ms==String("")){
    7348           0 :     if(numMS_p < 1 || !rvi_p){
    7349             :       os << LogIO::SEVERE << "Data selection incomplete" 
    7350           0 :          << LogIO::POST;
    7351           0 :       return false;
    7352             :     }
    7353             :   }
    7354           0 :   spw.resize();
    7355           0 :   start.resize();
    7356           0 :   nchan.resize();
    7357             :   try {
    7358           0 :     if(!getFreqRange){
    7359           0 :       Block<Vector<Int> > bnchan;
    7360           0 :       Block<Vector<Int> > bstart;
    7361           0 :       Block<Vector<Int> > bspw;
    7362             :       Double fS, fE;
    7363           0 :       fS=freqStart;
    7364           0 :       fE=freqEnd;
    7365           0 :       if(freqEnd < freqStart){
    7366           0 :         fS=freqEnd;
    7367           0 :         fE=freqStart;
    7368             :       }
    7369             :     
    7370           0 :       if(ms==String("")){
    7371           0 :         rvi_p->getSpwInFreqRange(bspw, bstart, bnchan, fS, fE, fabs(freqStep), freqframe);
    7372             :       }
    7373             :       else{
    7374           0 :         bnchan.resize(1);
    7375           0 :         bstart.resize(1);
    7376           0 :         bspw.resize(1);
    7377           0 :         MeasurementSet elms(String(ms), TableLock(TableLock::AutoNoReadLocking), Table::Old);
    7378           0 :         MSUtil::getSpwInFreqRange(bspw[0], bstart[0], bnchan[0], elms, fS, fE, fabs(freqStep), freqframe, field_id);
    7379           0 :         elms.relinquishAutoLocks(true);
    7380             : 
    7381           0 :       }
    7382           0 :       spw=Vector<Vector<Int> >(bspw.begin( ), bspw.end( ));
    7383           0 :       start=Vector<Vector<Int> >(bstart.begin( ), bstart.end( ));
    7384           0 :       nchan=Vector<Vector<Int> >(bnchan.begin( ), bnchan.end( ));
    7385           0 :     }
    7386             :     else{
    7387           0 :       if(ms==String("")){
    7388           0 :         rvi_p->getFreqInSpwRange(freqStart, freqEnd, freqframe);
    7389             :       }
    7390             :       else{
    7391           0 :         MeasurementSet elms(ms, TableLock(TableLock::AutoNoReadLocking), Table::Old);
    7392           0 :         MSSelection thisSelection;
    7393           0 :         String spsel=spwselection;
    7394           0 :         if(spsel=="")spsel="*";
    7395           0 :         thisSelection.setSpwExpr(spsel);
    7396           0 :         TableExprNode exprNode=thisSelection.toTableExprNode(&elms);
    7397           0 :         Matrix<Int> chanlist=thisSelection.getChanList();
    7398           0 :         if(chanlist.ncolumn() <3){
    7399           0 :           freqStart=-1.0;
    7400           0 :           freqEnd=-1.0;
    7401           0 :           return false;
    7402             :         }
    7403           0 :         Vector<Int> elspw=chanlist.column(0);
    7404           0 :         Vector<Int> elstart=chanlist.column(1);
    7405           0 :         Vector<Int> elnchan=Vector<Int> (chanlist.column(2)-elstart)+1;
    7406           0 :         MSUtil::getFreqRangeInSpw(freqStart, freqEnd, elspw, elstart, elnchan, elms, freqframe, field_id);
    7407           0 :       }
    7408             : 
    7409             :     }
    7410             : 
    7411             : 
    7412             : 
    7413             :         
    7414           0 :   } catch (AipsError x) {
    7415             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    7416           0 :        << LogIO::POST;
    7417           0 :     return false;
    7418           0 :   } 
    7419           0 :   catch (...){
    7420             :     os << LogIO::SEVERE << "Unknown  exception handled" 
    7421           0 :        << LogIO::POST;
    7422           0 :     return false;
    7423             : 
    7424           0 :   }
    7425             : 
    7426           0 :   return true;
    7427             : 
    7428           0 : }
    7429             : 
    7430             : 
    7431             : 
    7432             : } //# NAMESPACE CASA - END
    7433             : 

Generated by: LCOV version 1.16