LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - Imager2.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 879 2431 36.2 %
Date: 2024-11-06 17:42:47 Functions: 34 61 55.7 %

          Line data    Source code
       1             : // -*- C++ -*-
       2             : //# Imager.cc: Implementation of Imager.h 
       3             : //# All helper functions of imager moved here for readability 
       4             : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
       5             : //# Associated Universities, Inc. Washington DC, USA.
       6             : //#
       7             : //# This library is free software; you can redistribute it and/or modify it
       8             : //# under the terms of the GNU Library General Public License as published by
       9             : //# the Free Software Foundation; either version 2 of the License, or (at your
      10             : //# option) any later version.
      11             : //#
      12             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      13             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      15             : //# License for more details.
      16             : //#
      17             : //# You should have received a copy of the GNU Library General Public License
      18             : //# along with this library; if not, write to the Free Software Foundation,
      19             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      20             : //#
      21             : //# Correspondence concerning AIPS++ should be addressed as follows:
      22             : //#        Internet email: casa-feedback@nrao.edu.
      23             : //#        Postal address: AIPS++ Project Office
      24             : //#                        National Radio Astronomy Observatory
      25             : //#                        520 Edgemont Road
      26             : //#                        Charlottesville, VA 22903-2475 USA
      27             : //#
      28             : //# $Id$
      29             : 
      30             : 
      31             : #include <casacore/casa/Exceptions/Error.h>
      32             : #include <iostream>
      33             : #include <synthesis/MeasurementEquations/Imager.h>
      34             : #include <synthesis/MeasurementComponents/EPJones.h>
      35             : #include <synthesis/TransformMachines/VisModelData.h>
      36             : 
      37             : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
      38             : 
      39             : #include <casacore/casa/Arrays/Matrix.h>
      40             : #include <casacore/casa/Arrays/ArrayMath.h>
      41             : #include <casacore/casa/Arrays/ArrayLogical.h>
      42             : 
      43             : #include <casacore/casa/Logging.h>
      44             : #include <casacore/casa/Logging/LogIO.h>
      45             : #include <casacore/casa/Logging/LogMessage.h>
      46             : 
      47             : #include <casacore/casa/OS/DirectoryIterator.h>
      48             : #include <casacore/casa/OS/File.h>
      49             : #include <casacore/casa/OS/Path.h>
      50             : 
      51             : #include <casacore/casa/OS/HostInfo.h>
      52             : #include <casacore/tables/Tables/RefRows.h>
      53             : #include <casacore/tables/Tables/Table.h>
      54             : #include <casacore/tables/Tables/SetupNewTab.h>
      55             : #include <casacore/tables/TaQL/TableParse.h>
      56             : #include <casacore/tables/Tables/TableRecord.h>
      57             : #include <casacore/tables/Tables/TableDesc.h>
      58             : #include <casacore/tables/Tables/TableLock.h>
      59             : #include <casacore/tables/TaQL/ExprNode.h>
      60             : 
      61             : #include <casacore/casa/BasicSL/String.h>
      62             : #include <casacore/casa/Utilities/Assert.h>
      63             : #include <casacore/casa/Utilities/Fallible.h>
      64             : #include <casacore/casa/Utilities/CompositeNumber.h>
      65             : 
      66             : #include <casacore/casa/BasicSL/Constants.h>
      67             : 
      68             : #include <casacore/casa/Logging/LogSink.h>
      69             : #include <casacore/casa/Logging/LogMessage.h>
      70             : 
      71             : #include <casacore/casa/Arrays/ArrayMath.h>
      72             : #include <casacore/casa/Arrays/Slice.h>
      73             : #include <casacore/images/Images/ImageExpr.h>
      74             : #include <imageanalysis/ImageAnalysis/ImagePolarimetry.h>
      75             : #include <imageanalysis/Images/ComponentListImage.h>
      76             : #include <casacore/images/Images/ImageBeamSet.h>
      77             : #include <synthesis/MeasurementEquations/ClarkCleanProgress.h>
      78             : #include <casacore/lattices/LatticeMath/LatticeCleanProgress.h>
      79             : #include <msvis/MSVis/VisSet.h>
      80             : #include <msvis/MSVis/VisSetUtil.h>
      81             : #include <msvis/MSVis/VisImagingWeight.h>
      82             : #include <msvis/MSVis/SubMS.h>
      83             : // Disabling Imager::correct() (gmoellen 06Nov20)
      84             : //#include <synthesis/MeasurementComponents/TimeVarVisJones.h>
      85             : 
      86             : #include <casacore/measures/Measures/Stokes.h>
      87             : #include <casacore/casa/Quanta/UnitMap.h>
      88             : #include <casacore/casa/Quanta/UnitVal.h>
      89             : #include <casacore/casa/Quanta/MVAngle.h>
      90             : #include <casacore/measures/Measures/MDirection.h>
      91             : #include <casacore/measures/Measures/MPosition.h>
      92             : #include <casacore/casa/Quanta/MVEpoch.h>
      93             : #include <casacore/casa/Quanta/MVTime.h>
      94             : #include <casacore/measures/Measures/MEpoch.h>
      95             : #include <casacore/measures/Measures/MeasTable.h>
      96             : #include <casacore/measures/Measures/MeasFrame.h>
      97             : 
      98             : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
      99             : #include <casacore/ms/MeasurementSets/MSColumns.h>
     100             : #include <casacore/ms/MSSel/MSSelection.h>
     101             : #include <casacore/ms/MSSel/MSDataDescIndex.h>
     102             : #include <casacore/ms/MeasurementSets/MSDopplerUtil.h>
     103             : #include <casacore/ms/MSSel/MSSourceIndex.h>
     104             : #include <casacore/ms/MSOper/MSSummary.h>
     105             : #include <synthesis/MeasurementEquations/CubeSkyEquation.h>
     106             : // Disabling Imager::correct() (gmoellen 06Nov20)
     107             : //#include <synthesis/MeasurementEquations/VisEquation.h>
     108             : #include <synthesis/MeasurementComponents/ImageSkyModel.h>
     109             : #include <synthesis/MeasurementComponents/CEMemImageSkyModel.h>
     110             : #include <synthesis/MeasurementComponents/MFCEMemImageSkyModel.h>
     111             : #include <synthesis/MeasurementComponents/MFCleanImageSkyModel.h>
     112             : #include <synthesis/MeasurementComponents/CSCleanImageSkyModel.h>
     113             : #include <synthesis/MeasurementComponents/MFMSCleanImageSkyModel.h>
     114             : #include <synthesis/MeasurementComponents/HogbomCleanImageSkyModel.h>
     115             : #include <synthesis/MeasurementComponents/MSCleanImageSkyModel.h>
     116             : #include <synthesis/MeasurementComponents/NNLSImageSkyModel.h>
     117             : #include <synthesis/MeasurementComponents/WBCleanImageSkyModel.h>
     118             : #include <synthesis/MeasurementComponents/MultiThreadedVisResampler.h>
     119             : #include <synthesis/MeasurementComponents/GridBoth.h>
     120             : #include <synthesis/TransformMachines/rGridFT.h>
     121             : #include <synthesis/TransformMachines/SetJyGridFT.h>
     122             : #include <synthesis/TransformMachines/MosaicFT.h>
     123             : #include <synthesis/TransformMachines/WProjectFT.h>
     124             : #include <synthesis/MeasurementComponents/nPBWProjectFT.h>
     125             : #include <synthesis/MeasurementComponents/PBMosaicFT.h>
     126             : #include <synthesis/TransformMachines/PBMath.h>
     127             : #include <synthesis/TransformMachines/SimpleComponentFTMachine.h>
     128             : #include <synthesis/TransformMachines/SimpCompGridMachine.h>
     129             : #include <synthesis/TransformMachines/VPSkyJones.h>
     130             : #include <synthesis/TransformMachines/SynthesisError.h>
     131             : #include <synthesis/TransformMachines/HetArrayConvFunc.h>
     132             : #include <synthesis/TransformMachines/VisibilityResamplerBase.h>
     133             : 
     134             : #include <synthesis/DataSampling/SynDataSampling.h>
     135             : #include <synthesis/DataSampling/SDDataSampling.h>
     136             : #include <synthesis/DataSampling/ImageDataSampling.h>
     137             : 
     138             : #include <synthesis/TransformMachines/StokesImageUtil.h>
     139             : #include <casacore/lattices/LRegions/LattRegionHolder.h>
     140             : #include <casacore/lattices/Lattices/TiledLineStepper.h> 
     141             : #include <casacore/lattices/Lattices/LatticeIterator.h> 
     142             : #include <casacore/lattices/LEL/LatticeExpr.h> 
     143             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
     144             : #include <casacore/lattices/LRegions/LCEllipsoid.h>
     145             : #include <casacore/lattices/LRegions/LCRegion.h>
     146             : #include <casacore/lattices/LRegions/LCBox.h>
     147             : #include <casacore/lattices/LRegions/LCIntersection.h>
     148             : #include <casacore/lattices/LRegions/LCUnion.h>
     149             : #include <casacore/lattices/LRegions/LCExtension.h>
     150             : 
     151             : #include <casacore/images/Images/ImageRegrid.h>
     152             : #include <casacore/images/Regions/ImageRegion.h>
     153             : #include <casacore/images/Regions/RegionManager.h>
     154             : #include <casacore/images/Regions/WCBox.h>
     155             : #include <casacore/images/Regions/WCUnion.h>
     156             : #include <casacore/images/Regions/WCIntersection.h>
     157             : #include <synthesis/TransformMachines/PBMath.h>
     158             : #include <casacore/images/Images/PagedImage.h>
     159             : #include <casacore/images/Images/ImageInfo.h>
     160             : #include <casacore/images/Images/SubImage.h>
     161             : #include <casacore/images/Images/ImageUtilities.h>
     162             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
     163             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
     164             : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
     165             : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
     166             : #include <casacore/coordinates/Coordinates/Projection.h>
     167             : #include <casacore/coordinates/Coordinates/ObsInfo.h>
     168             : 
     169             : #include <components/ComponentModels/ComponentList.h>
     170             : #include <components/ComponentModels/ConstantSpectrum.h>
     171             : #include <components/ComponentModels/TabularSpectrum.h>
     172             : #include <components/ComponentModels/Flux.h>
     173             : #include <components/ComponentModels/FluxStandard.h>
     174             : #include <components/ComponentModels/PointShape.h>
     175             : #include <components/ComponentModels/DiskShape.h>
     176             : 
     177             : #include <casacore/casa/OS/HostInfo.h>
     178             : 
     179             : #include <components/ComponentModels/ComponentList.h>
     180             : 
     181             : #include <casacore/measures/Measures/UVWMachine.h>
     182             : 
     183             : #include <sstream>
     184             : 
     185             : #include <sys/types.h>
     186             : #include <unistd.h>
     187             : #include <limits>
     188             : 
     189             : #include <synthesis/TransformMachines/AWProjectFT.h>
     190             : #include <synthesis/TransformMachines/AWProjectWBFT.h>
     191             : #include <synthesis/TransformMachines/MultiTermFT.h>
     192             : #include <synthesis/TransformMachines/NewMultiTermFT.h>
     193             : #include <synthesis/TransformMachines/AWConvFunc.h>
     194             : //#include <synthesis/TransformMachines/AWConvFuncEPJones.h>
     195             : #include <synthesis/TransformMachines/NoOpATerm.h>
     196             : 
     197             : #include <synthesis/Utilities/PointingDirectionCalculator.h>
     198             : #include <synthesis/Utilities/SingleDishBeamUtil.h>
     199             : 
     200             : using namespace std;
     201             : 
     202             : using namespace casacore;
     203             : namespace casa { //# NAMESPACE CASA - BEGIN
     204             : 
     205           0 : String Imager::imageName()
     206             : {
     207           0 :   LogIO os(LogOrigin("imager", "imageName()", WHERE));
     208             :   try {
     209           0 :     lock();
     210           0 :     String name(msname_p);
     211           0 :     MSColumns msc(*ms_p);
     212           0 :     if(datafieldids_p.shape() !=0) {
     213           0 :       name=msc.field().name()(datafieldids_p(0));
     214             :     }
     215           0 :     else if(fieldid_p > -1) {
     216           0 :        name=msc.field().name()(fieldid_p);
     217             :     }
     218           0 :     unlock();
     219           0 :     return name;
     220           0 :   } catch (AipsError x) {
     221           0 :     unlock();
     222           0 :     os << LogIO::SEVERE << "Caught Exception: "<< x.getMesg() << LogIO::EXCEPTION; 
     223           0 :     return "";
     224           0 :   } 
     225             :   return String("imagerImage");
     226           0 : }
     227             : 
     228             : // imagecoordinates2 (use subMS method to get freq vectors)
     229             : // Make standard choices for coordinates
     230         770 : Bool Imager::imagecoordinates2(CoordinateSystem& coordInfo, const Bool verbose) 
     231             : {  
     232         770 :   if(!valid()) return false;
     233         770 :   if(!assertDefinedImageParameters()) return false;
     234        1540 :   LogIO os(LogOrigin("Imager", "imagecoordinates()", WHERE));
     235             :   
     236             :   //===Adjust for some setimage defaults if imageNchan=-1 and spwids=-1
     237         770 :   if(imageNchan_p <=0){
     238          69 :     imageNchan_p=1;
     239             :   }
     240         770 :   if(spectralwindowids_p.nelements()==1){
     241         685 :     if(spectralwindowids_p[0]<0){
     242         122 :       spectralwindowids_p.resize();
     243         122 :       if(dataspectralwindowids_p.nelements()==0){
     244           0 :          Int nspwinms=ms_p->spectralWindow().nrow();
     245           0 :          dataspectralwindowids_p.resize(nspwinms);
     246           0 :          indgen(dataspectralwindowids_p);
     247             :       }
     248         122 :       spectralwindowids_p=dataspectralwindowids_p;
     249             :     }
     250             :     
     251             :   }
     252         770 :   if(fieldid_p < 0){
     253         125 :      if(datafieldids_p.shape() !=0) {
     254         125 :        fieldid_p=datafieldids_p[0];
     255             :      }
     256             :      else{
     257           0 :        fieldid_p=0; //best default if nothing is specified
     258             :      }
     259             :   }
     260             :   //===end of default
     261         770 :   Vector<Double> deltas(2);
     262         770 :   deltas(0)=-mcellx_p.get("rad").getValue();
     263         770 :   deltas(1)=mcelly_p.get("rad").getValue();
     264             :   
     265             :   //MSColumns msc(*ms_p);
     266         770 :   MSColumns msc(*mssel_p); // CAS-11503
     267         770 :   MFrequency::Types obsFreqRef=MFrequency::DEFAULT;
     268         770 :   ScalarColumn<Int> measFreqRef(ms_p->spectralWindow(),
     269        1540 :                                   MSSpectralWindow::columnName(MSSpectralWindow::MEAS_FREQ_REF));
     270             :   //using the first frame of reference; TO DO should do the right thing 
     271             :   //for different frames selected. 
     272             :   //Int eh = spectralwindowids_p(0);
     273         770 :   if(spectralwindowids_p.size() && measFreqRef(spectralwindowids_p(0)) >=0) {
     274         770 :      obsFreqRef=(MFrequency::Types)measFreqRef(spectralwindowids_p(0));
     275             :   }
     276             :                             
     277             : 
     278         770 :   MVDirection mvPhaseCenter(phaseCenter_p.getAngle());
     279             :   // Normalize correctly
     280         770 :   MVAngle ra=mvPhaseCenter.get()(0);
     281         770 :   ra(0.0);
     282         770 :   MVAngle dec=mvPhaseCenter.get()(1);
     283         770 :   Vector<Double> refCoord(2);
     284         770 :   refCoord(0)=ra.get().getValue();    
     285         770 :   refCoord(1)=dec;    
     286             :   
     287         770 :   Vector<Double> refPixel(2); 
     288         770 :   refPixel(0) = Double(nx_p / 2);
     289         770 :   refPixel(1) = Double(ny_p / 2);
     290             :   
     291             :   //defining observatory...needed for position on earth
     292         770 :   String telescop = msc.observation().telescopeName()(0);
     293             : 
     294             :   // defining epoch as begining time from timerange in OBSERVATION subtable
     295             :   // Using first observation for now
     296             :   //MEpoch obsEpoch = msc.observation().timeRangeMeas()(0)(IPosition(1,0));
     297             :   // modified to use main table's TIME column for better match with what
     298             :   // VisIter does.
     299         770 :   MEpoch obsEpoch = msc.timeMeas()(0);
     300             : 
     301             :   //Now finding the position of the telescope on Earth...needed for proper
     302             :   //frequency conversions
     303             : 
     304         770 :   MPosition obsPosition;
     305         770 :   if(nonDefaultLocation()) {
     306             :     os << LogIO::DEBUG1 << "Using user defined location: "
     307        1244 :        << mLocation_p.getRefString() << " " << mLocation_p.get("m")
     308        1244 :        << LogIO::POST;
     309         622 :     obsPosition = mLocation_p;
     310         622 :     freqFrameValid_p = true;
     311         148 :   } else if(!(MeasTable::Observatory(obsPosition, telescop))){
     312             :     os << LogIO::WARN << "Did not get the position of " << telescop 
     313           0 :        << " from data repository" << LogIO::POST;
     314             :     os << LogIO::WARN 
     315             :        << "Please contact CASA to add it to the repository."
     316           0 :        << LogIO::POST;
     317           0 :     os << LogIO::WARN << "Frequency conversion will not work " << LogIO::POST;
     318           0 :     freqFrameValid_p = false;
     319             :   }
     320             :   else{
     321         148 :     mLocation_p = obsPosition;
     322         148 :     freqFrameValid_p = true;
     323             :     os << LogIO::DEBUG1 << "Using observatory location of "
     324         148 :        << telescop << ": " << mLocation_p.getRefString()
     325         148 :        << " " << mLocation_p.get("m") << LogIO::POST;
     326             :   }
     327             :    //Make sure frame conversion is switched off for REST frame data.
     328         770 :   freqFrameValid_p=freqFrameValid_p && (obsFreqRef !=MFrequency::REST);
     329             : 
     330             :   // Now find the projection to use: could probably also use
     331             :   // max(abs(w))=0.0 as a criterion
     332         770 :   Projection::Type ptype = Projection::type(projection_p);
     333         770 :   Projection projection(ptype);
     334         770 :   if(ptype == Projection::SIN
     335         770 :       && (telescop == "ATCASCP" || telescop == "WSRT" || telescop == "DRAO")) {
     336             :     os << LogIO::NORMAL // Loglevel NORMAL
     337             :        << "Using SIN image projection adjusted for "
     338           0 :        << (telescop == "ATCASCP" ? 'S' : 'N') << "CP" 
     339           0 :        << LogIO::POST;
     340           0 :     Vector<Double> projectionParameters(2);
     341           0 :     projectionParameters(0) = 0.0;
     342           0 :     if(sin(dec) != 0.0){
     343           0 :       projectionParameters(1) = cos(dec)/sin(dec);
     344           0 :       projection=Projection(Projection::SIN, projectionParameters);
     345             :     }
     346             :     else {
     347             :       os << LogIO::WARN
     348             :          << "Singular projection for " << telescop << ": using plain SIN"
     349           0 :          << LogIO::POST;
     350           0 :       projection=Projection(Projection::SIN);
     351             :     }
     352           0 :   }
     353             :   else {
     354         770 :     os << LogIO::DEBUGGING << "Using " << projection_p << " image projection" << LogIO::POST;
     355             :   }
     356         770 :   os << LogIO::NORMAL;
     357             :   
     358         770 :   Matrix<Double> xform(2,2);
     359         770 :   xform=0.0;xform.diagonal()=1.0;
     360             :   DirectionCoordinate
     361         770 :     myRaDec(MDirection::Types(phaseCenter_p.getRefPtr()->getType()),
     362             :             projection,
     363        2310 :             refCoord(0), refCoord(1),
     364        2310 :             deltas(0), deltas(1),
     365             :             xform,
     366        1540 :             refPixel(0), refPixel(1));
     367             :   
     368             :   // Now set up spectral coordinate
     369         770 :   SpectralCoordinate* mySpectral=0;
     370         770 :   Double refChan=0.0;
     371             :   
     372             :   // Spectral synthesis
     373             :   // For mfs band we set the window to include all spectral windows
     374         770 :   Int nspw=spectralwindowids_p.nelements();
     375         770 :   if (imageMode_p=="MFS") {
     376          14 :     Double fmin=C::dbl_max;
     377          14 :     Double fmax=-(C::dbl_max);
     378          14 :     Double fmean=0.0;
     379             :     /*
     380             :     Int nms = freqrange_p.shape()(0);
     381             :     for (Int i=0;i<nspw;++i) {
     382             :       Int spw=spectralwindowids_p(i);
     383             :       Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spw); 
     384             :       Vector<Double> freqResolution = msc.spectralWindow().chanWidth()(spw); 
     385             :       
     386             :       if(dataMode_p=="none"){
     387             :       
     388             :         if(nms >1) {
     389             :           for (Int j=0; j<nms; ++j) {
     390             :             fmin=min(fmin,freqrange_p(j,0)); 
     391             :             fmax=max(fmax,freqrange_p(j,1)); 
     392             :           }
     393             :         }
     394             :         else if(i==0) {
     395             :           fmin=min(chanFreq-abs(0.5*freqResolution));
     396             :           fmax=max(chanFreq+abs(0.5*freqResolution));
     397             :         }
     398             :         else {
     399             :           fmin=min(fmin,min(chanFreq-abs(0.5*freqResolution)));
     400             :           fmax=max(fmax,max(chanFreq+abs(0.5*freqResolution)));
     401             :         }
     402             :       }
     403             :       else if(dataMode_p=="channel"){
     404             :         // This needs some careful thought about roundoff - it is likely 
     405             :         // still adding an extra half-channel at top and bottom but 
     406             :         // if the freqResolution is nonlinear, there are subtleties
     407             :         // multiple MS case
     408             :         if(nms >1) {
     409             :           for (Int j=0; j<nms; ++j) {
     410             :             fmin=min(fmin,freqrange_p(j,0)); 
     411             :             fmax=max(fmax,freqrange_p(j,1)); 
     412             :           }
     413             :         }
     414             :         // single ms case
     415             :         else {
     416             :           Int elnchan=chanFreq.nelements();
     417             :           Int firstchan=0;
     418             :           Int elstep=1;
     419             :           for (uInt jj=0; jj < dataspectralwindowids_p.nelements(); ++jj){
     420             :             if(dataspectralwindowids_p[jj]==spw){
     421             :               firstchan=dataStart_p[jj];
     422             :               elnchan=dataNchan_p[jj];
     423             :               elstep=dataStep_p[jj];
     424             :             }   
     425             :           }
     426             :           Int lastchan=firstchan+ elnchan*elstep;
     427             :           for(Int k=firstchan ; k < lastchan ;  k+=elstep){
     428             :             fmin=min(fmin,chanFreq[k]-abs(freqResolution[k]*(elstep-0.5)));
     429             :             fmax=max(fmax,chanFreq[k]+abs(freqResolution[k]*(elstep-0.5)));
     430             :           }
     431             :         }
     432             :       }
     433             :       else{
     434             :         this->unlock();
     435             :         os << LogIO::SEVERE 
     436             :            << "setdata has to be in 'channel' or 'none' mode for 'mfs' imaging to work"
     437             :            << LogIO::EXCEPTION;
     438             :       return false;
     439             :       }
     440             :  
     441             :     }
     442             : 
     443             :     */
     444          14 :     rvi_p->getFreqInSpwRange(fmin, fmax, freqFrameValid_p ? MFrequency::LSRK : freqFrame_p);
     445             :     
     446             : 
     447          14 :     fmean=(fmax+fmin)/2.0;
     448          14 :     Vector<Double> restFreqArray;
     449          14 :     Double restFreq=fmean;
     450          14 :     if(getRestFreq(restFreqArray, spectralwindowids_p(0))){
     451          14 :       restFreq=restFreqArray[0];
     452             :     }
     453          14 :     imageNchan_p=1;
     454          14 :     Double finc=(fmax-fmin); 
     455          28 :     mySpectral = new SpectralCoordinate(freqFrameValid_p ? MFrequency::LSRK : freqFrame_p,  fmean//-finc/2.0
     456             :                                         , finc,
     457          14 :                                         refChan, restFreq);
     458             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
     459             :        << "Center frequency = "
     460          28 :        << MFrequency(Quantity(fmean, "Hz")).get("GHz").getValue()
     461             :        << " GHz, synthesized continuum bandwidth = "
     462          28 :        << MFrequency(Quantity(finc, "Hz")).get("GHz").getValue()
     463          42 :        << " GHz" << LogIO::POST;
     464             : 
     465          14 :     if(ntaylor_p>1 && reffreq_p==0.0) 
     466             :     {
     467           0 :             reffreq_p = fmean;
     468           0 :             os << "Setting center frequency as MS-MFS reference frequency" << LogIO::POST;
     469             :     }
     470          14 :   }
     471             :   
     472         756 :   else if(imageMode_p.contains("FREQ")) {
     473          24 :       if(imageNchan_p==0) {
     474           0 :         this->unlock();
     475             :         os << LogIO::SEVERE << "Must specify number of channels" 
     476           0 :            << LogIO::EXCEPTION;
     477           0 :         return false;
     478             :       }
     479          24 :       Double restFreq=mfImageStart_p.get("Hz").getValue();
     480          24 :       Vector<Double> restFreqVec;
     481          24 :       if(getRestFreq(restFreqVec, spectralwindowids_p(0))){
     482          24 :         restFreq=restFreqVec[0];
     483             :       }
     484          24 :       MFrequency::Types mfreqref=(obsFreqRef==(MFrequency::REST)) ? MFrequency::REST : MFrequency::castType(mfImageStart_p.getRef().getType()) ; 
     485             : 
     486             :       /////Some problem here it is really goofing up in getting frequency
     487             :       // -> fixed was made in calcImFreqs -TT 
     488          24 :       Vector<Double> imgridfreqs;
     489          24 :       Vector<Double> imfreqres;
     490             :       //rstate=calcImFreqs(imgridfreqs, imfreqres, mfreqref, obsEpoch, obsPosition,restFreq);
     491             :       // should use obsFreqRef
     492             : 
     493          24 :       if (!calcImFreqs(imgridfreqs, imfreqres, obsFreqRef, obsEpoch, mLocation_p ,restFreq)) {
     494           0 :          return false;
     495             :       }
     496             :       //cerr<<"imfreqres(0)="<<imfreqres(0)<<endl;
     497             :       
     498             : 
     499          24 :       if (imageNchan_p==1) {
     500           6 :         mySpectral = new SpectralCoordinate(mfreqref,
     501          12 :                                             mfImageStart_p.get("Hz").getValue(),
     502          12 :                                             mfImageStep_p.get("Hz").getValue(),
     503           6 :                                             refChan, restFreq);
     504             :       }
     505             :       else {
     506          18 :         Double finc= imgridfreqs(1)-imgridfreqs(0);
     507          18 :         mySpectral = new SpectralCoordinate(mfreqref, imgridfreqs(0), finc, refChan, restFreq);
     508             :         //cerr << "after myspectral2 " << mySpectral->referenceValue() << " pixel " <<  mySpectral->referencePixel() << endl;
     509             :         //debug TT
     510             :         //Double wrld,pixl;
     511             :         //pixl=0.0;
     512             :         //mySpectral->toWorld(wrld,pixl);
     513             :         //cerr<<"world="<<wrld<<" pixel="<<pixl;
     514             :       }
     515             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     516             :          << "Start frequency = " // Loglevel INFO
     517          48 :          << mfImageStart_p.get("GHz").getValue()
     518             :          << ", channel increment = "
     519          48 :          << mfImageStep_p.get("GHz").getValue() 
     520             :          << "GHz, frequency frame = "
     521             :          << MFrequency::showType(mfreqref)
     522          72 :          << endl;
     523             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     524             :          << "Rest frequency is "  // Loglevel INFO
     525          48 :          << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
     526          48 :          << "GHz" << LogIO::POST;
     527             :       
     528          24 :   }
     529             :   
     530             : 
     531             :   else {
     532         732 :     Vector<Double> chanFreq;
     533         732 :     Vector<Double> freqResolution;
     534             :     //starting with a default rest frequency to be ref 
     535             :     //in case none is defined
     536             :     Double restFreq=
     537         732 :       msc.spectralWindow().refFrequency()(spectralwindowids_p(0));
     538             : 
     539        1632 :     for (Int spwIndex=0; spwIndex < nspw; ++spwIndex){
     540             :  
     541         900 :       Int spw=spectralwindowids_p(spwIndex);
     542             :       
     543         900 :       Vector<Double> restFreqArray;
     544         900 :       if(getRestFreq(restFreqArray, spw)){
     545         884 :         if(spwIndex==0){
     546         716 :           restFreq = restFreqArray(0);
     547             :         }
     548             :         else{
     549         168 :           if(restFreq != restFreqArray(0)){
     550             :             os << LogIO::WARN << "Rest frequencies are different for  spectralwindows selected " 
     551           0 :                << LogIO::POST;
     552             :             os << LogIO::WARN 
     553             :                <<"Will be using the restFreq defined in spectralwindow "
     554           0 :                << spectralwindowids_p(0) << LogIO::POST;
     555             :           }
     556             :           
     557             :         }       
     558             :       }
     559         900 :     }
     560             :   
     561             :     // use data frame here (for channel mode)
     562         732 :     if (!calcImFreqs(chanFreq, freqResolution, obsFreqRef, obsEpoch, mLocation_p,restFreq)) {
     563           0 :       return false;
     564             :     }
     565             : 
     566         732 :     if(imageMode_p=="CHANNEL") {
     567         714 :       if(imageNchan_p==0) {
     568           0 :         this->unlock();
     569             :         os << LogIO::SEVERE << "Must specify number of channels" 
     570           0 :            << LogIO::EXCEPTION;
     571           0 :         return false;
     572             :       }
     573         714 :       if(imageStep_p==0)
     574          12 :         imageStep_p=1;
     575             : //      TT: commented these out otherwise the case for multiple MSes would not work
     576             : //      Int nsubchans=
     577             : //      (chanFreq.shape()(0) - Int(imageStart_p)+1)/Int(imageStep_p)+1;
     578             : //      if((nsubchans >0) && (imageNchan_p>nsubchans)) imageNchan_p=nsubchans;
     579             : 
     580             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     581             :          << "Image spectral coordinate: "<< imageNchan_p
     582             :          << " channels, starting at visibility channel "
     583         714 :          << imageStart_p << " stepped by " << imageStep_p << LogIO::POST;
     584             :      
     585             :       Double finc;
     586             :       {
     587             :         // Now use outframe (instead of data frame) as the rest of
     588             :         // the modes do
     589             :         //
     590             :        
     591         714 :         finc= ((chanFreq.shape().nelements()==1) && (chanFreq.shape()[0] > 1)) ? chanFreq(1)-chanFreq(0): freqResolution[0];
     592             :         
     593         714 :         mySpectral = new SpectralCoordinate(freqFrame_p,
     594         714 :                                           chanFreq(0),
     595             :                                             finc,  
     596         714 :                                             refChan, restFreq);
     597             :       }
     598             :         
     599             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     600             :          << "Frequency = " // Loglevel INFO
     601        1428 :          << MFrequency(Quantity(chanFreq(0), "Hz")).get("GHz").getValue()
     602             :          << ", channel increment = "
     603        1428 :          << MFrequency(Quantity(finc, "Hz")).get("GHz").getValue() 
     604        2142 :          << "GHz" << endl;
     605             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     606             :          << "Rest frequency is "  // Loglevel INFO
     607        1428 :          << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
     608        1428 :          << "GHz" << LogIO::POST;
     609             :       
     610             :     }
     611             :     // Spectral channels resampled at equal increments in optical velocity
     612             :     // Here we compute just the first two channels and use increments for
     613             :     // the others
     614          18 :     else if (imageMode_p=="VELOCITY" || imageMode_p.contains("RADIO")) {
     615          18 :       if(imageNchan_p==0) {
     616           0 :         this->unlock();
     617             :         os << LogIO::SEVERE << "Must specify number of channels" 
     618           0 :            << LogIO::EXCEPTION;
     619           0 :         return false;
     620             :       }
     621             :       {
     622          18 :         ostringstream oos;
     623          18 :         oos << "Image spectral coordinate:"<< imageNchan_p 
     624          18 :             << " channels, starting at radio velocity " << mImageStart_p
     625          18 :             << "  stepped by " << mImageStep_p << endl;
     626             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     627          18 :            << String(oos); // Loglevel INFO
     628          18 :       }
     629             :      
     630          18 :       MFrequency::Types mfreqref=MFrequency::LSRK;
     631             :       //Can't convert to frame in mImageStart
     632          18 :       if(!MFrequency::getType(mfreqref, (MRadialVelocity::showType(mImageStart_p.getRef().getType()))))
     633           0 :         mfreqref=freqFrame_p;
     634          18 :       mfreqref=(obsFreqRef==(MFrequency::REST)) ? MFrequency::REST : mfreqref; 
     635             :       //rstate=calcImFreqs(chanFreq, freqResolution, mfreqref, obsEpoch, obsPosition,restFreq);
     636          18 :       if (!calcImFreqs(chanFreq, freqResolution, obsFreqRef, obsEpoch, mLocation_p, restFreq)) {
     637           0 :         return false;
     638             :       }
     639             : 
     640             : 
     641             :       Double finc;
     642          18 :       if(imageNchan_p ==1) {
     643           6 :         finc = freqResolution(0);
     644             :       }
     645             :       else {
     646          12 :         finc = chanFreq(1)-chanFreq(0);
     647             :       }
     648             :       //mySpectral = new SpectralCoordinate(obsFreqRef,
     649          18 :       mySpectral = new SpectralCoordinate(mfreqref,
     650          18 :                                           chanFreq(0),
     651             :                                           finc,  
     652          18 :                                           refChan, restFreq);
     653             :      
     654             :       {
     655          18 :         ostringstream oos;
     656          18 :         oos << "Reference Frequency = "
     657          36 :             << MFrequency(Quantity(chanFreq(0), "Hz")).get("GHz")
     658          18 :             << ", spectral increment = "
     659          36 :             << MFrequency(Quantity(finc, "Hz")).get("GHz") 
     660          18 :             << ", frequency frame = "
     661          18 :             << MFrequency::showType(mfreqref)
     662          18 :             << endl; 
     663          18 :         oos << "Rest frequency is " 
     664          36 :             << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
     665          18 :             << " GHz" << endl;
     666          18 :         os << LogIO::NORMAL << String(oos) << LogIO::POST; // Loglevel INFO
     667          18 :       }
     668             :       
     669             :     }
     670             :     // Since optical/relativistic velocity is non-linear in frequency, we have to
     671             :     // pass in all the frequencies. For radio velocity we can use 
     672             :     // a linear axis.
     673           0 :     else if (imageMode_p=="OPTICALVELOCITY" || imageMode_p.contains("OPTICAL") || imageMode_p.contains("TRUE") 
     674           0 :              || imageMode_p.contains("BETA") ||  imageMode_p.contains("RELATI") ) {
     675           0 :       if(imageNchan_p==0) {
     676           0 :         this->unlock();
     677             :         os << LogIO::SEVERE << "Must specify number of channels" 
     678           0 :            << LogIO::EXCEPTION;
     679           0 :         return false;
     680             :       }
     681             :       {
     682           0 :         ostringstream oos;
     683           0 :         oos << "Image spectral coordinate: "<< imageNchan_p 
     684           0 :             << " channels, starting at optical velocity " << mImageStart_p
     685           0 :             << "  stepped by " << mImageStep_p << endl;
     686             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     687           0 :            << String(oos); // Loglevel INFO
     688           0 :       }
     689             :       
     690             :       // Use this next line when non-linear is working
     691             :       // when selecting in velocity its specfied freqframe or REST 
     692           0 :       MFrequency::Types imfreqref=(obsFreqRef==MFrequency::REST) ? MFrequency::REST : freqFrame_p;
     693             :       //rstate=calcImFreqs(chanFreq, freqResolution, imfreqref, obsEpoch, obsPosition,restFreq);
     694           0 :       if (!calcImFreqs(chanFreq, freqResolution, obsFreqRef, obsEpoch, mLocation_p,restFreq)) {
     695           0 :          return false;
     696             :       }
     697             :   
     698           0 :       if (imageNchan_p==1) {
     699           0 :         mySpectral = new SpectralCoordinate(imfreqref,
     700           0 :                                             chanFreq(0),
     701           0 :                                             freqResolution(0),
     702           0 :                                             refChan, restFreq);
     703             :       }
     704             :       else {
     705           0 :         mySpectral = new SpectralCoordinate(imfreqref, chanFreq, restFreq);
     706             :       }
     707             : 
     708             :       {
     709           0 :         ostringstream oos;
     710           0 :         oos << "Reference Frequency = "
     711             :             //<< MFrequency(Quantity(freqs(0), "Hz")).get("GHz")
     712           0 :             << MFrequency(Quantity(chanFreq(0), "Hz")).get("GHz")
     713             :             << " Ghz, " 
     714           0 :             <<" frequency frame= "<<MFrequency::showType(imfreqref)<<endl;
     715             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
     716           0 :            << String(oos) << LogIO::POST; // Loglevel INFO
     717           0 :       }
     718             :     }
     719             :     else {
     720           0 :       this->unlock();
     721           0 :       os << LogIO::SEVERE << "Unknown mode " << imageMode_p
     722           0 :          << LogIO::EXCEPTION;
     723           0 :       return false;
     724             :     }
     725             :         
     726             :     
     727         732 :   }
     728             :  
     729             :     //In FTMachine lsrk is used for channel matching with data channel 
     730             :     //hence we make sure that
     731             :     // we convert to lsrk when dealing with the channels
     732         770 :   freqFrameValid_p=freqFrameValid_p && (obsFreqRef !=MFrequency::REST);
     733         770 :   if(freqFrameValid_p){
     734         770 :       mySpectral->setReferenceConversion(MFrequency::LSRK, obsEpoch, 
     735             :                                          obsPosition,
     736         770 :                                          phaseCenter_p);
     737             :   }
     738             : 
     739             :   // Polarization
     740         770 :   Vector<String> polType=msc.feed().polarizationType()(0);
     741         818 :   if (polType(0)!="X" && polType(0)!="Y" &&
     742         818 :       polType(0)!="R" && polType(0)!="L") {
     743             :     os << LogIO::WARN << "Unknown stokes types in feed table: ["
     744           0 :        << polType(0) << ", " << polType(1) << "]" << endl
     745           0 :        << "Results open to question!" << LogIO::POST;
     746             :   }
     747             :   
     748         770 :   if (polType(0)=="X" || polType(0)=="Y") {
     749         746 :     polRep_p=StokesImageUtil::LINEAR;
     750             :     os << LogIO::DEBUG1 
     751         746 :        << "Preferred polarization representation is linear" << LogIO::POST;
     752             :   }
     753             :   else {
     754          24 :     polRep_p=StokesImageUtil::CIRCULAR;
     755             :     os << LogIO::DEBUG1
     756          24 :        << "Preferred polarization representation is circular" << LogIO::POST;
     757             :   }
     758             : 
     759             :   // Compare user input with whatever is allowed by the data. 
     760             :   // If possible, allow.
     761             : 
     762         770 :   Vector<Int> whichStokes = decideNPolPlanes(true);
     763         770 :   if(whichStokes.nelements()==0 || (whichStokes.nelements()==1 && whichStokes[0]==0) ) 
     764             :     {
     765           0 :       if(polRep_p==StokesImageUtil::CIRCULAR) 
     766           0 :         os << LogIO::SEVERE << "Stokes selection of " << stokes_p << " is not valid for Circular feeds." << LogIO::EXCEPTION;
     767             :       else 
     768           0 :         os << LogIO::SEVERE << "Stokes selection of " << stokes_p << " is not valid for Linear feeds." << LogIO::EXCEPTION;
     769           0 :       return false;
     770             :     }
     771             :  
     772         770 :   StokesCoordinate myStokes(whichStokes);
     773             :   
     774             :   //  os << LogIO::DEBUG1 << "imagecoordinate : " << (coordInfo).stokesCoordinate((coordInfo).findCoordinate(Coordinate::STOKES)).stokes() << LogIO::POST;
     775             : 
     776             :   //Set Observatory info
     777         770 :   ObsInfo myobsinfo;
     778         770 :   myobsinfo.setTelescope(telescop);
     779         770 :   myobsinfo.setPointingCenter(mvPhaseCenter);
     780         770 :   myobsinfo.setObsDate(obsEpoch);
     781         770 :   myobsinfo.setObserver(msc.observation().observer()(0));
     782         770 :   this->setObsInfo(myobsinfo);
     783             : 
     784             :   //Adding everything to the coordsystem
     785         770 :   coordInfo.addCoordinate(myRaDec);
     786         770 :   coordInfo.addCoordinate(myStokes);
     787         770 :   coordInfo.addCoordinate(*mySpectral);
     788         770 :   coordInfo.setObsInfo(myobsinfo);
     789             : 
     790         770 :   if(mySpectral) delete mySpectral;
     791             : 
     792         770 :   return true;
     793         770 : }
     794             : 
     795             : //Return if mLocation_p is non-default MPosition
     796         770 : Bool Imager::nonDefaultLocation(){
     797         770 :   MPosition default_MPosition;
     798             :   //Check for measure reference
     799         770 :   if (mLocation_p.getRefString() != default_MPosition.getRefString())
     800         610 :     return true;
     801             :   //Check for measure value
     802         160 :   if (mLocation_p.get("m") != default_MPosition.get("m"))
     803          12 :     return true;
     804         148 :   return false;
     805         770 : }
     806             : 
     807             : 
     808             : // Make standard choices for coordinates
     809           0 : Bool Imager::imagecoordinates(CoordinateSystem& coordInfo, const Bool verbose) 
     810             : {  
     811           0 :   if(!valid()) return false;
     812           0 :   if(!assertDefinedImageParameters()) return false;
     813           0 :   LogIO os(LogOrigin("Imager", "imagecoordinates()", WHERE));
     814             :   
     815             :   //===Adjust for some setimage defaults if imageNchan=-1 and spwids=-1
     816           0 :   if(imageNchan_p <=0){
     817           0 :     imageNchan_p=1;
     818             :   }
     819           0 :   if(spectralwindowids_p.nelements()==1){
     820           0 :     if(spectralwindowids_p[0]<0){
     821           0 :       spectralwindowids_p.resize();
     822           0 :       if(dataspectralwindowids_p.nelements()==0){
     823           0 :          Int nspwinms=ms_p->spectralWindow().nrow();
     824           0 :          dataspectralwindowids_p.resize(nspwinms);
     825           0 :          indgen(dataspectralwindowids_p);
     826             :       }
     827           0 :       spectralwindowids_p=dataspectralwindowids_p;
     828             :     }
     829             :     
     830             :   }
     831           0 :   if(fieldid_p < 0){
     832           0 :      if(datafieldids_p.shape() !=0) {
     833           0 :        fieldid_p=datafieldids_p[0];
     834             :      }
     835             :      else{
     836           0 :        fieldid_p=0; //best default if nothing is specified
     837             :      }
     838             :   }
     839             :   //===end of default
     840           0 :   Vector<Double> deltas(2);
     841           0 :   deltas(0)=-mcellx_p.get("rad").getValue();
     842           0 :   deltas(1)=mcelly_p.get("rad").getValue();
     843             :   
     844           0 :   MSColumns msc(*ms_p);
     845           0 :   MFrequency::Types obsFreqRef=MFrequency::DEFAULT;
     846           0 :   ScalarColumn<Int> measFreqRef(ms_p->spectralWindow(),
     847           0 :                                   MSSpectralWindow::columnName(MSSpectralWindow::MEAS_FREQ_REF));
     848             :   //using the first frame of reference; TO DO should do the right thing 
     849             :   //for different frames selected. 
     850             :   //Int eh = spectralwindowids_p(0);
     851           0 :   if(spectralwindowids_p.size() && measFreqRef(spectralwindowids_p(0)) >=0) {
     852           0 :      obsFreqRef=(MFrequency::Types)measFreqRef(spectralwindowids_p(0));
     853             :   }
     854             :                             
     855             : 
     856           0 :   MVDirection mvPhaseCenter(phaseCenter_p.getAngle());
     857             :   // Normalize correctly
     858           0 :   MVAngle ra=mvPhaseCenter.get()(0);
     859           0 :   ra(0.0);
     860           0 :   MVAngle dec=mvPhaseCenter.get()(1);
     861           0 :   Vector<Double> refCoord(2);
     862           0 :   refCoord(0)=ra.get().getValue();    
     863           0 :   refCoord(1)=dec;    
     864             :   
     865           0 :   Vector<Double> refPixel(2); 
     866           0 :   refPixel(0) = Double(nx_p / 2);
     867           0 :   refPixel(1) = Double(ny_p / 2);
     868             :   
     869             :   //defining observatory...needed for position on earth
     870           0 :   String telescop = msc.observation().telescopeName()(0);
     871             : 
     872             :   // defining epoch as begining time from timerange in OBSERVATION subtable
     873             :   // Using first observation for now
     874             :   //MEpoch obsEpoch = msc.observation().timeRangeMeas()(0)(IPosition(1,0));
     875             :   // modified to use main table's TIME column for better match with what
     876             :   // VisIter does.
     877           0 :   MEpoch obsEpoch = msc.timeMeas()(0);
     878             : 
     879             :   //Now finding the position of the telescope on Earth...needed for proper
     880             :   //frequency conversions
     881             : 
     882           0 :   MPosition obsPosition;
     883           0 :   if(nonDefaultLocation()) {
     884           0 :     freqFrameValid_p = true;
     885           0 :   } else if(!(MeasTable::Observatory(obsPosition, telescop))){
     886             :     os << LogIO::WARN << "Did not get the position of " << telescop 
     887           0 :        << " from data repository" << LogIO::POST;
     888             :     os << LogIO::WARN 
     889             :        << "Please contact CASA to add it to the repository."
     890           0 :        << LogIO::POST;
     891           0 :     os << LogIO::WARN << "Frequency conversion will not work " << LogIO::POST;
     892           0 :     freqFrameValid_p = false;
     893             :   }
     894             :   else{
     895           0 :     mLocation_p = obsPosition;
     896           0 :     freqFrameValid_p = true;
     897             :   }
     898             :   //Make sure frame conversion is switched off for REST frame data.
     899           0 :   freqFrameValid_p=freqFrameValid_p && (obsFreqRef !=MFrequency::REST);
     900             :   // Now find the projection to use: could probably also use
     901             :   // max(abs(w))=0.0 as a criterion
     902           0 :   Projection projection(Projection::SIN);
     903           0 :   if(telescop == "ATCASCP" || telescop == "WSRT" || telescop == "DRAO") {
     904             :     os << LogIO::NORMAL // Loglevel NORMAL
     905             :        << "Using SIN image projection adjusted for "
     906           0 :        << (telescop == "ATCASCP" ? 'S' : 'N') << "CP" 
     907           0 :        << LogIO::POST;
     908           0 :     Vector<Double> projectionParameters(2);
     909           0 :     projectionParameters(0) = 0.0;
     910           0 :     if(sin(dec) != 0.0){
     911           0 :       projectionParameters(1) = cos(dec)/sin(dec);
     912           0 :       projection=Projection(Projection::SIN, projectionParameters);
     913             :     }
     914             :     else {
     915             :       os << LogIO::WARN
     916             :          << "Singular projection for " << telescop << ": using plain SIN"
     917           0 :          << LogIO::POST;
     918           0 :       projection=Projection(Projection::SIN);
     919             :     }
     920           0 :   }
     921             :   else {
     922           0 :     os << LogIO::DEBUGGING << "Using SIN image projection" << LogIO::POST;
     923             :   }
     924           0 :   os << LogIO::NORMAL;
     925             :   
     926           0 :   Matrix<Double> xform(2,2);
     927           0 :   xform=0.0;xform.diagonal()=1.0;
     928             :   DirectionCoordinate
     929           0 :     myRaDec(MDirection::Types(phaseCenter_p.getRefPtr()->getType()),
     930             :             projection,
     931           0 :             refCoord(0), refCoord(1),
     932           0 :             deltas(0), deltas(1),
     933             :             xform,
     934           0 :             refPixel(0), refPixel(1));
     935             :   
     936             :   // Now set up spectral coordinate
     937           0 :   SpectralCoordinate* mySpectral=0;
     938           0 :   Double refChan=0.0;
     939             :   
     940             :   // Spectral synthesis
     941             :   // For mfs band we set the window to include all spectral windows
     942           0 :   Int nspw=spectralwindowids_p.nelements();
     943           0 :   if (imageMode_p=="MFS") {
     944           0 :     Double fmin=C::dbl_max;
     945           0 :     Double fmax=-(C::dbl_max);
     946           0 :     Double fmean=0.0;
     947           0 :     for (Int i=0;i<nspw;++i) {
     948           0 :       Int spw=spectralwindowids_p(i);
     949           0 :       Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spw); 
     950           0 :       Vector<Double> freqResolution = msc.spectralWindow().chanWidth()(spw); 
     951             :       
     952           0 :       if(dataMode_p=="none"){
     953             :       
     954           0 :         if(i==0) {
     955           0 :           fmin=min(chanFreq-abs(0.5*freqResolution));
     956           0 :           fmax=max(chanFreq+abs(0.5*freqResolution));
     957             :         }
     958             :         else {
     959           0 :           fmin=min(fmin,min(chanFreq-abs(0.5*freqResolution)));
     960           0 :           fmax=max(fmax,max(chanFreq+abs(0.5*freqResolution)));
     961             :         }
     962             :       }
     963           0 :       else if(dataMode_p=="channel"){
     964             :         // This needs some careful thought about roundoff - it is likely 
     965             :         // still adding an extra half-channel at top and bottom but 
     966             :         // if the freqResolution is nonlinear, there are subtleties
     967           0 :         Int elnchan=chanFreq.nelements();
     968           0 :         Int firstchan=0;
     969           0 :         Int elstep=1;
     970           0 :         for (uInt jj=0; jj < dataspectralwindowids_p.nelements(); ++jj){
     971           0 :           if(dataspectralwindowids_p[jj]==spw){
     972           0 :             firstchan=dataStart_p[jj];
     973           0 :             elnchan=dataNchan_p[jj];
     974           0 :             elstep=dataStep_p[jj];
     975             :           }     
     976             :         }
     977           0 :         Int lastchan=firstchan+ elnchan*elstep;
     978           0 :         for(Int k=firstchan ; k < lastchan ;  k+=elstep){
     979           0 :           fmin=min(fmin,chanFreq[k]-abs(freqResolution[k]*(elstep-0.5)));
     980           0 :           fmax=max(fmax,chanFreq[k]+abs(freqResolution[k]*(elstep-0.5)));
     981             :         }
     982             :       }
     983             :       else{
     984           0 :         this->unlock();
     985             :         os << LogIO::SEVERE 
     986             :            << "setdata has to be in 'channel' or 'none' mode for 'mfs' imaging to work"
     987           0 :            << LogIO::EXCEPTION;
     988           0 :       return false;
     989             :       }
     990             :  
     991           0 :     }
     992             : 
     993           0 :     fmean=(fmax+fmin)/2.0;
     994           0 :     Vector<Double> restFreqArray;
     995           0 :     Double restFreq=fmean;
     996           0 :     if(getRestFreq(restFreqArray, spectralwindowids_p(0))){
     997           0 :       restFreq=restFreqArray[0];
     998             :     }
     999           0 :     imageNchan_p=1;
    1000           0 :     Double finc=(fmax-fmin); 
    1001           0 :     mySpectral = new SpectralCoordinate(freqFrame_p,  fmean//-finc/2.0
    1002             :                                         , finc,
    1003           0 :                                         refChan, restFreq);
    1004             :     os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
    1005             :        << "Center frequency = "
    1006           0 :        << MFrequency(Quantity(fmean, "Hz")).get("GHz").getValue()
    1007             :        << " GHz, synthesized continuum bandwidth = "
    1008           0 :        << MFrequency(Quantity(finc, "Hz")).get("GHz").getValue()
    1009           0 :        << " GHz" << LogIO::POST;
    1010             : 
    1011           0 :     if(ntaylor_p>1 && reffreq_p==0.0) 
    1012             :     {
    1013           0 :             reffreq_p = fmean;
    1014           0 :             os << "Setting center frequency as MS-MFS reference frequency" << LogIO::POST;
    1015             :     }
    1016           0 :   }
    1017             :   
    1018           0 :   else if(imageMode_p.contains("FREQ")) {
    1019           0 :       if(imageNchan_p==0) {
    1020           0 :         this->unlock();
    1021             :         os << LogIO::SEVERE << "Must specify number of channels" 
    1022           0 :            << LogIO::EXCEPTION;
    1023           0 :         return false;
    1024             :       }
    1025           0 :       Double restFreq=mfImageStart_p.get("Hz").getValue();
    1026           0 :       Vector<Double> restFreqVec;
    1027           0 :       if(getRestFreq(restFreqVec, spectralwindowids_p(0))){
    1028           0 :         restFreq=restFreqVec[0];
    1029             :       }
    1030           0 :       MFrequency::Types mfreqref=(obsFreqRef==(MFrequency::REST)) ? MFrequency::REST : MFrequency::castType(mfImageStart_p.getRef().getType()) ; 
    1031             :       //  mySpectral = new SpectralCoordinate(mfreqref,
    1032             :       //                                          mfImageStart_p.get("Hz").getValue()+
    1033             :       //mfImageStep_p.get("Hz").getValue()/2.0,
    1034             :       //                                          mfImageStep_p.get("Hz").getValue(),
    1035             :       //                                          refChan, restFreq);
    1036           0 :       mySpectral = new SpectralCoordinate(mfreqref,
    1037           0 :                                           mfImageStart_p.get("Hz").getValue(),
    1038           0 :                                           mfImageStep_p.get("Hz").getValue(),
    1039           0 :                                           refChan, restFreq);
    1040             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1041             :          << "Start frequency = " // Loglevel INFO
    1042           0 :          << mfImageStart_p.get("GHz").getValue()
    1043             :          << ", channel increment = "
    1044           0 :          << mfImageStep_p.get("GHz").getValue() 
    1045             :          << "GHz, frequency frame = "
    1046             :          << MFrequency::showType(mfreqref)
    1047           0 :          << endl;
    1048             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1049             :          << "Rest frequency is "  // Loglevel INFO
    1050           0 :          << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
    1051           0 :          << "GHz" << LogIO::POST;
    1052             :       
    1053           0 :   }
    1054             :   
    1055             : 
    1056             :   else {
    1057             :     //    if(nspw>1) {
    1058             :     //      os << LogIO::SEVERE << "Line modes allow only one spectral window"
    1059             :     //   << LogIO::POST;
    1060             :     //      return false;
    1061             :     //    }
    1062           0 :     Vector<Double> chanFreq;
    1063           0 :     Vector<Double> freqResolution;
    1064             :     //starting with a default rest frequency to be ref 
    1065             :     //in case none is defined
    1066             :     Double restFreq=
    1067           0 :       msc.spectralWindow().refFrequency()(spectralwindowids_p(0));
    1068             : 
    1069           0 :     for (Int spwIndex=0; spwIndex < nspw; ++spwIndex){
    1070             :  
    1071           0 :       Int spw=spectralwindowids_p(spwIndex);
    1072           0 :       Int origsize=chanFreq.shape()(0);
    1073           0 :       Int newsize=origsize+msc.spectralWindow().chanFreq()(spw).shape()(0);
    1074           0 :       chanFreq.resize(newsize, true);
    1075           0 :       chanFreq(Slice(origsize, newsize-origsize))=msc.spectralWindow().chanFreq()(spw);
    1076           0 :       freqResolution.resize(newsize, true);
    1077           0 :      freqResolution(Slice(origsize, newsize-origsize))=
    1078           0 :         msc.spectralWindow().chanWidth()(spw); 
    1079             :       
    1080             : 
    1081             :      
    1082           0 :       Vector<Double> restFreqArray;
    1083           0 :       if(getRestFreq(restFreqArray, spw)){
    1084           0 :         if(spwIndex==0){
    1085           0 :           restFreq = restFreqArray(0);
    1086             :         }
    1087             :         else{
    1088           0 :           if(restFreq != restFreqArray(0)){
    1089             :             os << LogIO::WARN << "Rest frequencies are different for  spectralwindows selected " 
    1090           0 :                << LogIO::POST;
    1091             :             os << LogIO::WARN 
    1092             :                <<"Will be using the restFreq defined in spectralwindow "
    1093           0 :                << spectralwindowids_p(0) << LogIO::POST;
    1094             :           }
    1095             :           
    1096             :         }       
    1097             :       }
    1098           0 :     }
    1099             :   
    1100             : 
    1101           0 :     if(imageMode_p=="CHANNEL") {
    1102           0 :       if(imageNchan_p==0) {
    1103           0 :         this->unlock();
    1104             :         os << LogIO::SEVERE << "Must specify number of channels" 
    1105           0 :            << LogIO::EXCEPTION;
    1106           0 :         return false;
    1107             :       }
    1108           0 :       Vector<Double> freqs;
    1109           0 :       if(imageStep_p==0)
    1110           0 :         imageStep_p=1;
    1111             : //      TT: commented these out otherwise the case for multiple MSes would not work
    1112             : //      Int nsubchans=
    1113             : //      (chanFreq.shape()(0) - Int(imageStart_p)+1)/Int(imageStep_p)+1;
    1114             : //      if((nsubchans >0) && (imageNchan_p>nsubchans)) imageNchan_p=nsubchans;
    1115             : 
    1116             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1117             :          << "Image spectral coordinate: "<< imageNchan_p
    1118             :          << " channels, starting at visibility channel "
    1119           0 :          << imageStart_p << " stepped by " << imageStep_p << LogIO::POST;
    1120           0 :       freqs.resize(imageNchan_p);
    1121           0 :       for (Int chan=0;chan<imageNchan_p;chan++) {
    1122           0 :         freqs(chan)=chanFreq(Int(imageStart_p)+Int(Float(chan)*Float(imageStep_p)));
    1123             :       }
    1124             :       // Use this next line when non-linear working
    1125             :       //    mySpectral = new SpectralCoordinate(obsFreqRef, freqs,
    1126             :       //                                        restFreq);
    1127             :       // Since we are taking the frequencies as is, the frame must be
    1128             :       // what is specified in the SPECTRAL_WINDOW table
    1129             :       //      Double finc=(freqs(imageNchan_p-1)-freqs(0))/(imageNchan_p-1);
    1130           0 :       Double finc = 0;
    1131           0 :       if(imageNchan_p > 1){
    1132           0 :         finc=freqs(1)-freqs(0);
    1133             :       }
    1134           0 :       else if(imageNchan_p==1) {
    1135           0 :         finc=freqResolution(IPosition(1,0))*imageStep_p;
    1136             :       }
    1137             : 
    1138             : 
    1139             :       //in order to outframe to work need to set here original freq frame
    1140             :       //mySpectral = new SpectralCoordinate(freqFrame_p, freqs(0)-finc/2.0, finc,
    1141           0 :       mySpectral = new SpectralCoordinate(obsFreqRef, freqs(0)//-finc/2.0
    1142             :                                           , finc,
    1143           0 :                                           refChan, restFreq);
    1144             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1145             :          << "Frequency = " // Loglevel INFO
    1146           0 :          << MFrequency(Quantity(freqs(0), "Hz")).get("GHz").getValue()
    1147             :          << ", channel increment = "
    1148           0 :          << MFrequency(Quantity(finc, "Hz")).get("GHz").getValue() 
    1149           0 :          << "GHz" << endl;
    1150             :       os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1151             :          << "Rest frequency is "  // Loglevel INFO
    1152           0 :          << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
    1153           0 :          << "GHz" << LogIO::POST;
    1154             :       
    1155           0 :     }
    1156             :     // Spectral channels resampled at equal increments in optical velocity
    1157             :     // Here we compute just the first two channels and use increments for
    1158             :     // the others
    1159           0 :     else if (imageMode_p=="VELOCITY" || imageMode_p.contains("RADIO")) {
    1160           0 :       if(imageNchan_p==0) {
    1161           0 :         this->unlock();
    1162             :         os << LogIO::SEVERE << "Must specify number of channels" 
    1163           0 :            << LogIO::EXCEPTION;
    1164           0 :         return false;
    1165             :       }
    1166             :       {
    1167           0 :         ostringstream oos;
    1168           0 :         oos << "Image spectral coordinate:"<< imageNchan_p 
    1169           0 :             << " channels, starting at radio velocity " << mImageStart_p
    1170           0 :             << "  stepped by " << mImageStep_p << endl;
    1171             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1172           0 :            << String(oos); // Loglevel INFO
    1173           0 :       }
    1174           0 :       Vector<Double> freqs(2);
    1175           0 :       freqs=0.0;
    1176           0 :       if(Double(mImageStep_p.getValue())!=0.0) {
    1177           0 :         MRadialVelocity mRadVel=mImageStart_p;
    1178           0 :         for (Int chan=0;chan<2;chan++) {
    1179           0 :           MDoppler mdoppler(mRadVel.getValue().get(), MDoppler::RADIO);
    1180           0 :           freqs(chan)=
    1181           0 :             MFrequency::fromDoppler(mdoppler, 
    1182           0 :                                     restFreq).getValue().getValue();
    1183           0 :           Quantity vel=mRadVel.get("m/s");
    1184           0 :           Quantity inc=mImageStep_p.get("m/s");
    1185           0 :           vel+=inc;
    1186           0 :           mRadVel=MRadialVelocity(vel, MRadialVelocity::LSRK);
    1187           0 :         }
    1188           0 :       }
    1189             :       else {
    1190           0 :         for (Int chan=0;chan<2;++chan) {
    1191           0 :           freqs(chan)=chanFreq(chan);
    1192             :         }
    1193             :       }
    1194             : 
    1195           0 :       MFrequency::Types mfreqref=MFrequency::LSRK;
    1196             :       //Can't convert to frame in mImageStart
    1197           0 :       if(!MFrequency::getType(mfreqref, (MRadialVelocity::showType(mImageStart_p.getRef().getType()))))
    1198           0 :         mfreqref=freqFrame_p;
    1199           0 :       mfreqref=(obsFreqRef==(MFrequency::REST)) ? MFrequency::REST : mfreqref; 
    1200           0 :       mySpectral = new SpectralCoordinate(mfreqref, freqs(0)//-(freqs(1)-freqs(0))/2.0
    1201           0 :                                           , freqs(1)-freqs(0), refChan,
    1202           0 :                                           restFreq);
    1203             :      
    1204             :       {
    1205           0 :         ostringstream oos;
    1206           0 :         oos << "Reference Frequency = "
    1207           0 :             << MFrequency(Quantity(freqs(0), "Hz")).get("GHz")
    1208           0 :             << ", spectral increment = "
    1209           0 :             << MFrequency(Quantity(freqs(1)-freqs(0), "Hz")).get("GHz") 
    1210           0 :             << ", frequency frame = "
    1211           0 :             << MFrequency::showType(mfreqref)
    1212           0 :             << endl; 
    1213           0 :         oos << "Rest frequency is " 
    1214           0 :             << MFrequency(Quantity(restFreq, "Hz")).get("GHz").getValue()
    1215           0 :             << " GHz" << endl;
    1216           0 :         os << LogIO::NORMAL << String(oos) << LogIO::POST; // Loglevel INFO
    1217           0 :       }
    1218             :       
    1219           0 :     }
    1220             :     // Since optical/relativistic velocity is non-linear in frequency, we have to
    1221             :     // pass in all the frequencies. For radio velocity we can use 
    1222             :     // a linear axis.
    1223           0 :     else if (imageMode_p=="OPTICALVELOCITY" || imageMode_p.contains("OPTICAL") || imageMode_p.contains("TRUE") 
    1224           0 :              || imageMode_p.contains("BETA") ||  imageMode_p.contains("RELATI") ) {
    1225           0 :       if(imageNchan_p==0) {
    1226           0 :         this->unlock();
    1227             :         os << LogIO::SEVERE << "Must specify number of channels" 
    1228           0 :            << LogIO::EXCEPTION;
    1229           0 :         return false;
    1230             :       }
    1231             :       {
    1232           0 :         ostringstream oos;
    1233           0 :         oos << "Image spectral coordinate: "<< imageNchan_p 
    1234           0 :             << " channels, starting at optical velocity " << mImageStart_p
    1235           0 :             << "  stepped by " << mImageStep_p << endl;
    1236             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1237           0 :            << String(oos); // Loglevel INFO
    1238           0 :       }
    1239           0 :       Vector<Double> freqs(imageNchan_p);
    1240           0 :       freqs=0.0;
    1241           0 :       Double chanVelResolution=0.0;
    1242           0 :       if(Double(mImageStep_p.getValue())!=0.0) {
    1243           0 :         MRadialVelocity mRadVel=mImageStart_p;
    1244           0 :         MDoppler mdoppler;
    1245           0 :         for (Int chan=0;chan<imageNchan_p;++chan) {
    1246           0 :           if(imageMode_p.contains("OPTICAL")){
    1247           0 :             mdoppler=MDoppler(mRadVel.getValue().get(), MDoppler::OPTICAL);
    1248             :           } 
    1249             :           else{
    1250           0 :             mdoppler=MDoppler(mRadVel.getValue().get(), MDoppler::BETA);
    1251             :           }
    1252           0 :           freqs(chan)=
    1253           0 :             MFrequency::fromDoppler(mdoppler, restFreq).getValue().getValue();
    1254           0 :           mRadVel.set(mRadVel.getValue()+mImageStep_p.getValue());
    1255           0 :           if(imageNchan_p==1)
    1256           0 :             chanVelResolution=MFrequency::fromDoppler(mdoppler, restFreq).getValue().getValue()-freqs(0);
    1257             :         }
    1258           0 :       }
    1259             :       else {
    1260           0 :         for (Int chan=0;chan<imageNchan_p;++chan) {
    1261           0 :             freqs(chan)=chanFreq(chan);
    1262             :         }
    1263             :       }
    1264             :       // Use this next line when non-linear is working
    1265             :       // when selecting in velocity its specfied freqframe or REST 
    1266           0 :       MFrequency::Types imfreqref=(obsFreqRef==MFrequency::REST) ? MFrequency::REST : freqFrame_p;
    1267             :   
    1268           0 :       if(imageNchan_p==1){
    1269           0 :         if(chanVelResolution==0.0)
    1270           0 :           chanVelResolution=freqResolution(0);
    1271           0 :         mySpectral = new SpectralCoordinate(imfreqref,
    1272           0 :                                             freqs(0)//-chanVelResolution/2.0,
    1273             :                                             ,
    1274             :                                             chanVelResolution,
    1275           0 :                                             refChan, restFreq);
    1276             :       }
    1277             :       else{
    1278           0 :         mySpectral = new SpectralCoordinate(imfreqref, freqs,
    1279           0 :                                             restFreq);
    1280             :       }
    1281             :       // mySpectral = new SpectralCoordinate(MFrequency::DEFAULT, freqs(0),
    1282             :       //                                       freqs(1)-freqs(0), refChan,
    1283             :       //                                        restFreq);
    1284             :       {
    1285           0 :         ostringstream oos;
    1286           0 :         oos << "Reference Frequency = "
    1287           0 :             << MFrequency(Quantity(freqs(0), "Hz")).get("GHz")
    1288             :             << " Ghz, " 
    1289           0 :             <<" frequency frame= "<<MFrequency::showType(imfreqref)<<endl;
    1290             :         os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
    1291           0 :            << String(oos) << LogIO::POST; // Loglevel INFO
    1292           0 :       }
    1293           0 :     }
    1294             :     else {
    1295           0 :       this->unlock();
    1296           0 :       os << LogIO::SEVERE << "Unknown mode " << imageMode_p
    1297           0 :          << LogIO::EXCEPTION;
    1298           0 :       return false;
    1299             :     }
    1300             :         
    1301             :     
    1302           0 :   }
    1303             :  
    1304             :  
    1305             :     //In FTMachine lsrk is used for channel matching with data channel 
    1306             :     //hence we make sure that
    1307             :     // we convert to lsrk when dealing with the channels
    1308           0 :   freqFrameValid_p=freqFrameValid_p && (obsFreqRef !=MFrequency::REST);
    1309           0 :   if(freqFrameValid_p){
    1310           0 :       mySpectral->setReferenceConversion(MFrequency::LSRK, obsEpoch, 
    1311             :                                          obsPosition,
    1312           0 :                                          phaseCenter_p);
    1313             :   }
    1314             : 
    1315             :   // Polarization
    1316           0 :   Vector<String> polType=msc.feed().polarizationType()(0);
    1317           0 :   if (polType(0)!="X" && polType(0)!="Y" &&
    1318           0 :       polType(0)!="R" && polType(0)!="L") {
    1319             :     os << LogIO::WARN << "Unknown stokes types in feed table: ["
    1320           0 :        << polType(0) << ", " << polType(1) << "]" << endl
    1321           0 :        << "Results open to question!" << LogIO::POST;
    1322             :   }
    1323             :   
    1324           0 :   if (polType(0)=="X" || polType(0)=="Y") {
    1325           0 :     polRep_p=StokesImageUtil::LINEAR;
    1326             :     os << LogIO::DEBUG1 
    1327           0 :        << "Preferred polarization representation is linear" << LogIO::POST;
    1328             :   }
    1329             :   else {
    1330           0 :     polRep_p=StokesImageUtil::CIRCULAR;
    1331             :     os << LogIO::DEBUG1
    1332           0 :        << "Preferred polarization representation is circular" << LogIO::POST;
    1333             :   }
    1334             : 
    1335             :   // Compare user input with whatever is allowed by the data. 
    1336             :   // If possible, allow.
    1337             : 
    1338           0 :   Vector<Int> whichStokes = decideNPolPlanes(true);
    1339           0 :   if(whichStokes.nelements()==0 || (whichStokes.nelements()==1 && whichStokes[0]==0) ) 
    1340             :     {
    1341           0 :       if(polRep_p==StokesImageUtil::CIRCULAR) 
    1342           0 :         os << LogIO::SEVERE << "Stokes selection of " << stokes_p << " is not valid for Circular feeds." << LogIO::EXCEPTION;
    1343             :       else 
    1344           0 :         os << LogIO::SEVERE << "Stokes selection of " << stokes_p << " is not valid for Linear feeds." << LogIO::EXCEPTION;
    1345           0 :       return false;
    1346             :     }
    1347             :   /* STOKESDBG */  //cout << "Imager2::imagecoordinate : Image 'whichStokes' : " << whichStokes << endl;
    1348             : 
    1349           0 :   StokesCoordinate myStokes(whichStokes);
    1350             :   
    1351             :   //Set Observatory info
    1352           0 :   ObsInfo myobsinfo;
    1353           0 :   myobsinfo.setTelescope(telescop);
    1354           0 :   myobsinfo.setPointingCenter(mvPhaseCenter);
    1355           0 :   myobsinfo.setObsDate(obsEpoch);
    1356           0 :   myobsinfo.setObserver(msc.observation().observer()(0));
    1357           0 :   this->setObsInfo(myobsinfo);
    1358             : 
    1359             :   //Adding everything to the coordsystem
    1360           0 :   coordInfo.addCoordinate(myRaDec);
    1361           0 :   coordInfo.addCoordinate(myStokes);
    1362           0 :   coordInfo.addCoordinate(*mySpectral);
    1363           0 :   coordInfo.setObsInfo(myobsinfo);
    1364             : 
    1365           0 :   if(mySpectral) delete mySpectral;
    1366             : 
    1367           0 :   return true;
    1368           0 : }
    1369             : 
    1370             : /* Match the user input stokes_p string to all available options.
    1371             :    If it matches none, return false - exceptions are thrown.
    1372             :    If it matches an option, set npol_p : number of desired image planes.
    1373             : 
    1374             :   If checkwithMS = true, check with the PolRep and valid combinations of what
    1375             :                                      is asked for and what the data allows.
    1376             : 
    1377             :   If checkwithMS = false, check only that the inputs are among the valid list
    1378             :                                      and give npol=1,2,3 or 4.
    1379             : 
    1380             :   There are two levels of checks because when called from defineimage, it does
    1381             :   not know what PolRep is and cannot check with the data. This used to be in
    1382             :   two different functions earlier. It is now easier to keep things consistent.
    1383             : 
    1384             :   PLEASE NOTE :  If any stokes options are to be allowed or disallowed,
    1385             :                            this is the place to do it. StokesImageUtil handles all combinations,
    1386             : */
    1387         919 : Vector<Int> Imager::decideNPolPlanes(Bool checkwithMS)
    1388             : {
    1389         919 :     Vector<Int> whichStokes(0);
    1390             : 
    1391             :     // Check with options for npol=1
    1392         977 :     if(stokes_p=="I" || stokes_p=="Q" || stokes_p=="U" || stokes_p=="V" || 
    1393          87 :        stokes_p=="RR" ||stokes_p=="LL" || //stokes_p=="RL" ||stokes_p=="LR" || 
    1394         977 :        stokes_p=="XX" || stokes_p=="YY" ) //|| stokes_p=="XY" ||stokes_p=="YX" ) 
    1395             :       {
    1396         904 :         npol_p=1;
    1397             : 
    1398         904 :         if(checkwithMS)
    1399             :         {
    1400             :  
    1401             :            // Fill in the stokes vector for the output image
    1402         758 :            whichStokes.resize(npol_p);
    1403             :            // The first 8 depend on circular vs linear
    1404         758 :            if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="RR")  whichStokes(0)=Stokes::RR;
    1405         758 :            else if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="LL")  whichStokes(0)=Stokes::LL;
    1406             :            ////else if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="RL")  whichStokes(0)=Stokes::RL;
    1407             :            ////else if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="LR")  whichStokes(0)=Stokes::LR;
    1408         758 :            else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="XX") whichStokes(0)=Stokes::XX;
    1409         752 :            else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="YY")  whichStokes(0)=Stokes::YY;
    1410             :            ////else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="XY")  whichStokes(0)=Stokes::XY;
    1411             :            ////else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="YX")  whichStokes(0)=Stokes::YX;
    1412             :            // these next 4 don't depend on circular vs linear
    1413         746 :            else if(stokes_p=="I") whichStokes(0)=Stokes::I;
    1414           0 :            else if(stokes_p=="Q") whichStokes(0)=Stokes::Q;
    1415           0 :            else if(stokes_p=="U")  whichStokes(0)=Stokes::U;
    1416           0 :            else if(stokes_p=="V")  whichStokes(0)=Stokes::V;
    1417           0 :            else {whichStokes.resize(0);}
    1418             : 
    1419             :         }// end of checkwithMS
    1420             : 
    1421             :     }// end of npol=1
    1422             :     // Check for options with npol=2
    1423          45 :     else if(stokes_p=="IV" || stokes_p=="IQ" || 
    1424          31 :               stokes_p=="RRLL" || stokes_p=="XXYY" ||
    1425             :             ////stokes_p=="RLLR" || stokes_p=="XYYX" ||
    1426          31 :               stokes_p=="QU" || stokes_p=="UV") 
    1427             :       {
    1428          14 :         npol_p=2;
    1429             : 
    1430          14 :         if(checkwithMS)
    1431             :         {
    1432             :             // Check with polrep and fill in the stokes vector for the output image
    1433          12 :            whichStokes.resize(npol_p);
    1434             :            // The first 4 depend on circular vs linear
    1435          12 :            if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="RRLL")  
    1436           0 :                  {whichStokes(0)=Stokes::RR; whichStokes(1)=Stokes::LL;}
    1437             :            ////else if(polRep_p==StokesImageUtil::CIRCULAR && stokes_p=="RLLR") 
    1438             :            ////      {whichStokes(0)=Stokes::RL; whichStokes(1)=Stokes::LR;}
    1439          12 :            else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="XXYY") 
    1440          12 :                   {whichStokes(0)=Stokes::XX; whichStokes(1)=Stokes::YY;}
    1441             :            ////else if(polRep_p==StokesImageUtil::LINEAR && stokes_p=="XYYX") 
    1442             :            ////      {whichStokes(0)=Stokes::XY; whichStokes(1)=Stokes::YX;}
    1443             :            // These 4 don't care about circular vs linear
    1444           0 :            else if(stokes_p=="IV") 
    1445           0 :                   {whichStokes(0)=Stokes::I; whichStokes(1)=Stokes::V;}
    1446           0 :            else if(stokes_p=="QU") 
    1447           0 :                   {whichStokes(0)=Stokes::Q; whichStokes(1)=Stokes::U;}
    1448           0 :            else if(stokes_p=="IQ") 
    1449           0 :                   {whichStokes(0)=Stokes::I; whichStokes(1)=Stokes::Q;}
    1450           0 :            else if(stokes_p=="UV") 
    1451           0 :                   {whichStokes(0)=Stokes::U; whichStokes(1)=Stokes::V;}
    1452             :            else 
    1453           0 :                   {whichStokes.resize(0);}
    1454             : 
    1455             :         }// end of checkwithMS
    1456             : 
    1457             :     }
    1458             :     // Check for options with npol=3
    1459           1 :     else if(stokes_p=="IQU" || stokes_p=="IUV") 
    1460             :     {
    1461           0 :         npol_p=3;
    1462             :  
    1463           0 :         if(checkwithMS)
    1464             :         {
    1465           0 :           whichStokes.resize(npol_p);
    1466             :            // Check with polRep_p
    1467           0 :           if(stokes_p=="IUV")
    1468           0 :             { whichStokes(0)=Stokes::I; whichStokes(1)=Stokes::U; whichStokes(2)=Stokes::V; }
    1469           0 :           else if(stokes_p=="IQU")
    1470           0 :             { whichStokes(0)=Stokes::I; whichStokes(1)=Stokes::Q; whichStokes(2)=Stokes::U; }
    1471             :           else 
    1472           0 :             { whichStokes.resize(0);}
    1473             : 
    1474             :         }// end of checkwithMS
    1475             : 
    1476             :     }//end of npol=3
    1477             :     // Check with options for npol=4
    1478           1 :     else if(stokes_p=="IQUV") // NOT allowing RRLLRLLR and XXYYXYYX !!
    1479             :     {
    1480           0 :         npol_p=4;
    1481             :  
    1482           0 :        if(checkwithMS)
    1483             :         {
    1484           0 :           whichStokes.resize(npol_p);
    1485           0 :           whichStokes(0)=Stokes::I;
    1486           0 :           whichStokes(1)=Stokes::Q;
    1487           0 :           whichStokes(2)=Stokes::U;
    1488           0 :           whichStokes(3)=Stokes::V;
    1489             :         }// end of checkwithMS
    1490             : 
    1491             :     }// end of npol=4
    1492             :     else // If none of the options are valid (checked in setimage/defineimage)
    1493             :     {
    1494           1 :       whichStokes.resize(1); whichStokes[0]=0; // undefined.
    1495             :     }
    1496             : 
    1497             :     // If no match has been found, or an incompatible match is found, this returns Vector<Int>(0);
    1498         919 :     return whichStokes;
    1499           0 : }// end of decideNPolPlanes
    1500             : 
    1501             : 
    1502             : 
    1503             : 
    1504           0 : String Imager::state() 
    1505             : {
    1506           0 :   ostringstream os;
    1507             :   
    1508             :   try {
    1509           0 :     this->lock();
    1510           0 :     os << "General: " << endl;
    1511           0 :     os << "  MeasurementSet is " << ms_p->tableName() << endl;
    1512           0 :     if(beamValid_p) {
    1513           0 :       os << "  Beam fit: " << beam_p(0,0).getMajor("arcsec") << " by "
    1514           0 :          << beam_p(0,0).getMinor("arcsec") << " (arcsec) at pa "
    1515           0 :          << beam_p(0,0).getPA(Unit("deg")) << " (deg) " << endl;
    1516             :     }
    1517             :     else {
    1518           0 :       os << "  Beam fit is not valid" << endl;
    1519             :     }
    1520             :     
    1521           0 :     MSColumns msc(*ms_p);
    1522           0 :     MDirection mDesiredCenter;
    1523           0 :     if(setimaged_p) {
    1524             :       os << "Image definition settings: "
    1525           0 :         "(use setimage in Function Group <setup> to change)" << endl;
    1526           0 :       os << "  nx=" << nx_p << ", ny=" << ny_p
    1527           0 :          << ", cellx=" << mcellx_p << ", celly=" << mcelly_p
    1528           0 :          << ", Stokes axes : " << stokes_p << endl;
    1529           0 :       Int widthRA=20;
    1530           0 :       Int widthDec=20;
    1531           0 :       if(doShift_p) {
    1532           0 :         os << "  doshift is true: Image phase center will be as specified "
    1533           0 :            << endl;
    1534             :       }
    1535             :       else {
    1536           0 :         os << "  doshift is false: Image phase center will be that of field "
    1537           0 :            << fieldid_p << " :" << endl;
    1538             :       }
    1539             :       
    1540           0 :       if(shiftx_p.get().getValue()!=0.0||shifty_p.get().getValue()!=0.0) {
    1541           0 :         os << "  plus the shift: longitude: " << shiftx_p
    1542           0 :            << " / cos(latitude) : latitude: " << shifty_p << endl;
    1543             :       }
    1544             :       
    1545           0 :       MVAngle mvRa=phaseCenter_p.getAngle().getValue()(0);
    1546           0 :       MVAngle mvDec=phaseCenter_p.getAngle().getValue()(1);
    1547           0 :       os << "     ";
    1548           0 :       os.setf(ios::left, ios::adjustfield);
    1549           0 :       os.width(widthRA);  os << mvRa(0.0).string(MVAngle::TIME,8);
    1550           0 :       os.width(widthDec); os << mvDec.string(MVAngle::DIG2,8);
    1551           0 :       os << "     " << MDirection::showType(phaseCenter_p.getRefPtr()->getType())
    1552           0 :          << endl;
    1553             :       
    1554           0 :       if(distance_p.get().getValue()!=0.0) {
    1555           0 :         os << "  Refocusing to distance " << distance_p << endl;
    1556             :       }
    1557             :       
    1558           0 :       if(imageMode_p=="MFS") {
    1559           0 :         os << "  Image mode is mfs: Image will be frequency synthesised from spectral windows : ";
    1560           0 :         for (uInt i=0;i<spectralwindowids_p.nelements();++i) {
    1561           0 :           os << spectralwindowids_p(i) << " ";
    1562             :         }
    1563           0 :         os << endl;
    1564             :       }
    1565             :       
    1566             :       else {
    1567           0 :         os << "  Image mode is " << imageMode_p
    1568           0 :            << "  Image number of spectral channels ="
    1569           0 :            << imageNchan_p << endl;
    1570             :       }
    1571             :       
    1572           0 :     }
    1573             :     else {
    1574             :       os << "Image: parameters not yet set (use setimage "
    1575           0 :         "in Function Group <setup> )" << endl;
    1576             :     }
    1577             :     
    1578             :     os << "Data selection settings: (use setdata in Function Group <setup> "
    1579           0 :       "to change)" << endl;
    1580           0 :     if(dataMode_p=="none") {
    1581           0 :       if(mssel_p->nrow() == ms_p->nrow()){
    1582           0 :         os << "  All data selected" << endl;
    1583             :       }
    1584             :       else{
    1585           0 :         os << " Number of rows of data selected= " << mssel_p->nrow() << endl;
    1586             :       }
    1587             :     }
    1588             :     else {
    1589           0 :       os << "  Data selection mode is " << dataMode_p << ": have selected "
    1590           0 :          << dataNchan_p << " channels";
    1591           0 :       if(dataspectralwindowids_p.nelements()>0) {
    1592           0 :         os << " spectral windows : ";
    1593           0 :         for (uInt i=0;i<dataspectralwindowids_p.nelements();++i) {
    1594           0 :           os << dataspectralwindowids_p(i) << " ";
    1595             :         }
    1596             :       }
    1597           0 :       if(datafieldids_p.nelements()>0) {
    1598           0 :         os << "  Data selected includes fields : ";
    1599           0 :         for (uInt i=0;i<datafieldids_p.nelements();++i) {
    1600           0 :           os << datafieldids_p(i) << " ";
    1601             :         }
    1602             :       }
    1603           0 :       os << endl;
    1604             :     }
    1605             :     os << "Options settings: (use setoptions in Function Group <setup> "
    1606           0 :       "to change) " << endl;
    1607           0 :     os << "  Gridding cache has " << cache_p << " complex pixels, in tiles of "
    1608           0 :        << tile_p << " pixels on a side" << endl;
    1609           0 :     os << "  Gridding convolution function is ";
    1610             :     
    1611           0 :     if(gridfunction_p=="SF") {
    1612           0 :       os << "Spheroidal wave function";
    1613             :     }
    1614           0 :     else if(gridfunction_p=="BOX") {
    1615           0 :       os << "Box car convolution";
    1616             :     }
    1617           0 :     else if(gridfunction_p=="PB") {
    1618           0 :       os << "Using primary beam for convolution";
    1619             :     }
    1620             :     else {
    1621           0 :       os << "Unknown type : " << gridfunction_p;
    1622             :     }
    1623           0 :     os << endl;
    1624             :     
    1625           0 :     if(doVP_p) {
    1626           0 :       os << "  Primary beam correction is enabled" << endl;
    1627             :       //       Table vpTable( vpTableStr_p );   could fish out info and summarize
    1628             :     }
    1629             :     else {
    1630           0 :       os << "  No primary beam correction will be made " << endl;
    1631             :     }
    1632           0 :     os << "  Image plane padding : " << padding_p << endl;
    1633             :     
    1634           0 :     this->unlock();
    1635           0 :   } catch (AipsError x) {
    1636           0 :     this->unlock();
    1637           0 :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1638           0 :        << LogIO::EXCEPTION;
    1639             : 
    1640           0 :   } 
    1641           0 :   return String(os);
    1642           0 : }
    1643             : 
    1644             : 
    1645             : 
    1646             : 
    1647             : // Apply a primary beam or voltage pattern to an image
    1648           0 : Bool Imager::pb(const String& inimage, 
    1649             :                 const String& outimage,
    1650             :                 const String& incomps,
    1651             :                 const String& /*outcomps*/,
    1652             :                 const String& operation, 
    1653             :                 const MDirection& pointingCenter,
    1654             :                 const Quantity& pa,
    1655             :                 const String& pborvp)
    1656             : 
    1657             : {
    1658           0 :   if(!valid()) return false;
    1659             :   
    1660           0 :   LogIO os(LogOrigin("imager", "pb()", WHERE));
    1661             :   
    1662           0 :   PagedImage<Float> * inImage_pointer = 0;
    1663           0 :   PagedImage<Float> * outImage_pointer = 0;
    1664           0 :   ComponentList * inComps_pointer = 0;
    1665           0 :   ComponentList * outComps_pointer = 0;
    1666           0 :   PBMath * myPBp = 0;
    1667             :   try {
    1668             : 
    1669           0 :     if ( ! doVP_p ) {
    1670           0 :       this->unlock();
    1671             :       os << LogIO::SEVERE << 
    1672           0 :         "Must invoke setvp() first in order to apply the primary beam" << LogIO::EXCEPTION;
    1673           0 :       return false;
    1674             :     }
    1675             :     
    1676           0 :     if (pborvp == "vp") {
    1677           0 :       this->unlock();
    1678           0 :       os << LogIO::SEVERE << "VP application is not yet implemented in DOimager" << LogIO::EXCEPTION;
    1679           0 :       return false;
    1680             :     }
    1681             : 
    1682           0 :     if (operation == "apply") {
    1683             :       os << LogIO::DEBUG1
    1684           0 :          << "function pb will apply " << pborvp << LogIO::POST;
    1685           0 :     } else if (operation=="correct") {
    1686             :       os << LogIO::DEBUG1
    1687           0 :          << "function pb will correct for " << pborvp << LogIO::POST;
    1688             :     } else {
    1689           0 :       this->unlock();
    1690             :       os << LogIO::SEVERE << "Unknown pb operation " << operation 
    1691           0 :          << LogIO::EXCEPTION;
    1692           0 :       return false;
    1693             :     }
    1694             :     
    1695             :     // Get initial image and/or SkyComponents
    1696             : 
    1697           0 :     if (incomps!="") {
    1698           0 :       if(!Table::isReadable(incomps)) {
    1699           0 :         this->unlock();
    1700             :         os << LogIO::SEVERE << "ComponentList " << incomps
    1701           0 :            << " not readable" << LogIO::EXCEPTION;
    1702           0 :         return false;
    1703             :       }
    1704           0 :       inComps_pointer = new ComponentList(incomps);
    1705             :       //outComps_pointer = new ComponentList( inComps_pointer->copy() );
    1706             :     }
    1707           0 :     if (inimage !="") {
    1708           0 :       if(!Table::isReadable(inimage)) {
    1709           0 :         this->unlock();
    1710             :         os << LogIO::SEVERE << "Image " << inimage << " not readable" 
    1711           0 :            << LogIO::EXCEPTION;
    1712           0 :         return false;
    1713             :       }
    1714           0 :       inImage_pointer = new PagedImage<Float>( inimage );
    1715           0 :       if (outimage != "") {
    1716           0 :         outImage_pointer = new PagedImage<Float>( TiledShape(inImage_pointer->shape(), inImage_pointer->niceCursorShape()), 
    1717           0 :                                                   inImage_pointer->coordinates(), outimage);
    1718             :       }
    1719             :     }
    1720             :     // create the PBMath object, needed to apply PB 
    1721             :     // to make high res Fourier weight image
    1722           0 :     Quantity qFreq;
    1723           0 :     if (doDefaultVP_p && inImage_pointer==0) {
    1724           0 :       this->unlock();
    1725             :       os << LogIO::SEVERE << 
    1726             :         "There is no default telescope associated with a componentlist" 
    1727           0 :          << LogIO::POST;
    1728             :       os << LogIO::SEVERE << 
    1729             :         "Either specify the PB/VP via a vptable or supply an image as well" 
    1730           0 :          << LogIO::EXCEPTION;
    1731           0 :         return false;
    1732           0 :     } else if (doDefaultVP_p && inImage_pointer!=0) {
    1733             :       // look up the telescope in ObsInfo
    1734           0 :       ObsInfo oi = inImage_pointer->coordinates().obsInfo();
    1735           0 :       String myTelescope = oi.telescope();
    1736           0 :       if (myTelescope == "") {
    1737           0 :         this->unlock();
    1738             :         os << LogIO::SEVERE << "No telescope imbedded in image" 
    1739           0 :            << LogIO::EXCEPTION;
    1740           0 :         return false;
    1741             :       }
    1742             :       {
    1743           0 :         Int spectralIndex=inImage_pointer->coordinates().findCoordinate(Coordinate::SPECTRAL);
    1744           0 :         AlwaysAssert(spectralIndex>=0, AipsError);
    1745             :         SpectralCoordinate
    1746           0 :           spectralCoord=inImage_pointer->coordinates().spectralCoordinate(spectralIndex);
    1747           0 :         Vector<String> units(1); units = "Hz";
    1748           0 :         spectralCoord.setWorldAxisUnits(units); 
    1749           0 :         Vector<Double> spectralWorld(1);
    1750           0 :         Vector<Double> spectralPixel(1);
    1751           0 :         spectralPixel(0) = 0;
    1752           0 :         spectralCoord.toWorld(spectralWorld, spectralPixel);  
    1753           0 :         Double freq  = spectralWorld(0);
    1754           0 :         qFreq = Quantity( freq, "Hz" );
    1755           0 :       }
    1756           0 :       String band;
    1757             :       PBMath::CommonPB whichPB;
    1758           0 :       String pbName;
    1759             :       // get freq from coordinates
    1760           0 :       PBMath::whichCommonPBtoUse (myTelescope, qFreq, band, whichPB, pbName);
    1761           0 :       if (whichPB  == PBMath::UNKNOWN) {
    1762           0 :         this->unlock();
    1763             :         os << LogIO::SEVERE << "Unknown telescope for PB type: " 
    1764           0 :            << myTelescope << LogIO::EXCEPTION;
    1765           0 :         return false;
    1766             :       }
    1767           0 :       myPBp = new PBMath(whichPB);
    1768           0 :     } else {
    1769             :       // get the PB from the vpTable
    1770           0 :       Table vpTable( vpTableStr_p );
    1771           0 :       ScalarColumn<TableRecord> recCol(vpTable, (String)"pbdescription");
    1772           0 :       myPBp = new PBMath(recCol(0));
    1773           0 :     }
    1774           0 :     AlwaysAssert((myPBp != 0), AipsError);
    1775             : 
    1776             : 
    1777             :     // Do images (if indeed we have any)
    1778           0 :     if (outImage_pointer!=0) {
    1779           0 :       Vector<Int> whichStokes;
    1780           0 :       CoordinateSystem cCoords;
    1781           0 :       cCoords=StokesImageUtil::CStokesCoord(//inImage_pointer->shape(),
    1782             :                                             inImage_pointer->coordinates(),
    1783             :                                             whichStokes,
    1784           0 :                                             polRep_p);
    1785           0 :       TempImage<Complex> cIn(inImage_pointer->shape(),
    1786           0 :                              cCoords);
    1787           0 :       StokesImageUtil::From(cIn, *inImage_pointer);
    1788           0 :       if (operation=="apply") {
    1789           0 :         myPBp->applyPB(cIn, cIn, pointingCenter, 
    1790             :                        pa, squintType_p, false);
    1791             :       } else {
    1792           0 :         myPBp->applyPB(cIn, cIn, pointingCenter, 
    1793             :                        pa, squintType_p, true);
    1794             :       }
    1795           0 :       StokesImageUtil::To(*outImage_pointer, cIn);
    1796           0 :     }
    1797             :     // Do components (if indeed we have any)
    1798           0 :     if (inComps_pointer!=0) {
    1799           0 :       if (inImage_pointer==0) {
    1800           0 :         this->unlock();
    1801             :         os << LogIO::SEVERE << 
    1802             :           "No input image was given for the componentList to get the frequency from" 
    1803           0 :            << LogIO::EXCEPTION;
    1804           0 :         return false;
    1805             :       }
    1806           0 :       Int ncomponents = inComps_pointer->nelements();
    1807           0 :       outComps_pointer = new ComponentList();
    1808           0 :       for (Int icomp=0;icomp<ncomponents;++icomp) {
    1809           0 :         SkyComponent component=(inComps_pointer->component(icomp)).copy();
    1810           0 :         if (operation=="apply") {
    1811           0 :           myPBp->applyPB(component, component, pointingCenter, 
    1812             :                          qFreq, pa, squintType_p, false);
    1813             :         } else {
    1814           0 :           myPBp->applyPB(component, component, pointingCenter, 
    1815             :                          qFreq, pa, squintType_p, true);
    1816             :         }
    1817           0 :         outComps_pointer->add(component);
    1818           0 :       }
    1819           0 :       if(outImage_pointer){
    1820           0 :         ComponentListImage clImage(*outComps_pointer, outImage_pointer->coordinates(), outImage_pointer->shape());
    1821           0 :         outImage_pointer->copyData(LatticeExpr<Float>((*outImage_pointer)+clImage));
    1822           0 :       }
    1823             :     }
    1824           0 :     if (myPBp) delete myPBp;
    1825           0 :     if (inImage_pointer) delete inImage_pointer;
    1826           0 :     if (outImage_pointer) delete outImage_pointer; 
    1827           0 :     if (inComps_pointer) delete inComps_pointer; 
    1828           0 :     if (outComps_pointer) delete outComps_pointer; 
    1829           0 :     return true;
    1830           0 :   } catch (AipsError x) {
    1831           0 :     if (myPBp) delete myPBp;
    1832           0 :     if (inImage_pointer) delete inImage_pointer;
    1833           0 :     if (outImage_pointer) delete outImage_pointer; 
    1834           0 :     if (inComps_pointer) delete inComps_pointer; 
    1835           0 :     if (outComps_pointer) delete outComps_pointer; 
    1836           0 :     this->unlock();
    1837             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1838           0 :        << LogIO::EXCEPTION;
    1839           0 :     return false;
    1840           0 :   }
    1841             :   return true;
    1842           0 : }
    1843             : 
    1844             : 
    1845             : // Apply a primary beam or voltage pattern to an image
    1846           0 : Bool Imager::pbguts(ImageInterface<Float>& inImage, 
    1847             :                     ImageInterface<Float>& outImage,
    1848             :                     const MDirection& pointingDirection,
    1849             :                     const Quantity& pa)
    1850             : {
    1851           0 :   if(!valid()) return false;
    1852             :   
    1853           0 :   LogIO os(LogOrigin("imager", "pbguts()", WHERE));
    1854             :   
    1855             :   try {
    1856           0 :     if ( ! doVP_p ) {
    1857             :       os << LogIO::SEVERE << 
    1858           0 :         "Must invoke setvp() first in order to apply the primary beam" << LogIO::POST;
    1859           0 :       return false;
    1860             :     }
    1861           0 :     String operation = "apply";  // could have as input in the future!
    1862             : 
    1863             :     // create the PBMath object, needed to apply PB 
    1864             :     // to make high res Fourier weight image
    1865           0 :     Quantity qFreq;
    1866           0 :     PBMath * myPBp = 0;
    1867             : 
    1868           0 :     if (doDefaultVP_p) {
    1869             :       // look up the telescope in ObsInfo
    1870           0 :       ObsInfo oi = inImage.coordinates().obsInfo();
    1871           0 :       String myTelescope = oi.telescope();
    1872           0 :       if (myTelescope == "") {
    1873           0 :         os << LogIO::SEVERE << "No telescope embedded in image" << LogIO::POST;
    1874           0 :         return false;
    1875             :       }
    1876             :       {
    1877           0 :         Int spectralIndex=inImage.coordinates().findCoordinate(Coordinate::SPECTRAL);
    1878           0 :         AlwaysAssert(spectralIndex>=0, AipsError);
    1879             :         SpectralCoordinate
    1880           0 :           spectralCoord=inImage.coordinates().spectralCoordinate(spectralIndex);
    1881           0 :         Vector<String> units(1); units = "Hz";
    1882           0 :         spectralCoord.setWorldAxisUnits(units); 
    1883           0 :         Vector<Double> spectralWorld(1);
    1884           0 :         Vector<Double> spectralPixel(1);
    1885           0 :         spectralPixel(0) = 0;
    1886           0 :         spectralCoord.toWorld(spectralWorld, spectralPixel);  
    1887           0 :         Double freq  = spectralWorld(0);
    1888           0 :         qFreq = Quantity( freq, "Hz" );
    1889           0 :       }
    1890           0 :       String band;
    1891             :       PBMath::CommonPB whichPB;
    1892           0 :       String pbName;
    1893             :       // get freq from coordinates
    1894           0 :       PBMath::whichCommonPBtoUse (myTelescope, qFreq, band, whichPB, pbName);
    1895           0 :       if (whichPB  != PBMath::UNKNOWN) {
    1896             :       
    1897           0 :         myPBp = new PBMath(whichPB);
    1898             :       }
    1899             :       else{
    1900           0 :         MSAntennaColumns ac(ms_p->antenna());
    1901           0 :         Double dishDiam=ac.dishDiameter()(0);
    1902           0 :         myPBp= new PBMath(dishDiam, true, qFreq);
    1903             : 
    1904           0 :       }
    1905           0 :     } else {
    1906             :       // get the PB from the vpTable
    1907           0 :       Table vpTable( vpTableStr_p );
    1908           0 :       ScalarColumn<TableRecord> recCol(vpTable, (String)"pbdescription");
    1909           0 :       myPBp = new PBMath(recCol(0));
    1910           0 :     }
    1911           0 :     AlwaysAssert((myPBp != 0), AipsError);
    1912             : 
    1913           0 :     Vector<Int> whichStokes;
    1914           0 :     CoordinateSystem cCoords;
    1915           0 :     cCoords=StokesImageUtil::CStokesCoord(//inImage.shape(),
    1916             :                                           inImage.coordinates(),
    1917             :                                           whichStokes,
    1918           0 :                                           polRep_p);
    1919           0 :     TempImage<Complex> cIn(inImage.shape(),
    1920           0 :                            cCoords);
    1921           0 :     StokesImageUtil::From(cIn, inImage);
    1922           0 :     if (operation=="apply") {
    1923           0 :       myPBp->applyPB(cIn, cIn, pointingDirection, 
    1924             :                      pa, squintType_p, false);
    1925             :     } else {
    1926           0 :       myPBp->applyPB(cIn, cIn, pointingDirection, 
    1927             :                      pa, squintType_p, true);
    1928             :     }
    1929           0 :     StokesImageUtil::To(outImage, cIn);
    1930           0 :     delete myPBp;    
    1931           0 :     return true;
    1932           0 :   } catch (AipsError x) {
    1933             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    1934           0 :        << LogIO::POST;
    1935           0 :     return false;
    1936           0 :   } 
    1937             :   
    1938             :   return true;
    1939           0 : }
    1940             : 
    1941             : 
    1942           0 : void Imager::printbeam(CleanImageSkyModel *sm_p, LogIO &os, const Bool firstrun)
    1943             : {
    1944             :   //Use predefined beam for restoring or find one by fitting
    1945           0 :   Bool printBeam = false;
    1946           0 :   if(!beamValid_p){
    1947           0 :     ImageBeamSet beam;
    1948           0 :     beam=sm_p->beam(0);
    1949           0 :     if(beam.nelements() > 0){
    1950             :       /*beam_p.setMajorMinor(
    1951             :                 Quantity(abs(beam(0)), "arcsec"),
    1952             :                 Quantity(abs(beam(1)), "arcsec")
    1953             :         );
    1954             :       beam_p.setPA(Quantity(beam(2), "deg"));
    1955             :       */
    1956           0 :       beam_p=beam;
    1957           0 :       beamValid_p=true;
    1958           0 :       printBeam = true;
    1959           0 :       os << LogIO::NORMAL << "Fitted beam used in restoration: " ;         // Loglevel INFO
    1960             :     }
    1961           0 :   }
    1962           0 :   else if(firstrun){
    1963           0 :     printBeam = true;
    1964           0 :     os << LogIO::NORMAL << "Beam used in restoration: "; // Loglevel INFO
    1965             :   }
    1966           0 :   if(printBeam)
    1967           0 :     os << LogIO::NORMAL << beam_p(0,0).getMajor("arcsec") << " by " // Loglevel INFO
    1968           0 :        << beam_p(0,0).getMinor("arcsec") << " (arcsec) at pa "
    1969           0 :        << beam_p(0,0).getPA(Unit("deg")) << " (deg) " << LogIO::POST;
    1970           0 : }
    1971             : 
    1972           0 : Bool Imager::restoreImages(const Vector<String>& restoredNames, Bool modresiduals)
    1973             : {
    1974             : 
    1975           0 :   LogIO os(LogOrigin("imager", "restoreImages()", WHERE));
    1976             :   try{
    1977             :     // It's important that we use the congruent images in both
    1978             :     // cases. This means that we must use the residual image as
    1979             :     // passed to the SkyModel and not the one returned. This 
    1980             :     // distinction is important only (currently) for WFCleanImageSkyModel
    1981             :     // which has a different representation for the image internally.
    1982           0 :     Vector<String> residualNames(images_p.nelements());
    1983           0 :     Vector<String> modelNames(images_p.nelements());
    1984           0 :     Vector<Bool> dofluxscale(images_p.nelements());
    1985           0 :     dofluxscale=false;
    1986           0 :     for(uInt k=0; k < modelNames.nelements() ; ++k){
    1987           0 :       residualNames[k]=residuals_p[k]->name();
    1988           0 :       modelNames[k]=images_p[k]->name();
    1989           0 :       dofluxscale[k]=sm_p->doFluxScale(k);
    1990             :     }
    1991             : 
    1992             : 
    1993           0 :     Double availablemem=Double(HostInfo::memoryFree())*1024.0;
    1994           0 :     Bool nomemory=false;
    1995           0 :     Block<CountedPtr< TempImage<Float> > > tempfluximage(modelNames.nelements());
    1996             :     //The convolution needs in ram 3 complex x-y planes ...lets multiply it by 5 for safety
    1997           0 :     if((availablemem < Double(nx_p*ny_p)*15.0*8.0 ) && (ft_p->name() != "MosaicFT") && !(doWideBand_p && ntaylor_p>1)){
    1998             :       // very large for convolution ...destroy Skyequations to release memory
    1999             :       // need to fix the convolution to be leaner
    2000           0 :       for (Int thismodel=0;thismodel<Int(restoredNames.nelements()); 
    2001             :            ++thismodel) {
    2002           0 :         tempfluximage[thismodel]=new TempImage<Float>(sm_p->fluxScale(thismodel).shape(), sm_p->fluxScale(thismodel).coordinates(), 10.0);
    2003           0 :         (tempfluximage[thismodel])->copyData(sm_p->fluxScale(thismodel));
    2004             :       }
    2005           0 :       destroySkyEquation();
    2006           0 :       nomemory=true;
    2007             :       
    2008             :     }
    2009             :    
    2010             : 
    2011             :       // If msmfs, calculate Coeff Residuals
    2012           0 :       if(doWideBand_p && ntaylor_p>1)
    2013             :         {
    2014           0 :           if( modresiduals ) // When called from pclean, this is set to false, via the iClean call to restoreImages.
    2015             :             {
    2016           0 :               sm_p->calculateCoeffResiduals(); 
    2017             :               // Re-fill them into the output residual images.
    2018           0 :               for (uInt k=0 ; k < residuals_p.nelements(); ++k){
    2019           0 :                 (residuals_p[k])->copyData(sm_p->getResidual(k));
    2020             :               }
    2021             :             }
    2022             :         }
    2023             : 
    2024             :  
    2025           0 :     Bool dorestore=false;
    2026           0 :     if(  beam_p.nelements() >0 )
    2027           0 :       dorestore=true;
    2028             :     
    2029           0 :     if(restoredNames.nelements()>0) {
    2030           0 :       for (Int thismodel=0;thismodel<Int(restoredNames.nelements()); 
    2031             :            ++thismodel) {
    2032           0 :         if(restoredNames(thismodel)!="") {
    2033           0 :           PagedImage<Float> modelIm(modelNames[thismodel]);
    2034           0 :           PagedImage<Float> residIm(residualNames[thismodel]);
    2035           0 :           TempImage<Float> restored;
    2036           0 :           if(dorestore){
    2037           0 :             restored=TempImage<Float>(modelIm.shape(),
    2038           0 :                                 modelIm.coordinates());
    2039           0 :             restored.copyData(modelIm);
    2040             :            
    2041           0 :             StokesImageUtil::Convolve(restored, beam_p);
    2042             :           }
    2043             :           // We can work only if the residual image was defined.
    2044           0 :           if(residIm.name() != "") {
    2045           0 :             if(dorestore){
    2046           0 :               LatticeExpr<Float> le(restored+(residIm)); 
    2047           0 :               restored.copyData(le);
    2048           0 :             }
    2049           0 :             if(freqFrameValid_p){
    2050           0 :               CoordinateSystem cs=residIm.coordinates();
    2051           0 :               String errorMsg;
    2052           0 :               if (cs.setSpectralConversion (errorMsg, MFrequency::showType(freqFrame_p))) {
    2053           0 :                 residIm.setCoordinateInfo(cs);
    2054           0 :                 if(dorestore)
    2055           0 :                   restored.setCoordinateInfo(cs);
    2056             :               }
    2057           0 :             } 
    2058             :             
    2059             :             //should be able to do that only on testing dofluxscale
    2060             :             // ftmachines or sm_p should tell us that
    2061             :             
    2062             :             // this should go away..
    2063             :             //special casing like this gets hard to maintain
    2064             :             // need to redo how interactive is done so that it is outside 
    2065             :             //of this code 
    2066             : 
    2067             : 
    2068             :             //
    2069             :             // Using minPB_p^2 below to make it consistent with the normalization in SkyEquation for ftmachine mosaic as coverimage in that case in square of what it should be
    2070             :             //
    2071           0 :             Float cutoffval=minPB_p;
    2072           0 :             if(ft_p->name()=="MosaicFT")         
    2073           0 :               cutoffval=minPB_p*minPB_p;
    2074             :             
    2075           0 :             ImageInterface<Float> * diviseur= nomemory ? &(*tempfluximage[thismodel]) : &(sm_p->fluxScale(thismodel));
    2076             : 
    2077           0 :             if (dofluxscale(thismodel)) {
    2078           0 :               TempImage<Float> cover(modelIm.shape(),modelIm.coordinates());
    2079           0 :               if(ft_p->name()=="MosaicFT")
    2080           0 :                 se_p->getCoverageImage(thismodel, cover);
    2081             :               else
    2082           0 :                 cover.copyData(*diviseur);
    2083             :              
    2084           0 :               if(scaleType_p=="NONE"){
    2085           0 :                 if(dorestore){
    2086           0 :                   LatticeExpr<Float> le(iif(((cover > cutoffval) && ((*diviseur) >0.0)) , 
    2087           0 :                                             (restored/(*diviseur)), 0.0));
    2088           0 :                   restored.copyData(le);
    2089           0 :                 }
    2090           0 :                     LatticeExpr<Float> le1(iif(((cover > cutoffval) && ((*diviseur) >0.0)), 
    2091           0 :                                                (residIm/(*diviseur)), 0.0));
    2092           0 :                 residIm.copyData(le1);
    2093             :                 
    2094           0 :               }
    2095             :               
    2096             :               //Setting the bit-mask for mosaic image
    2097           0 :               LatticeExpr<Bool> lemask(iif((cover > cutoffval) && ((*diviseur) >0.0), 
    2098           0 :                                            true, false));
    2099           0 :               if(dorestore){
    2100           0 :                 ImageRegion outreg=restored.makeMask("mask0", false, true);
    2101           0 :                 LCRegion& outmask=outreg.asMask();
    2102           0 :                 outmask.copyData(lemask);
    2103           0 :                 restored.defineRegion("mask0", outreg, RegionHandler::Masks, true);
    2104           0 :                 restored.setDefaultMask("mask0");
    2105             :           
    2106           0 :               }
    2107             :               
    2108           0 :             }
    2109           0 :             if(dorestore){
    2110           0 :               PagedImage<Float> diskrestore(restored.shape(), restored.coordinates(), 
    2111           0 :                                             restoredNames(thismodel));
    2112           0 :               diskrestore.copyData(restored);
    2113           0 :               ImageInfo ii = modelIm.imageInfo();
    2114           0 :               ii.setBeams(beam_p);
    2115           0 :               diskrestore.setImageInfo(ii);
    2116           0 :               diskrestore.setUnits(Unit("Jy/beam"));
    2117           0 :               copyMask(diskrestore, restored, "mask0");
    2118             :                  
    2119           0 :             }
    2120             :             
    2121             :           }
    2122             :           else {
    2123             :             os << LogIO::SEVERE << "No residual image for model "
    2124           0 :                << thismodel << ", cannot restore image" << LogIO::POST;
    2125             :           }
    2126             :           
    2127           0 :           if(!(residuals_p[thismodel].null()) && residuals_p[thismodel]->ok()){
    2128           0 :             residuals_p[thismodel]->table().relinquishAutoLocks(true);
    2129           0 :             residuals_p[thismodel]->table().unlock();
    2130             :             //detaching residual so that other processes can use it
    2131           0 :             residuals_p[thismodel]=0;
    2132             :           }
    2133           0 :         }
    2134             :         
    2135             :       }// end of for 'thismodel'
    2136             :  
    2137             :       // If msmfs, calculate alpha, beta too
    2138           0 :       if(doWideBand_p && ntaylor_p>1)
    2139             :         {
    2140           0 :           sm_p->calculateAlphaBeta(restoredNames, residualNames);
    2141             :         }
    2142             :    
    2143             :     }
    2144           0 :   }
    2145           0 : catch (exception &x) { 
    2146           0 :     os << LogIO::SEVERE << "Exception: " << x.what() << LogIO::POST;
    2147           0 :     return false;
    2148           0 :   }
    2149           0 :   return true;
    2150           0 : }
    2151             : 
    2152          97 : Bool Imager::copyMask(ImageInterface<Float>& out, const ImageInterface<Float>& in, String maskname, Bool setdef){
    2153             :   try{
    2154          97 :     if(in.hasRegion(maskname) && !out.hasRegion(maskname)){
    2155          97 :       ImageRegion outreg=out.makeMask(maskname, false, true);
    2156          97 :       LCRegion& outmask=outreg.asMask();
    2157          97 :       outmask.copyData(in.getRegion(maskname).asLCRegion());
    2158         194 :       LatticeExpr<Float> myexpr(iif(outmask, out, 0.0) );
    2159          97 :       out.copyData(myexpr);
    2160          97 :       out.defineRegion(maskname, outreg, RegionHandler::Masks, true);
    2161          97 :       if(setdef)
    2162          97 :         out.setDefaultMask(maskname);
    2163          97 :     }
    2164             :     else
    2165           0 :       return false;
    2166             :     
    2167             :   }
    2168           0 :   catch(exception &x){
    2169           0 :     throw(AipsError(x.what()));
    2170             :     return false;
    2171           0 :   }
    2172             : 
    2173             : 
    2174          97 :   return true;
    2175             : }
    2176             : 
    2177           0 : Bool Imager::writeFluxScales(const Vector<String>& fluxScaleNames)
    2178             : {
    2179           0 :   LogIO os(LogOrigin("imager", "writeFluxScales()", WHERE));
    2180           0 :   Bool answer = false;
    2181             :   ImageInterface<Float> *cover;
    2182           0 :   if(fluxScaleNames.nelements()>0) {
    2183           0 :     for (Int thismodel=0;thismodel<Int(fluxScaleNames.nelements());++thismodel) {
    2184           0 :       if(fluxScaleNames(thismodel)!="") {
    2185           0 :         PagedImage<Float> fluxScale(images_p[thismodel]->shape(),
    2186           0 :                                     images_p[thismodel]->coordinates(),
    2187           0 :                                     fluxScaleNames(thismodel));
    2188           0 :         PagedImage<Float> coverimage(images_p[thismodel]->shape(),
    2189           0 :                                      images_p[thismodel]->coordinates(),
    2190           0 :                                      fluxScaleNames(thismodel)+".pbcoverage");
    2191           0 :         coverimage.table().markForDelete();
    2192           0 :         if(freqFrameValid_p){
    2193           0 :           CoordinateSystem cs=fluxScale.coordinates();
    2194           0 :           String errorMsg;
    2195           0 :           if (cs.setSpectralConversion (errorMsg,MFrequency::showType(freqFrame_p))) {
    2196           0 :             fluxScale.setCoordinateInfo(cs);
    2197           0 :             coverimage.setCoordinateInfo(cs);
    2198             :           }
    2199           0 :         }
    2200           0 :         if (sm_p->doFluxScale(thismodel)) {
    2201           0 :           cover=&(sm_p->fluxScale(thismodel));
    2202           0 :           answer = true;
    2203           0 :           fluxScale.copyData(sm_p->fluxScale(thismodel));
    2204           0 :           Float cutoffval=minPB_p;
    2205           0 :           if(ft_p->name()=="MosaicFT"){
    2206           0 :             cutoffval=minPB_p*minPB_p;
    2207           0 :             se_p->getCoverageImage(thismodel, coverimage);
    2208           0 :             cover=&(coverimage);
    2209             :             //Do the sqrt
    2210           0 :             coverimage.copyData(( LatticeExpr<Float> )(iif(coverimage > 0.0, sqrt(coverimage), 0.0)));
    2211           0 :             coverimage.table().unmarkForDelete();
    2212           0 :             LatticeExpr<Bool> lemask(iif((*cover) < sqrt(cutoffval), 
    2213           0 :                                        false, true));
    2214           0 :             ImageRegion outreg=coverimage.makeMask("mask0", false, true);
    2215           0 :             LCRegion& outmask=outreg.asMask();
    2216           0 :             outmask.copyData(lemask);
    2217           0 :             coverimage.defineRegion("mask0", outreg,RegionHandler::Masks, true); 
    2218           0 :             coverimage.setDefaultMask("mask0");
    2219           0 :           }
    2220           0 :           LatticeExpr<Bool> lemask(iif(((*cover) > minPB_p) && (fluxScale > 0.0), 
    2221           0 :                                        true, false));
    2222           0 :           ImageRegion outreg=fluxScale.makeMask("mask0", false, true);
    2223           0 :           LCRegion& outmask=outreg.asMask();
    2224           0 :           outmask.copyData(lemask);
    2225           0 :           fluxScale.defineRegion("mask0", outreg,RegionHandler::Masks, true); 
    2226           0 :           fluxScale.setDefaultMask("mask0");
    2227             : 
    2228             : 
    2229           0 :         } else {
    2230           0 :           answer = false;
    2231             :           os << LogIO::NORMAL // Loglevel INFO
    2232             :              << "No flux scale available (or required) for model " << thismodel
    2233           0 :              << LogIO::POST;
    2234             :           os << LogIO::NORMAL // Loglevel INFO
    2235           0 :              << "(This is only pertinent to mosaiced images)" << LogIO::POST;
    2236             :           os << LogIO::NORMAL // Loglevel INFO
    2237           0 :              << "Writing out image of constant 1.0" << LogIO::POST;
    2238           0 :           fluxScale.set(1.0);
    2239             :         }
    2240           0 :       }
    2241             :     }
    2242             :   }
    2243           0 :   return answer;
    2244           0 : }
    2245             : // Supports the "[] or -1 => everything" convention using the rule:
    2246             : // If v is empty or only has 1 element, and it is < 0, 
    2247             : //     replace v with 0, 1, ..., nelem - 1.
    2248             : // Returns whether or not it modified v.
    2249             : //   If so, v is modified in place.
    2250          66 : Bool Imager::expand_blank_sel(Vector<Int>& v, const uInt nelem)
    2251             : {
    2252          66 :   if((v.nelements() == 1 && v[0] < 0) || v.nelements() == 0){
    2253          32 :     v.resize(nelem);
    2254          32 :     indgen(v);
    2255          32 :     return true;
    2256             :   }
    2257          34 :   return false;
    2258             : }
    2259             : 
    2260             : 
    2261             : // Correct the data using a plain VisEquation.
    2262             : // This just moves data from observed to corrected.
    2263             : // Eventually we should pass in a calibrater
    2264             : // object to do the work.
    2265           0 : Bool Imager::correct(const Bool /*doparallactic*/, const Quantity& /*t*/)
    2266             : {
    2267           0 :   if(!valid()) return false;
    2268             : 
    2269           0 :   LogIO os(LogOrigin("imager", "correct()", WHERE));
    2270             :   
    2271             :   // (gmoellen 06Nov20)
    2272             :   // VisEquation/VisJones have been extensively revised, so
    2273             :   //  so we are disabling this method.  Will probably soon
    2274             :   /// delete it entirely, since this is a calibrater responsibility....
    2275             : 
    2276           0 :   this->lock();
    2277             :   try {
    2278             : 
    2279             :     // Warn users we are disabled.
    2280           0 :     throw(AipsError("Imager::correct() has been disabled (gmoellen 06Nov20)."));
    2281             : 
    2282             :  /* Commenting out old VisEquation/VisJones usage
    2283             :     os << "Correcting data: CORRECTED_DATA column will be replaced"
    2284             :        << LogIO::POST;
    2285             :     
    2286             :     
    2287             :     if(doparallactic) {
    2288             :       os<<"Correcting parallactic angle variation"<<LogIO::POST;
    2289             :       VisEquation ve(*vs_p);
    2290             :       Float ts=t.get("s").getValue();
    2291             :       Float dt=ts/10.0;
    2292             :       PJones pj(*vs_p, ts, dt);
    2293             :       ve.setVisJones(pj);
    2294             :       ve.correct();
    2295             :     }
    2296             :     else {
    2297             :       VisEquation ve(*vs_p);
    2298             :       ve.correct();
    2299             :     }
    2300             :     this->unlock();
    2301             :     return true;
    2302             :  */
    2303             : 
    2304             : 
    2305           0 :   } catch (AipsError x) {
    2306           0 :     this->unlock();
    2307           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    2308           0 :     return false;
    2309           0 :   } 
    2310             :   this->unlock();
    2311             :   
    2312             :   return true;
    2313           0 : }
    2314             : 
    2315           0 : uInt Imager::count_visibilities(ROVisibilityIterator *rvi,
    2316             :                                 const Bool unflagged_only,
    2317             :                                 const Bool must_have_imwt)
    2318             : {
    2319           0 :   if(!valid()) return 0;
    2320           0 :   LogIO os(LogOrigin("imager", "count_visibilities()", WHERE));
    2321             :   
    2322           0 :   this->lock();
    2323           0 :   ROVisIter& vi(*rvi);
    2324           0 :   VisBuffer vb(vi);
    2325             :     
    2326           0 :   uInt nVis = 0;
    2327           0 :   for(vi.originChunks(); vi.moreChunks(); vi.nextChunk()){
    2328           0 :     for(vi.origin(); vi.more(); ++vi){
    2329           0 :       uInt nRow = vb.nRow();
    2330           0 :       uInt nChan = vb.nChannel();
    2331           0 :       for(uInt row = 0; row < nRow; ++row)
    2332           0 :         for(uInt chn = 0; chn < nChan; ++chn)
    2333           0 :           if((!unflagged_only || !vb.flag()(chn,row)) &&
    2334           0 :              (!must_have_imwt || vb.imagingWeight()(chn,row) > 0.0))
    2335           0 :             ++nVis;
    2336             :     }
    2337             :   }
    2338           0 :   this->unlock();
    2339           0 :   return nVis;
    2340           0 : }
    2341             : // Create the FTMachine as late as possible
    2342         252 : Bool Imager::createFTMachine()
    2343             : {
    2344             :   
    2345             : 
    2346         252 :   if(ft_p) {delete ft_p; ft_p=0;}
    2347         252 :   if(gvp_p) {delete gvp_p; gvp_p=0;}
    2348         252 :   if(cft_p) {delete cft_p; cft_p=0;}
    2349             : 
    2350             :   //For ftmachines that can use double precision gridders 
    2351         252 :   Bool useDoublePrecGrid=false;
    2352             :   //few channels use Double precision
    2353             :   //till we find a better algorithm to determine when to use Double prec gridding
    2354         252 :   if((imageNchan_p < 5) && !(singlePrec_p))
    2355         206 :     useDoublePrecGrid=true;
    2356             : 
    2357         504 :   LogIO os(LogOrigin("imager", "createFTMachine()", WHERE));
    2358             : 
    2359             :   Float padding;
    2360         252 :   padding=1.0;
    2361         252 :   if(doMultiFields_p||(facets_p>1)) {
    2362           0 :     padding = padding_p;
    2363             :     os << LogIO::NORMAL // Loglevel INFO
    2364             :        << "Multiple fields or facets: transforms will be padded by a factor "
    2365           0 :        << padding << LogIO::POST;
    2366             :   }
    2367             : 
    2368         252 :   if(ftmachine_p=="sd") {
    2369             :     os << LogIO::NORMAL // Loglevel INFO
    2370         122 :        << "Performing single dish gridding..." << LogIO::POST;
    2371             :     os << LogIO::NORMAL1 // gridfunction_p is too cryptic for most users.
    2372         122 :        << "with convolution function " << gridfunction_p << LogIO::POST;
    2373             : 
    2374             :     // Now make the Single Dish Gridding
    2375             :     os << LogIO::NORMAL // Loglevel INFO
    2376         122 :        << "Gridding will use specified common tangent point:" << LogIO::POST;
    2377         122 :     os << LogIO::NORMAL << tangentPoint() << LogIO::POST; // Loglevel INFO
    2378         122 :     if(gridfunction_p=="pb") {
    2379          18 :       if(!gvp_p) {
    2380          18 :         MSColumns msc(*ms_p);
    2381          18 :         if (doDefaultVP_p) {
    2382             :           os << LogIO::NORMAL // Loglevel INFO
    2383          18 :              << "Using defaults for primary beams used in gridding" << LogIO::POST;
    2384          18 :             gvp_p=new VPSkyJones(msc, true, parAngleInc_p, squintType_p,
    2385          18 :                                  skyPosThreshold_p);
    2386             :         } else {
    2387             :           os << LogIO::NORMAL // Loglevel INFO
    2388           0 :              << "Using VP as defined in " << vpTableStr_p <<  LogIO::POST;
    2389           0 :           Table vpTable( vpTableStr_p ); 
    2390           0 :           gvp_p=new VPSkyJones(msc, vpTable, parAngleInc_p, squintType_p,
    2391           0 :                                skyPosThreshold_p);
    2392           0 :         }
    2393          18 :       } 
    2394          36 :       ft_p = new SDGrid(mLocation_p, *gvp_p, cache_p/2, tile_p, gridfunction_p,
    2395          18 :                         sdConvSupport_p, minWeight_p, clipminmax_p);
    2396             :     }
    2397         104 :     else if (gridfunction_p=="gauss" || gridfunction_p=="gjinc") {
    2398           3 :       if (mcellx_p != mcelly_p && 
    2399           0 :           ((!qtruncate_p.getUnit().empty()||qtruncate_p.getUnit()=="pixel")
    2400           0 :            || (!qgwidth_p.getUnit().empty()||qgwidth_p.getUnit()=="pixel")
    2401           0 :            || (!qjwidth_p.getUnit().empty()||qjwidth_p.getUnit()=="pixel"))) {
    2402             :         os << LogIO::WARN 
    2403           0 :            << "The " << gridfunction_p << " gridding doesn't support non-square grid." << endl
    2404           0 :            << "Result may be wrong." << LogIO::POST;
    2405             :       } 
    2406             :       Float truncate, gwidth, jwidth;
    2407           3 :       if (qtruncate_p.getUnit().empty() || qtruncate_p.getUnit()=="pixel")
    2408           3 :         truncate = qtruncate_p.getValue();
    2409             :       else
    2410           0 :         truncate = qtruncate_p.getValue("rad")/mcelly_p.getValue("rad");
    2411           3 :       if (qgwidth_p.getUnit().empty() || qgwidth_p.getUnit()=="pixel")
    2412           3 :         gwidth = qgwidth_p.getValue();
    2413             :       else
    2414           0 :         gwidth = qgwidth_p.getValue("rad")/mcelly_p.getValue("rad");
    2415           3 :       if (qjwidth_p.getUnit().empty() || qjwidth_p.getUnit()=="pixel")
    2416           3 :         jwidth = qjwidth_p.getValue();
    2417             :       else
    2418           0 :         jwidth = qjwidth_p.getValue("rad")/mcelly_p.getValue("rad");
    2419           6 :       ft_p = new SDGrid(mLocation_p, cache_p/2, tile_p, gridfunction_p,
    2420           3 :                         truncate, gwidth, jwidth, minWeight_p, clipminmax_p);
    2421             :     }
    2422             :     else {
    2423         202 :       ft_p = new SDGrid(mLocation_p, cache_p/2, tile_p, gridfunction_p,
    2424         101 :                         sdConvSupport_p, minWeight_p, clipminmax_p);
    2425             :     }
    2426         122 :     ft_p->setPointingDirColumn(pointingDirCol_p);
    2427         122 :     auto * sdgrid = dynamic_cast<SDGrid *>(ft_p);
    2428         122 :     if (sdgrid) {
    2429         122 :       sdgrid->setEnableCache(enablecache_p);
    2430         122 :       sdgrid->setConvertFirst(convertfirst_p);
    2431             :     }
    2432             : 
    2433         122 :     ROVisIter& vi(*rvi_p);
    2434             :     // Get bigger chunks o'data: this should be tuned some time
    2435             :     // since it may be wrong for e.g. spectral line
    2436         122 :     vi.setRowBlocking(100);
    2437             :     
    2438         122 :     AlwaysAssert(ft_p, AipsError);
    2439             :     
    2440         122 :     cft_p = new SimpleComponentGridMachine();
    2441         122 :     AlwaysAssert(cft_p, AipsError);
    2442             :   }
    2443         130 :   else if(ftmachine_p=="mosaic") {
    2444           0 :     os << LogIO::NORMAL << "Performing mosaic gridding" << LogIO::POST; // Loglevel PROGRESS
    2445             :    
    2446           0 :     setMosaicFTMachine(useDoublePrecGrid);
    2447             : 
    2448             :     // VisIter& vi(vs_p->iter());
    2449             :     //   vi.setRowBlocking(100);
    2450             :     
    2451           0 :     AlwaysAssert(ft_p, AipsError);
    2452             :     
    2453           0 :     cft_p = new SimpleComponentFTMachine();
    2454           0 :     AlwaysAssert(cft_p, AipsError);
    2455             :   }
    2456             :   //
    2457             :   // Make WProject FT machine (for non co-planar imaging)
    2458             :   //
    2459         130 :   else if (ftmachine_p == "wproject"){
    2460             :     os << LogIO::NORMAL << "Performing w-plane projection" // Loglevel PROGRESS
    2461           0 :        << LogIO::POST;
    2462             :    
    2463           0 :     Double maxW=-1.0;
    2464           0 :     Double minW=-1.0;
    2465           0 :     Double rmsW=-1.0;
    2466           0 :     if(wprojPlanes_p < 1)
    2467           0 :       WProjectFT::wStat(*rvi_p, minW, maxW, rmsW);
    2468           0 :     if(facets_p > 1){
    2469           0 :       ft_p = new WProjectFT(wprojPlanes_p,  phaseCenter_p, mLocation_p,
    2470           0 :                             cache_p/2, tile_p, false, padding_p, useDoublePrecGrid, minW, maxW, rmsW);
    2471             :     }
    2472             :     else{
    2473           0 :       ft_p = new WProjectFT(wprojPlanes_p,  mLocation_p,
    2474           0 :                             cache_p/2, tile_p, false, padding_p, useDoublePrecGrid, minW, maxW, rmsW);
    2475             :     }
    2476           0 :     AlwaysAssert(ft_p, AipsError);
    2477           0 :     cft_p = new SimpleComponentFTMachine();
    2478           0 :     AlwaysAssert(cft_p, AipsError);
    2479             :   }
    2480             :   //
    2481             :   // Make PBWProject FT machine (for non co-planar imaging with
    2482             :   // antenna based PB corrections)
    2483             :   //
    2484         130 :   else if (ftmachine_p == "pbwproject"){
    2485           0 :     if (wprojPlanes_p<=1)
    2486             :       {
    2487             :         os << LogIO::NORMAL
    2488             :            << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    2489           0 :            << LogIO::POST;
    2490           0 :         os << LogIO::NORMAL << "Performing pb-projection" << LogIO::POST; // Loglevel PROGRESS
    2491             :       }
    2492           0 :     if((wprojPlanes_p>1)&&(wprojPlanes_p<64)) 
    2493             :       {
    2494             :         os << LogIO::WARN
    2495             :            << "No. of w-planes set too low for W projection - recommend at least 128"
    2496           0 :            << LogIO::POST;
    2497             :         os << LogIO::NORMAL << "Performing pb + w-plane projection" // Loglevel PROGRESS
    2498           0 :            << LogIO::POST;
    2499             :       }
    2500             : 
    2501             : 
    2502           0 :     if(!gvp_p) 
    2503             :       {
    2504             :         os << LogIO::NORMAL // Loglevel INFO
    2505           0 :            << "Using defaults for primary beams used in gridding" << LogIO::POST;
    2506           0 :         MSColumns msc(*ms_p);
    2507           0 :         gvp_p = new VPSkyJones(msc, true, parAngleInc_p, squintType_p,
    2508           0 :                                skyPosThreshold_p);
    2509           0 :       }
    2510             : 
    2511           0 :     ft_p = new nPBWProjectFT(//*ms_p, 
    2512           0 :                              wprojPlanes_p, cache_p/2,
    2513           0 :                             cfCacheDirName_p, doPointing, doPBCorr,
    2514           0 :                              tile_p, computePAStep_p, pbLimit_p, true);
    2515             :     //
    2516             :     // Explicit type casting of ft_p does not look good.  It does not
    2517             :     // pick up the setPAIncrement() method of PBWProjectFT without
    2518             :     // this
    2519             :     //
    2520           0 :     ((nPBWProjectFT *)ft_p)->setPAIncrement(parAngleInc_p);
    2521           0 :     if (doPointing)
    2522             :       {
    2523             :         try
    2524             :           {
    2525             :             //            epJ = new EPJones(*vs_p, *ms_p);
    2526           0 :             VisSet elVS(*rvi_p);
    2527           0 :             epJ = new EPJones(elVS);
    2528           0 :             RecordDesc applyRecDesc;
    2529           0 :             applyRecDesc.addField("table", TpString);
    2530           0 :             applyRecDesc.addField("interp",TpString);
    2531           0 :             Record applyRec(applyRecDesc);
    2532           0 :             applyRec.define("table",epJTableName_p);
    2533           0 :             applyRec.define("interp", "nearest");
    2534           0 :             epJ->setApply(applyRec);
    2535           0 :             ((nPBWProjectFT *)ft_p)->setEPJones(epJ);
    2536           0 :           }
    2537           0 :         catch(AipsError& x)
    2538             :           {
    2539             :             //
    2540             :             // Add some more useful info. to the message and translate
    2541             :             // the generic AipsError exception object to a more specific
    2542             :             // SynthesisError object.
    2543             :             //
    2544           0 :             String mesg = x.getMesg();
    2545           0 :             mesg += ". Error in loading pointing offset table.";
    2546           0 :             SynthesisError err(mesg);
    2547           0 :             throw(err);
    2548           0 :           }
    2549             :       }
    2550             : 
    2551           0 :     AlwaysAssert(ft_p, AipsError);
    2552           0 :     cft_p = new SimpleComponentFTMachine();
    2553           0 :     AlwaysAssert(cft_p, AipsError);
    2554             :   }
    2555         130 :   else if (ftmachine_p == "pbmosaic"){
    2556             : 
    2557           0 :     if (wprojPlanes_p<=1)
    2558             :       {
    2559             :         os << LogIO::NORMAL
    2560             :            << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    2561           0 :            << LogIO::POST;
    2562           0 :         os << LogIO::NORMAL << "Performing pb-mosaic" << LogIO::POST; // Loglevel PROGRESS
    2563             :       }
    2564           0 :     if((wprojPlanes_p>1)&&(wprojPlanes_p<64)) 
    2565             :       {
    2566             :         os << LogIO::WARN
    2567             :            << "No. of w-planes set too low for W projection - recommend at least 128"
    2568           0 :            << LogIO::POST;
    2569           0 :         os << LogIO::NORMAL << "Performing pb + w-plane projection" << LogIO::POST; // Loglevel PROGRESS
    2570             :       }
    2571             : 
    2572           0 :     if(!gvp_p) 
    2573             :       {
    2574             :         os << LogIO::NORMAL // Loglevel INFO
    2575           0 :            << "Using defaults for primary beams used in gridding" << LogIO::POST;
    2576           0 :         MSColumns msc(*ms_p);
    2577           0 :         gvp_p = new VPSkyJones(msc, true, parAngleInc_p, squintType_p,
    2578           0 :                                skyPosThreshold_p);
    2579           0 :       }
    2580           0 :     ft_p = new PBMosaicFT(*ms_p, wprojPlanes_p, cache_p/2, 
    2581           0 :                           cfCacheDirName_p, /*true */doPointing, doPBCorr, 
    2582           0 :                           tile_p, computePAStep_p, pbLimit_p, true);
    2583           0 :     ((PBMosaicFT *)ft_p)->setObservatoryLocation(mLocation_p);
    2584             :     //
    2585             :     // Explicit type casting of ft_p does not look good.  It does not
    2586             :     // pick up the setPAIncrement() method of PBWProjectFT without
    2587             :     // this
    2588             :     //
    2589           0 :     os << LogIO::NORMAL << "Setting PA increment to " << parAngleInc_p.getValue("deg") << " deg" << endl;
    2590           0 :     ((nPBWProjectFT *)ft_p)->setPAIncrement(parAngleInc_p);
    2591             : 
    2592           0 :     if (doPointing) 
    2593             :       {
    2594             :         try
    2595             :           {
    2596             :             // Warn users we are have temporarily disabled pointing cal
    2597             :             //      throw(AipsError("Pointing calibration temporarily disabled (gmoellen 06Nov20)."));
    2598             :             //  TBD: Bring this up-to-date with new VisCal mechanisms
    2599           0 :             VisSet elVS(*rvi_p);
    2600           0 :             epJ = new EPJones(elVS, *ms_p);
    2601           0 :             RecordDesc applyRecDesc;
    2602           0 :             applyRecDesc.addField("table", TpString);
    2603           0 :             applyRecDesc.addField("interp",TpString);
    2604           0 :             Record applyRec(applyRecDesc);
    2605           0 :             applyRec.define("table",epJTableName_p);
    2606           0 :             applyRec.define("interp", "nearest");
    2607           0 :             epJ->setApply(applyRec);
    2608           0 :             ((nPBWProjectFT *)ft_p)->setEPJones(epJ);
    2609           0 :           }
    2610           0 :         catch(AipsError& x)
    2611             :           {
    2612             :             //
    2613             :             // Add some more useful info. to the message and translate
    2614             :             // the generic AipsError exception object to a more specific
    2615             :             // SynthesisError object.
    2616             :             //
    2617           0 :             String mesg = x.getMesg();
    2618           0 :             mesg += ". Error in loading pointing offset table.";
    2619           0 :             SynthesisError err(mesg);
    2620           0 :             throw(err);
    2621           0 :           }
    2622             :       }
    2623             :     
    2624           0 :     AlwaysAssert(ft_p, AipsError);
    2625           0 :     cft_p = new SimpleComponentFTMachine();
    2626           0 :     AlwaysAssert(cft_p, AipsError);
    2627             : 
    2628             :   }
    2629         130 :   else if(ftmachine_p=="both") {
    2630             :       
    2631             :     os << LogIO::NORMAL // Loglevel INFO
    2632             :        << "Performing single dish gridding with convolution function "
    2633           0 :        << gridfunction_p << LogIO::POST;
    2634             :     os << LogIO::NORMAL // Loglevel INFO
    2635             :        << "and interferometric gridding with the prolate spheroidal convolution function"
    2636           0 :        << LogIO::POST;
    2637             :     
    2638             :     // Now make the Single Dish Gridding
    2639             :     os << LogIO::NORMAL // Loglevel INFO
    2640           0 :        << "Gridding will use specified common tangent point:" << LogIO::POST;
    2641           0 :     os << LogIO::NORMAL << tangentPoint() << LogIO::POST; // Loglevel INFO
    2642           0 :     if(!gvp_p) {
    2643             :       os << LogIO::NORMAL // Loglevel INFO
    2644           0 :          << "Using defaults for primary beams used in gridding" << LogIO::POST;
    2645           0 :       MSColumns msc(*ms_p);
    2646           0 :       gvp_p = new VPSkyJones(msc, true, parAngleInc_p, squintType_p,
    2647           0 :                              skyPosThreshold_p);
    2648           0 :     }
    2649           0 :     if(sdScale_p != 1.0)
    2650             :       os << LogIO::NORMAL // Loglevel INFO
    2651           0 :          << "Multiplying single dish data by factor " << sdScale_p << LogIO::POST;
    2652           0 :     if(sdWeight_p != 1.0)
    2653             :       os << LogIO::NORMAL // Loglevel INFO
    2654           0 :          << "Multiplying single dish weights by factor " << sdWeight_p
    2655           0 :          << LogIO::POST;
    2656           0 :     ft_p = new GridBoth(*gvp_p, cache_p/2, tile_p,
    2657           0 :                         mLocation_p, phaseCenter_p,
    2658           0 :                         gridfunction_p, "SF", padding,
    2659           0 :                         sdScale_p, sdWeight_p);
    2660             :     
    2661             :     //VisIter& vi(vs_p->iter());
    2662             :     // Get bigger chunks o'data: this should be tuned some time
    2663             :     // since it may be wrong for e.g. spectral line
    2664           0 :     rvi_p->setRowBlocking(100);
    2665             :     
    2666           0 :     AlwaysAssert(ft_p, AipsError);
    2667             :     
    2668           0 :     cft_p = new SimpleComponentFTMachine();
    2669           0 :     AlwaysAssert(cft_p, AipsError);
    2670             :     
    2671             :   }  
    2672         130 :   else if(ftmachine_p=="nift") {
    2673             :     os << LogIO::NORMAL // Loglevel INFO
    2674           0 :        << "Using FTMachine " << ftmachine_p << LogIO::POST
    2675             :        << "Performing interferometric gridding..."
    2676           0 :        << LogIO::POST;
    2677             :     os << LogIO::NORMAL1 // gridfunction_p is too cryptic for most users.
    2678           0 :        << "...with convolution function " << gridfunction_p << LogIO::POST;
    2679             :     /*
    2680             :     // Make the re-gridder components.  Here, make the basic
    2681             :     // re-sampler.
    2682             :     CountedPtr<VisibilityResamplerBase> visResamplerCtor = new VisibilityResampler();
    2683             :     // Make the multi-threaded re-sampler and supply the basic
    2684             :     // re-sampler used in the worklet threads.
    2685             :     CountedPtr<VisibilityResamplerBase> mthVisResampler = new MultiThreadedVisibilityResampler(useDoublePrecGrid,
    2686             :                                                                                                visResamplerCtor);
    2687             :     */
    2688             :     // Now make the FTMachine
    2689           0 :     if(facets_p>1) {
    2690             :       os << LogIO::NORMAL // Loglevel INFO
    2691             :          << "Multi-facet Fourier transforms will use specified common tangent point:"
    2692           0 :          << LogIO::POST;
    2693           0 :       os << LogIO::NORMAL << tangentPoint() << LogIO::POST; // Loglevel INFO
    2694             :       //      ft_p = new rGridFT(cache_p / 2, tile_p, mthVisResampler, gridfunction_p, mLocation_p,
    2695             :       //                         phaseCenter_p, padding, false, useDoublePrecGrid);
    2696             : 
    2697           0 :       ft_p=new rGridFT(cache_p / 2, tile_p, gridfunction_p, mLocation_p,
    2698           0 :                         phaseCenter_p, padding, false, useDoublePrecGrid);
    2699             :       
    2700             :     }
    2701             :     else {
    2702             :       os << LogIO::DEBUG1
    2703             :          << "Single facet Fourier transforms will use image center as tangent points"
    2704           0 :          << LogIO::POST;
    2705           0 :       ft_p = new rGridFT(cache_p/2, tile_p, gridfunction_p, mLocation_p,
    2706           0 :                         padding, false, useDoublePrecGrid);
    2707             :     }
    2708           0 :     AlwaysAssert(ft_p, AipsError);
    2709             :     
    2710           0 :     cft_p = new SimpleComponentFTMachine();
    2711           0 :     AlwaysAssert(cft_p, AipsError);
    2712             :     
    2713             :   }
    2714             :   //===============================================================
    2715             :   // A-Projection FTMachine code start here
    2716             :   //===============================================================
    2717         130 :   else if ((ftmachine_p == "awproject") || (ftmachine_p == "mawproject")){
    2718           0 :     if (wprojPlanes_p<=1)
    2719             :       {
    2720             :         os << LogIO::NORMAL
    2721             :            << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    2722           0 :            << LogIO::POST;
    2723           0 :         os << LogIO::NORMAL << "Performing WBA-Projection" << LogIO::POST; // Loglevel PROGRESS
    2724             :       }
    2725           0 :     if((wprojPlanes_p>1)&&(wprojPlanes_p<64)) 
    2726             :       {
    2727             :         os << LogIO::WARN
    2728             :            << "No. of w-planes set too low for W projection - recommend at least 128"
    2729           0 :            << LogIO::POST;
    2730           0 :         os << LogIO::NORMAL << "Performing WBAW-Projection" << LogIO::POST; // Loglevel PROGRESS
    2731             :       }
    2732             : 
    2733           0 :     CountedPtr<ATerm> apertureFunction = createTelescopeATerm(*ms_p, aTermOn_p);
    2734           0 :     CountedPtr<PSTerm> psTerm = new PSTerm();
    2735           0 :     CountedPtr<WTerm> wTerm = new WTerm();
    2736             :     
    2737             :     //
    2738             :     // Selectively switch off CFTerms.
    2739             :     //
    2740           0 :     if (aTermOn_p == false) {apertureFunction->setOpCode(CFTerms::NOOP);}
    2741           0 :     if (psTermOn_p == false) psTerm->setOpCode(CFTerms::NOOP);
    2742             : 
    2743             :     //
    2744             :     // Construct the CF object with appropriate CFTerms.
    2745             :     //
    2746           0 :     CountedPtr<ConvolutionFunction> awConvFunc;
    2747             :     //    awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm, !wbAWP_p);
    2748             :     // if ((ftmachine_p=="mawproject") || (mTermOn_p))
    2749             :     //   awConvFunc = new AWConvFuncEPJones(apertureFunction,psTerm,wTerm,wbAWP_p);
    2750             :     // else
    2751           0 :       awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm,wbAWP_p);
    2752             : 
    2753             :     //
    2754             :     // Construct the appropriate re-sampler.
    2755             :     //
    2756           0 :     CountedPtr<VisibilityResamplerBase> visResampler = new AWVisResampler();
    2757             :     //    CountedPtr<VisibilityResamplerBase> visResampler = new VisibilityResampler();
    2758             : 
    2759             :     //
    2760             :     // Construct and initialize the CF cache object.
    2761             :     //
    2762           0 :     CountedPtr<CFCache> cfcache = new CFCache();
    2763           0 :     cfcache->setCacheDir(cfCacheDirName_p.data());
    2764           0 :     cfcache->initCache2();
    2765             : 
    2766             :     //
    2767             :     // Finally construct the FTMachine with the CFCache, ConvFunc and
    2768             :     // Re-sampler objects.  
    2769             :     //
    2770           0 :     useDoublePrecGrid=(!singlePrec_p);
    2771           0 :     ft_p = new AWProjectWBFT(wprojPlanes_p, cache_p/2, 
    2772             :                              cfcache, awConvFunc, 
    2773             :                              //                      mthVisResampler,
    2774             :                              visResampler,
    2775           0 :                              /*true */doPointing, doPBCorr, 
    2776           0 :                              tile_p, computePAStep_p, pbLimit_p, true,conjBeams_p,
    2777           0 :                              useDoublePrecGrid);
    2778             :       
    2779           0 :     ((AWProjectWBFT *)ft_p)->setObservatoryLocation(mLocation_p);
    2780             :     //
    2781             :     // Explicit type casting of ft_p does not look good.  It does not
    2782             :     // pick up the setPAIncrement() method of PBWProjectFT without
    2783             :     // this
    2784             :     //
    2785             :     // os << LogIO::NORMAL << "Setting PA increment to " << parAngleInc_p.getValue("deg") << " deg" << endl;
    2786             : 
    2787             :     //    ((AWProjectFT *)ft_p)->setPAIncrement(parAngleInc_p);
    2788           0 :     Quantity rotateOTF(rotPAStep_p,"deg");
    2789           0 :     ((AWProjectFT *)ft_p)->setPAIncrement(Quantity(computePAStep_p,"deg"),rotateOTF);
    2790             : 
    2791           0 :     AlwaysAssert(ft_p, AipsError);
    2792           0 :     cft_p = new SimpleComponentFTMachine();
    2793           0 :     AlwaysAssert(cft_p, AipsError);
    2794             : 
    2795           0 :   }
    2796             :   //===============================================================
    2797             :   // A-Projection FTMachine code end here
    2798             :   //===============================================================
    2799         130 :   else if(ftmachine_p=="SetJyGridFT"){
    2800           4 :     Vector<Double> freqs(0);
    2801           4 :     Vector<Double> scale(0);
    2802             :     os << LogIO::DEBUG1
    2803             :        << "SetJy Fourier transforms"
    2804           4 :        << LogIO::POST;
    2805           8 :     ft_p=new SetJyGridFT(cache_p/2, tile_p, gridfunction_p, mLocation_p,
    2806           4 :                     phaseCenter_p,
    2807           4 :                     padding, false, useDoublePrecGrid, freqs, scale);
    2808           4 :     cft_p = new SimpleComponentFTMachine();
    2809             : 
    2810           4 :   }
    2811             :   else {
    2812             :     os << LogIO::NORMAL // Loglevel INFO
    2813             :        << "Performing interferometric gridding..."
    2814         126 :        << LogIO::POST;
    2815             :     os << LogIO::NORMAL1 // gridfunction_p is too cryptic for most users.
    2816         126 :        << "...with convolution function " << gridfunction_p << LogIO::POST;
    2817             :     // Now make the FTMachine
    2818         126 :     if(facets_p>1) {
    2819             :       os << LogIO::NORMAL // Loglevel INFO
    2820             :          << "Multi-facet Fourier transforms will use specified common tangent point:"
    2821           0 :          << LogIO::POST;
    2822           0 :       os << LogIO::NORMAL << tangentPoint() << LogIO::POST; // Loglevel INFO
    2823           0 :       ft_p = new GridFT(cache_p / 2, tile_p, gridfunction_p, mLocation_p,
    2824           0 :                         phaseCenter_p, padding, false, useDoublePrecGrid);
    2825             :       
    2826             :     }
    2827             :     else {
    2828             :       os << LogIO::DEBUG1
    2829             :          << "Single facet Fourier transforms will use image center as tangent points"
    2830         126 :          << LogIO::POST;
    2831         252 :       ft_p = new GridFT(cache_p/2, tile_p, gridfunction_p, mLocation_p,
    2832         126 :                         padding, false, useDoublePrecGrid);
    2833             : 
    2834             :     }
    2835         126 :     AlwaysAssert(ft_p, AipsError);
    2836             :     
    2837         126 :     cft_p = new SimpleComponentFTMachine();
    2838         126 :     AlwaysAssert(cft_p, AipsError);
    2839             :     
    2840             :   }
    2841         252 :   ft_p->setnumthreads(numthreads_p);
    2842         252 :   cft_p->setnumthreads(numthreads_p);
    2843         252 :   ft_p->setSpw(dataspectralwindowids_p, freqFrameValid_p);
    2844         252 :   ft_p->setFreqInterpolation(freqInterpMethod_p);
    2845         252 :   if(doTrackSource_p){
    2846           1 :     ft_p->setMovingSource(trackDir_p);
    2847             :   }
    2848         252 :   ft_p->setSpwChanSelection(spwchansels_p);
    2849         252 :   ft_p->setSpwFreqSelection(mssFreqSel_p);
    2850             : 
    2851             :   /******* Start MTFT code ********/
    2852             :   // MultiTermFT is a container for an FTMachine of any type.
    2853             :   //    It will apply Taylor-polynomial weights during gridding and degridding
    2854             :   //    and will do multi-term grid-correction (normalizations).
    2855             :   //    (1) ft_p already holds an FT of the correct type
    2856             :   //    (2) If nterms>1, create a new MultiTermFT using ft_p, and reassign ft_p. 
    2857             :   // Currently, Multi-Term applies only to wideband imaging.
    2858         252 :   if( ntaylor_p > 1 )
    2859             :   { 
    2860             :     //cout << "UUU : Creating a Multi-Term FT machine containing " << ftmachine_p << endl;
    2861             :     FTMachine *tempftm;
    2862           0 :     if ( useNewMTFT_p == false ) 
    2863             :       {
    2864           0 :         tempftm = new MultiTermFT(ft_p, ft_p->name(), ntaylor_p, reffreq_p);
    2865             :       }
    2866             :     else
    2867             :       {
    2868           0 :         tempftm = new NewMultiTermFT(ft_p, ntaylor_p, reffreq_p);
    2869             :       }
    2870           0 :      ft_p = tempftm;
    2871             :   }
    2872             :   /******* End MTFT code ********/
    2873             : 
    2874         252 :   return true;
    2875         252 : }
    2876             : 
    2877         122 : String Imager::tangentPoint()
    2878             : {
    2879         122 :   MVAngle mvRa=phaseCenter_p.getAngle().getValue()(0);
    2880         122 :   MVAngle mvDec=phaseCenter_p.getAngle().getValue()(1);
    2881         122 :   ostringstream oos;
    2882         122 :   oos << "     ";
    2883         122 :   Int widthRA=20;
    2884         122 :   Int widthDec=20;
    2885         122 :   oos.setf(ios::left, ios::adjustfield);
    2886         122 :   oos.width(widthRA);  oos << mvRa(0.0).string(MVAngle::TIME,8);
    2887         122 :   oos.width(widthDec); oos << mvDec.string(MVAngle::DIG2,8);
    2888         122 :   oos << "     "
    2889         122 :       << MDirection::showType(phaseCenter_p.getRefPtr()->getType());
    2890         244 :   return String(oos);
    2891         122 : }
    2892             : 
    2893         284 : Bool Imager::removeTable(const String& tablename) {
    2894             :   
    2895         568 :   LogIO os(LogOrigin("imager", "removeTable()", WHERE));
    2896             :   
    2897         284 :   if(Table::isReadable(tablename)) {
    2898           0 :     if (! Table::isWritable(tablename)) {
    2899             :       os << LogIO::SEVERE << "Table " << tablename
    2900           0 :          << " is not writable!: cannot alter it" << LogIO::POST;
    2901           0 :       return false;
    2902             :     }
    2903             :     else {
    2904           0 :       if (Table::isOpened(tablename)) {
    2905             :         os << LogIO::SEVERE << "Table " << tablename
    2906             :            << " is already open in the process. It needs to be closed first"
    2907           0 :            << LogIO::POST;
    2908           0 :           return false;
    2909             :       } else {
    2910           0 :         Table table(tablename, Table::Update);
    2911           0 :         if (table.isMultiUsed()) {
    2912             :           os << LogIO::SEVERE << "Table " << tablename
    2913             :              << " is already open in another process. It needs to be closed first"
    2914           0 :              << LogIO::POST;
    2915           0 :             return false;
    2916             :         } else {
    2917           0 :           Table table(tablename, Table::Delete);
    2918           0 :         }
    2919           0 :       }
    2920             :     }
    2921             :   }
    2922         284 :   return true;
    2923         284 : }
    2924             : 
    2925           0 : Bool Imager::updateSkyModel(const Vector<String>& model,
    2926             :                             const String complist) {
    2927           0 :   LogIO os(LogOrigin("imager", "updateSkyModel()", WHERE));
    2928           0 :   if(redoSkyModel_p)
    2929           0 :     throw(AipsError("Programming error: update skymodel is called without a valid skymodel"));
    2930           0 :   Bool coordMatch=true; 
    2931           0 :   for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
    2932           0 :     CoordinateSystem cs=(sm_p->image(thismodel)).coordinates();
    2933           0 :     coordMatch= coordMatch || checkCoord(cs, model(thismodel));
    2934             :     ///return false if any fails anyways
    2935           0 :     if(!coordMatch)
    2936           0 :       return false;
    2937           0 :     if(model(thismodel)=="") {
    2938             :       os << LogIO::SEVERE << "Need a name for model "
    2939           0 :          << model << LogIO::POST;
    2940           0 :       return false;
    2941             :     }
    2942             :     else {
    2943           0 :       if(!Table::isReadable(model(thismodel))) {
    2944             :         os << LogIO::SEVERE << model(thismodel) << "is unreadable"
    2945           0 :            << model << LogIO::POST;
    2946           0 :         return false;
    2947             :       }
    2948             :     }
    2949           0 :     images_p[thismodel]=0;
    2950           0 :     images_p[thismodel]=new PagedImage<Float>(model(thismodel));
    2951           0 :     AlwaysAssert(!images_p[thismodel].null(), AipsError);
    2952           0 :     sm_p->updatemodel(thismodel, *images_p[thismodel]);
    2953           0 :   } 
    2954           0 :   if((complist !="") && Table::isReadable(complist)){
    2955           0 :       ComponentList cl(Path(complist), true);
    2956           0 :       sm_p->updatemodel(cl);
    2957           0 :     }
    2958           0 :   return true;
    2959           0 : }
    2960             : 
    2961           0 : Bool Imager::createSkyEquation(const String complist) 
    2962             : {
    2963           0 :   Vector<String> image;
    2964           0 :   Vector<String> mask;
    2965           0 :   Vector<String> fluxMask;
    2966           0 :   Vector<Bool> fixed;
    2967           0 :   return createSkyEquation(image, fixed, mask, fluxMask, complist);
    2968           0 : }
    2969             : 
    2970         124 : Bool Imager::createSkyEquation(const Vector<String>& image,
    2971             :                                const String complist) 
    2972             : {
    2973         124 :   Vector<Bool> fixed(image.nelements()); fixed=false;
    2974         124 :   Vector<String> mask(image.nelements()); mask="";
    2975         124 :   Vector<String> fluxMask(image.nelements()); fluxMask="";
    2976         248 :   return createSkyEquation(image, fixed, mask, fluxMask, complist);
    2977         124 : }
    2978             : 
    2979           0 : Bool Imager::createSkyEquation(const Vector<String>& image, const Vector<Bool>& fixed,
    2980             :                                const String complist) 
    2981             : {
    2982           0 :   Vector<String> mask(image.nelements()); mask="";
    2983           0 :   Vector<String> fluxMask(image.nelements()); fluxMask="";
    2984           0 :   return createSkyEquation(image, fixed, mask, fluxMask, complist);
    2985           0 : }
    2986             : 
    2987           0 : Bool Imager::createSkyEquation(const Vector<String>& image, const Vector<Bool>& fixed,
    2988             :                                const Vector<String>& mask,
    2989             :                                const String complist) 
    2990             : {
    2991           0 :   Vector<String> fluxMask(image.nelements()); fluxMask="";
    2992           0 :   return createSkyEquation(image, fixed, mask, fluxMask, complist);
    2993           0 : }
    2994             : 
    2995         124 : Bool Imager::createSkyEquation(const Vector<String>& image,
    2996             :                                const Vector<Bool>& fixed,
    2997             :                                const Vector<String>& mask,
    2998             :                                const Vector<String>& fluxMask,
    2999             :                                const String complist)
    3000             : {
    3001             :  
    3002         124 :   if(!valid()) return false;
    3003             : 
    3004         248 :   LogIO os(LogOrigin("imager", "createSkyEquation()", WHERE));
    3005             :   
    3006             :   // If there is no sky model, we'll make one:
    3007             : 
    3008         124 :   if(sm_p==0) {
    3009         124 :     if((facets_p >1)){
    3010             :       // Support serial and parallel specializations
    3011           0 :       setWFCleanImageSkyModel();
    3012             :     }
    3013         124 :     else if(ntaylor_p>1){
    3014             :       // Init the msmfs sky-model so that Taylor weights are triggered in CubeSkyEqn
    3015           0 :       sm_p = new WBCleanImageSkyModel(ntaylor_p, 1 ,reffreq_p);
    3016             :     }
    3017             :     else {
    3018         124 :       sm_p = new CleanImageSkyModel();
    3019             :     }
    3020             :   }
    3021         124 :   AlwaysAssert(sm_p, AipsError);
    3022             :   //Now lets tell it how to use memory and templattices
    3023         124 :   sm_p->setMemoryUse(avoidTempLatt_p);
    3024         124 :   if(imageTileVol_p > 1000)
    3025           0 :     sm_p->setTileVol(imageTileVol_p);
    3026             : 
    3027             :   // Read data pol rep from the MS. This is also done in imagecoordinates().
    3028             :   // This code segment is repeated here because imagecoordinates
    3029             :   // is not always called before SkyModel is made (im.ft).
    3030             :   // Note : This should go into a function.
    3031             :   {
    3032         124 :     MSColumns msc(*ms_p);
    3033         124 :     Vector<String> polType=msc.feed().polarizationType()(0);
    3034         238 :     if (polType(0)!="X" && polType(0)!="Y" &&
    3035         238 :         polType(0)!="R" && polType(0)!="L") {
    3036             :        os << LogIO::WARN << "Unknown stokes types in feed table: ["
    3037           0 :        << polType(0) << ", " << polType(1) << "]" << endl
    3038           0 :        << "Results open to question!" << LogIO::POST;
    3039             :     }
    3040             :   
    3041         124 :     if (polType(0)=="X" || polType(0)=="Y") {
    3042          67 :       polRep_p=StokesImageUtil::LINEAR;
    3043             :       os << LogIO::DEBUG1 
    3044          67 :           << "Preferred polarization representation is linear" << LogIO::POST;
    3045             :     }
    3046             :     else {
    3047          57 :       polRep_p=StokesImageUtil::CIRCULAR;
    3048             :       os << LogIO::DEBUG1
    3049          57 :          << "Preferred polarization representation is circular" << LogIO::POST;
    3050             :     }
    3051         124 :   }// end of reading-in polRep_p from the MS
    3052             : 
    3053             :   // Send the data correlation type to the SkyModel
    3054             :   // This needs to be done before the first call to 'ImageSkyModel::cImage()'
    3055         124 :    os << LogIO::DEBUG1 << "Data PolRep in Imager2.cc::createSkyEquation : " << polRep_p << LogIO::POST;
    3056         124 :    sm_p->setDataPolFrame(polRep_p);
    3057             : 
    3058             : 
    3059             :   // Add the componentlist
    3060             :   // cerr << "COMPLIST " << complist << endl;
    3061         124 :   if(complist!="") {
    3062          98 :     if(!Table::isReadable(complist)) {
    3063             :       os << LogIO::SEVERE << "ComponentList " << complist
    3064           0 :          << " not readable" << LogIO::POST;
    3065           0 :       return false;
    3066             :     }
    3067          98 :     if(componentList_p){
    3068           0 :       delete componentList_p;
    3069           0 :       componentList_p=0;
    3070             :     }
    3071          98 :     componentList_p=new ComponentList(complist, true);
    3072          98 :     if(componentList_p==0) {
    3073             :       os << LogIO::SEVERE << "Cannot create ComponentList from " << complist
    3074           0 :          << LogIO::POST;
    3075           0 :       return false;
    3076             :     }
    3077          98 :     if(!sm_p->add(*componentList_p)) {
    3078             :       os << LogIO::SEVERE << "Cannot add ComponentList " << complist
    3079           0 :          << " to SkyModel" << LogIO::POST;
    3080           0 :       return false;
    3081             :     }
    3082             :     os << LogIO::NORMAL // Loglevel INFO
    3083          98 :        << "Processing after subtracting componentlist " << complist << LogIO::POST;
    3084             :   }
    3085             :   else {
    3086          26 :     delete componentList_p;
    3087          26 :     componentList_p=0;
    3088             :   }
    3089             :  
    3090             :   // Make image with the required shape and coordinates only if
    3091             :   // they don't exist yet
    3092         124 :   nmodels_p=image.nelements();
    3093             : 
    3094             :   // Remove degenerate case (due to user interface?)
    3095         124 :   if((nmodels_p==1)&&(image(0)=="")) {
    3096           4 :     nmodels_p=0;
    3097             :   }
    3098         124 :   if(nmodels_p>0) {
    3099          27 :     images_p.resize(nmodels_p); 
    3100          27 :     masks_p.resize(nmodels_p);  
    3101          27 :     fluxMasks_p.resize(nmodels_p); 
    3102          27 :     residuals_p.resize(nmodels_p); 
    3103          55 :     for (Int model=0;model<Int(nmodels_p);++model) {
    3104          28 :       if(image(model)=="") {
    3105             :         os << LogIO::SEVERE << "Need a name for model "
    3106           0 :            << model << LogIO::POST;
    3107           0 :         return false;
    3108             :       }
    3109             :       else {
    3110          28 :         if(!Table::isReadable(image(model))) {
    3111           0 :           if(!assertDefinedImageParameters()) return false;
    3112           0 :           make(image(model));
    3113             :         }
    3114             :       }
    3115          28 :       images_p[model]=0;
    3116          28 :       images_p[model]=new PagedImage<Float>(image(model));
    3117          28 :       AlwaysAssert(!images_p[model].null(), AipsError);
    3118             : 
    3119             :       //Determining the number of XFR
    3120          28 :       Int numOfXFR=nmodels_p+1;
    3121          28 :       if(datafieldids_p.nelements() >0)
    3122          14 :         numOfXFR=datafieldids_p.nelements()*nmodels_p + 1;
    3123          28 :       if(squintType_p != BeamSquint::NONE){
    3124          22 :         if(parAngleInc_p.getValue("deg") >0 ){
    3125          22 :           numOfXFR= numOfXFR* Int(360/parAngleInc_p.getValue("deg"));
    3126             :         }       
    3127             :         else{
    3128           0 :         numOfXFR= numOfXFR*10;
    3129             :         }
    3130             :       }
    3131          28 :       if((sm_p->add(*images_p[model], numOfXFR))!=model) {
    3132           0 :         os << LogIO::SEVERE << "Error adding model " << model << LogIO::POST;
    3133           0 :         return false;
    3134             :       }
    3135             :  
    3136          28 :       fluxMasks_p[model]=0;
    3137          28 :       if(fluxMask(model)!=""&&Table::isReadable(fluxMask(model))) {
    3138           0 :         fluxMasks_p[model]=new PagedImage<Float>(fluxMask(model));
    3139           0 :         AlwaysAssert(!fluxMasks_p[model].null(), AipsError);
    3140           0 :         if(!sm_p->addFluxMask(model, *fluxMasks_p[model])) {
    3141             :           os << LogIO::SEVERE << "Error adding flux mask " << model
    3142           0 :              << " : " << fluxMask(model) << LogIO::POST;
    3143           0 :           return false;
    3144             :         }
    3145             :       }
    3146          28 :       residuals_p[model]=0;
    3147             :     }
    3148          27 :     addMasksToSkyEquation(mask, fixed);
    3149             :   }
    3150             :   
    3151             :   // Always need a VisSet and an FTMachine
    3152         124 :   if (!ft_p)
    3153         124 :     createFTMachine();
    3154             :   
    3155             :   // Now set up the SkyEquation
    3156         124 :   AlwaysAssert(sm_p, AipsError);
    3157             :   // AlwaysAssert(vs_p, AipsError);
    3158         124 :   AlwaysAssert(rvi_p, AipsError);
    3159         124 :   AlwaysAssert(ft_p, AipsError);
    3160         124 :   AlwaysAssert(cft_p, AipsError);
    3161             :  
    3162             :   // Setup the sky equation
    3163         124 :   setSkyEquation();
    3164             : 
    3165             :   // If primary-beams are needed, force the fluxScale images held by
    3166             :   // the SkyModel classes to be allocated/initialized.
    3167         124 :   if(doVP_p){
    3168           0 :     if( (sm_p->numberOfModels() > 0) && (ft_p->name() != "MosaicFT")) 
    3169           0 :         sm_p->mandateFluxScale(0);
    3170             :     }
    3171             :  
    3172             : 
    3173             :   /* // Commented out by URV (4 Apr 2012) : Redundant Code.
    3174             :   // This block determines which SkyEquation is to be used.
    3175             :   // We are using a mf* algorithm and there is more than one image
    3176             :       
    3177             :   if (doMultiFields_p && multiFields_p) {
    3178             :     // Mosaicing case
    3179             :     if(doVP_p){
    3180             :       //bypassing the minimum size FT stuff as its broken till its fixed
    3181             :       //se_p=new MosaicSkyEquation(*sm_p, *vs_p, *ft_p, *cft_p);
    3182             :       
    3183             :       setSkyEquation();
    3184             :       if(ft_p->name() != "MosaicFT") 
    3185             :         sm_p->mandateFluxScale(0);
    3186             :       os << LogIO::NORMAL // Loglevel INFO
    3187             :          << "Mosaicing multiple fields with simple sky equation" << LogIO::POST;
    3188             :     }
    3189             :     // mosaicing with no vp correction
    3190             :     else{
    3191             :       setSkyEquation();
    3192             :       os << LogIO::NORMAL // Loglevel INFO
    3193             :          << "Processing multiple fields with simple sky equation" << LogIO::POST;
    3194             :       os << LogIO::WARN
    3195             :          << "Voltage Pattern is not set: will not correct for primary beam"
    3196             :          << LogIO::POST;
    3197             :       doMultiFields_p=false;
    3198             :     }
    3199             :   }
    3200             :   // We are not using an mf* algorithm or there is only one image
    3201             :   else {
    3202             :     // Support serial and parallel specializations
    3203             :     if((facets_p >1)){
    3204             :         setSkyEquation();
    3205             :         //se_p=new SkyEquation(*sm_p, *vs_p, *ft_p, *cft_p);
    3206             :         os << LogIO::NORMAL // Loglevel INFO
    3207             :            << "Processing multiple facets with simple sky equation" << LogIO::POST;
    3208             :     }
    3209             :     // Mosaicing
    3210             :     else if(doVP_p) {
    3211             :       //Bypassing the mosaicskyequation to the slow version for now.
    3212             :       //      se_p=new MosaicSkyEquation(*sm_p, *vs_p, *ft_p, *cft_p);
    3213             :       
    3214             :       setSkyEquation();
    3215             :       if(ft_p->name() != "MosaicFT") 
    3216             :         sm_p->mandateFluxScale(0);
    3217             :       os << LogIO::NORMAL // Loglevel PROGRESS
    3218             :          << "Mosaicing single field with simple sky equation" << LogIO::POST;      
    3219             :     }
    3220             :     // Default
    3221             :     else {
    3222             :       setSkyEquation();
    3223             :       os << LogIO::DEBUG1
    3224             :          << "Processing single field with simple sky equation" << LogIO::POST;    
    3225             :     } 
    3226             :   }
    3227             : 
    3228             :   */
    3229             : 
    3230             : 
    3231             :   //os.localSink().flush();
    3232             :   //For now force none sault weighting with mosaic ft machine
    3233             :   
    3234         124 :   String scaleType=scaleType_p;
    3235         124 :   if(ft_p->name()=="MosaicFT")
    3236           0 :     scaleType="NONE";
    3237             :   
    3238         124 :   se_p->setImagePlaneWeighting(scaleType, minPB_p, constPB_p);
    3239         124 :   se_p->doFlatNoise(flatnoise_p);
    3240             :   
    3241         124 :   AlwaysAssert(se_p, AipsError);
    3242             : 
    3243             :   // Now add any SkyJones that are needed
    3244         124 :   if(doVP_p && (ft_p->name()!="MosaicFT")) {
    3245           0 :     MSColumns msc(*ms_p);
    3246           0 :     if (doDefaultVP_p) {
    3247           0 :       vp_p=new VPSkyJones(msc, true, parAngleInc_p, squintType_p, skyPosThreshold_p);
    3248             :     } else { 
    3249           0 :       Table vpTable( vpTableStr_p ); 
    3250           0 :       vp_p=new VPSkyJones(msc, vpTable, parAngleInc_p, squintType_p, skyPosThreshold_p);
    3251           0 :     }
    3252           0 :     se_p->setSkyJones(*vp_p);
    3253           0 :   }
    3254             :   else {
    3255         124 :     vp_p=0;
    3256             :   }
    3257         124 :   return true;  
    3258         124 : }
    3259             : 
    3260           0 : Bool Imager::addResiduals(const Vector<String>& imageNames) {
    3261           0 :   Bool retval=true;
    3262           0 :   residuals_p.resize(imageNames.nelements(), true, false);
    3263           0 :   for (Int thismodel=0;thismodel<Int(imageNames.nelements());++thismodel) {
    3264           0 :     if(imageNames(thismodel)!="") {
    3265           0 :       residuals_p[thismodel]=0;
    3266           0 :       if(Table::isWritable(imageNames(thismodel))){
    3267           0 :         residuals_p[thismodel]=new PagedImage<Float>(imageNames(thismodel));
    3268           0 :         if(!(residuals_p[thismodel]->shape()).isEqual(images_p[thismodel]->shape())){
    3269           0 :           residuals_p[thismodel]=0;
    3270           0 :           removeTable(imageNames(thismodel));
    3271             :         }
    3272             :       }
    3273           0 :       if(residuals_p[thismodel].null()){
    3274           0 :         if(Table::isReadable(imageNames(thismodel)))
    3275           0 :            removeTable(imageNames(thismodel));
    3276           0 :         residuals_p[thismodel]=
    3277           0 :           new PagedImage<Float> (TiledShape(images_p[thismodel]->shape(), 
    3278           0 :                                             images_p[thismodel]->niceCursorShape()),
    3279           0 :                                images_p[thismodel]->coordinates(),
    3280           0 :                                  imageNames(thismodel));
    3281           0 :         AlwaysAssert(!residuals_p[thismodel].null(), AipsError);
    3282           0 :         residuals_p[thismodel]->setUnits(Unit("Jy/beam"));
    3283             :       }
    3284           0 :       if(residuals_p[thismodel].null()) 
    3285           0 :         retval=false;
    3286             :     }
    3287             :     else{
    3288           0 :       retval=false;
    3289             :     }
    3290             :   }
    3291           0 :   return retval;
    3292             : } 
    3293             : // Tell the sky model to use the specified images as the residuals    
    3294           0 : Bool Imager::addResidualsToSkyEquation(const Vector<String>& imageNames) {
    3295             :   
    3296           0 :   addResiduals(imageNames);
    3297           0 :   for (Int thismodel=0;thismodel<Int(imageNames.nelements());++thismodel) {
    3298           0 :     if(imageNames(thismodel)!="") 
    3299           0 :       sm_p->addResidual(thismodel, *residuals_p[thismodel]);   
    3300             :   }
    3301           0 :   return true;
    3302             : } 
    3303             : 
    3304        2576 : void Imager::destroySkyEquation() 
    3305             : {
    3306        2576 :   if(se_p) delete se_p; se_p=0;
    3307        2576 :   if(sm_p) delete sm_p; sm_p=0;
    3308        2576 :   if(vp_p) delete vp_p; vp_p=0;
    3309        2576 :   if(gvp_p) delete gvp_p; gvp_p=0;
    3310             :   
    3311        2576 :   if(componentList_p) delete componentList_p; componentList_p=0;
    3312             :  
    3313             :   
    3314        2618 :   for (Int model=0;model<Int(nmodels_p); ++model) {
    3315             :     //As these are CountedPtrs....just assigning them to NULL 
    3316             :     //get the objects out of context
    3317          42 :     if(!images_p[model].null())  
    3318          28 :       images_p[model]=0;
    3319             :     
    3320          42 :     if(!masks_p[model].null()) 
    3321           0 :       masks_p[model]=0;
    3322             :  
    3323          42 :    if(!fluxMasks_p[model].null()) 
    3324           0 :      fluxMasks_p[model]=0;
    3325             :     
    3326          42 :    if(!residuals_p[model].null()) 
    3327           0 :      residuals_p[model]=0;
    3328             :   }
    3329             :   
    3330        2576 :   redoSkyModel_p=true;
    3331        2576 : }
    3332             : 
    3333        1446 : Bool Imager::assertDefinedImageParameters() const
    3334             : {
    3335        2892 :   LogIO os(LogOrigin("imager", "if(!assertDefinedImageParameters()", WHERE));
    3336        1446 :   if(!setimaged_p) { 
    3337             :     os << LogIO::SEVERE << "Image parameters not yet set: use im.defineimage."
    3338           0 :        << LogIO::POST;
    3339           0 :     return false;
    3340             :   }
    3341        1446 :   return true;
    3342        1446 : }
    3343             : 
    3344        2256 : Bool Imager::valid() const {
    3345        4512 :   LogIO os(LogOrigin("imager", "if(!valid()) return false", WHERE));
    3346        2256 :   if(ms_p.null()) {
    3347             :     os << LogIO::SEVERE << "Program logic error: MeasurementSet pointer ms_p not yet set"
    3348           0 :        << LogIO::POST;
    3349           0 :     return false;
    3350             :   }
    3351        2256 :   if(mssel_p.null()) {
    3352             :     os << LogIO::SEVERE << "Program logic error: MeasurementSet pointer mssel_p not yet set"
    3353           0 :        << LogIO::POST;
    3354           0 :     return false;
    3355             :   }
    3356        2256 :   if(!rvi_p) {
    3357             :     os << LogIO::SEVERE << "Program logic error: VisibilityIterator not yet set"
    3358           0 :        << LogIO::POST;
    3359           0 :     return false;
    3360             :   }
    3361        2256 :   return true;
    3362        2256 : }
    3363             : 
    3364             : 
    3365          27 : Bool Imager::addMasksToSkyEquation(const Vector<String>& mask, const Vector<Bool>& fixed){
    3366          54 :   LogIO os(LogOrigin("imager", "addMasksToSkyEquation()", WHERE));
    3367             : 
    3368          55 :   for(Int model=0 ;model < nmodels_p; ++model){
    3369             : 
    3370             :     
    3371          28 :     if((Int(fixed.nelements())>model) && fixed(model)) {
    3372             :       os << LogIO::NORMAL // Loglevel INFO
    3373           0 :          << "Model " << model << " will be held fixed" << LogIO::POST;
    3374           0 :       sm_p->fix(model);
    3375             :     }     
    3376             :     /*
    3377             :     if(!(masks_p[model].null())) delete masks_p[model];
    3378             :     masks_p[model]=0;
    3379             :     */
    3380          28 :       if(mask(model)!=""&&Table::isReadable(mask(model))) {
    3381           0 :         masks_p[model]=new PagedImage<Float>(mask(model));
    3382           0 :         AlwaysAssert(!masks_p[model].null(), AipsError);
    3383           0 :         if(!sm_p->addMask(model, *masks_p[model])) {
    3384             :           os << LogIO::SEVERE << "Error adding mask " << model
    3385           0 :              << " : " << mask(model) << LogIO::POST;
    3386           0 :           return false;
    3387             :         }
    3388             :       }
    3389             :   }
    3390          27 :   return true;
    3391          27 : }
    3392             : 
    3393             : void
    3394        8624 : Imager::openSubTable (const Table & otherTable, Table & table, const TableLock & tableLock)
    3395             : {
    3396        8624 :     if (otherTable.isNull()){
    3397             : 
    3398             :         // otherTable does not exist so leave things be
    3399             : 
    3400             :     }
    3401        7366 :     else if (otherTable.tableType() == Table::Memory){
    3402             : 
    3403           0 :         table = otherTable;
    3404             : 
    3405             :     }
    3406             :     else{
    3407             : 
    3408             :         // Reopen (potentially) the subtable with the desired locking
    3409             : 
    3410        7366 :         table = Table (otherTable.tableName(), tableLock);
    3411             :     }
    3412        8624 : }
    3413             : 
    3414             : Bool
    3415         480 : Imager::openSubTables()
    3416             : {
    3417             :     // These variables will already have copied in the Tables from
    3418             :     // the MS specified in open.  If they are not memory resident
    3419             :     // subtables then replace them with table objects having the
    3420             :     // UserNoReadLocking attribute.
    3421             : 
    3422         480 :     TableLock tableLock (TableLock::UserNoReadLocking);
    3423             : 
    3424         480 :     openSubTable (ms_p->antenna(), antab_p, tableLock);
    3425         480 :     openSubTable (ms_p->dataDescription (), datadesctab_p, tableLock);
    3426         480 :     openSubTable (ms_p->doppler(), dopplertab_p, tableLock);
    3427         480 :     openSubTable (ms_p->feed(), feedtab_p, tableLock);
    3428         480 :     openSubTable (ms_p->field(), fieldtab_p, tableLock);
    3429         480 :     openSubTable (ms_p->flagCmd(), flagcmdtab_p, tableLock);
    3430         480 :     openSubTable (ms_p->freqOffset(), freqoffsettab_p, tableLock);
    3431         480 :     openSubTable (ms_p->observation(), obstab_p, tableLock);
    3432         480 :     openSubTable (ms_p->pointing(), pointingtab_p, tableLock);
    3433         480 :     openSubTable (ms_p->polarization(), poltab_p, tableLock);
    3434         480 :     openSubTable (ms_p->processor(), proctab_p, tableLock);
    3435         480 :     openSubTable (ms_p->source(), sourcetab_p, tableLock);
    3436         480 :     openSubTable (ms_p->spectralWindow(), spwtab_p, tableLock);
    3437         480 :     openSubTable (ms_p->state(), statetab_p, tableLock);
    3438         480 :     openSubTable (ms_p->sysCal(), syscaltab_p, tableLock);
    3439         480 :     openSubTable (ms_p->weather(), weathertab_p, tableLock);
    3440             : 
    3441             :     // Handle the history table
    3442             : 
    3443         480 :     if(ms_p->isWritable()){
    3444             : 
    3445         480 :         if(!(Table::isReadable(ms_p->historyTableName()))){
    3446             : 
    3447             :             // setup a new table in case its not there
    3448           0 :             TableRecord &kws = ms_p->rwKeywordSet();
    3449           0 :             SetupNewTable historySetup(ms_p->historyTableName(),
    3450           0 :                                        MSHistory::requiredTableDesc(),Table::New);
    3451           0 :             kws.defineTable(MS::keywordName(MS::HISTORY), Table(historySetup));
    3452             : 
    3453           0 :         }
    3454        1440 :         historytab_p=Table(ms_p->historyTableName(),
    3455         960 :                            TableLock(TableLock::UserNoReadLocking), Table::Update);
    3456             : 
    3457         480 :         hist_p= new MSHistoryHandler(*ms_p, "imager");
    3458             :     }
    3459             : 
    3460         480 :     return true;
    3461             : 
    3462             : }
    3463             : 
    3464        1764 : Bool Imager::lock(){
    3465             : 
    3466             :   Bool ok; 
    3467        1764 :   ok=true;
    3468        1764 :   if(lockCounter_p == 0){
    3469             : 
    3470        1357 :     ok= ok && (ms_p->lock());
    3471        1357 :     ok= ok && antab_p.lock(false);
    3472        1357 :     ok= ok && datadesctab_p.lock(false);
    3473        1357 :     ok= ok && feedtab_p.lock(false);
    3474        1357 :     ok= ok && fieldtab_p.lock(false);
    3475        1357 :     ok= ok && obstab_p.lock(false);
    3476        1357 :     ok= ok && poltab_p.lock(false);
    3477        1357 :     ok= ok && proctab_p.lock(false);
    3478        1357 :     ok= ok && spwtab_p.lock(false);
    3479        1357 :     ok= ok && statetab_p.lock(false);
    3480        1357 :     if(!dopplertab_p.isNull())
    3481         428 :       ok= ok && dopplertab_p.lock(false);
    3482        1357 :     if(!flagcmdtab_p.isNull())
    3483        1357 :       ok= ok && flagcmdtab_p.lock(false);
    3484        1357 :     if(!freqoffsettab_p.isNull())
    3485         426 :       ok= ok && freqoffsettab_p.lock(false);
    3486        1357 :     if(!historytab_p.isNull())
    3487        1357 :       ok= ok && historytab_p.lock(false);
    3488        1357 :     if(!pointingtab_p.isNull())
    3489        1357 :       ok= ok && pointingtab_p.lock(false);
    3490        1357 :     if(!sourcetab_p.isNull())
    3491        1357 :       ok= ok && sourcetab_p.lock(false);
    3492        1357 :     if(!syscaltab_p.isNull())
    3493         633 :       ok= ok && syscaltab_p.lock(false);
    3494        1357 :     if(!weathertab_p.isNull())
    3495         645 :       ok= ok && weathertab_p.lock(false);
    3496             :  
    3497             :   }
    3498        1764 :   ++lockCounter_p;
    3499             : 
    3500        1764 :   return ok ; 
    3501             : }
    3502             : 
    3503        3423 : Bool Imager::unlock(){
    3504             : 
    3505        3423 :   if(lockCounter_p==1){
    3506        1357 :     ms_p->unlock();
    3507        1357 :     antab_p.unlock();
    3508        1357 :     datadesctab_p.unlock();
    3509        1357 :     feedtab_p.unlock();
    3510        1357 :     fieldtab_p.unlock();
    3511        1357 :     obstab_p.unlock();
    3512        1357 :     poltab_p.unlock();
    3513        1357 :     proctab_p.unlock();
    3514        1357 :     spwtab_p.unlock();
    3515        1357 :     statetab_p.unlock();
    3516        1357 :     if(!dopplertab_p.isNull())
    3517         428 :       dopplertab_p.unlock();
    3518        1357 :     if(!flagcmdtab_p.isNull())
    3519        1357 :       flagcmdtab_p.unlock();
    3520        1357 :     if(!freqoffsettab_p.isNull())
    3521         426 :     freqoffsettab_p.unlock();
    3522        1357 :     if(!historytab_p.isNull())
    3523        1357 :       historytab_p.unlock();
    3524        1357 :     if(!pointingtab_p.isNull())
    3525        1357 :       pointingtab_p.unlock();
    3526        1357 :     if(!sourcetab_p.isNull())
    3527        1357 :       sourcetab_p.unlock();
    3528        1357 :     if(!syscaltab_p.isNull())
    3529         633 :       syscaltab_p.unlock();
    3530        1357 :     if(!weathertab_p.isNull())
    3531         645 :       weathertab_p.unlock();
    3532             :   }
    3533        3493 :   for (Int thismodel=0;thismodel<Int(images_p.nelements());++thismodel) {
    3534          70 :     if ((images_p.nelements() > uInt(thismodel)) && (!images_p[thismodel].null())) {
    3535          14 :       images_p[thismodel]->table().relinquishAutoLocks(true);
    3536          14 :       images_p[thismodel]->table().unlock();
    3537             :     }
    3538          70 :     if ((residuals_p.nelements()> uInt(thismodel)) && (!residuals_p[thismodel].null())) {
    3539           0 :       residuals_p[thismodel]->table().relinquishAutoLocks(true);
    3540           0 :       residuals_p[thismodel]->table().unlock();
    3541             :     }
    3542          70 :     if ((masks_p.nelements()> uInt(thismodel)) && (!masks_p[thismodel].null())) {
    3543           0 :       masks_p[thismodel]->table().relinquishAutoLocks(true);
    3544           0 :       masks_p[thismodel]->table().unlock();
    3545             :     }
    3546             :   }
    3547        3423 :   if(lockCounter_p > 0 )
    3548        1764 :     --lockCounter_p;
    3549        3423 :   return true ; 
    3550             : }
    3551             : 
    3552         543 : Bool Imager::selectDataChannel(Vector<Int>& spectralwindowids, 
    3553             :                                String& dataMode, 
    3554             :                                Vector<Int>& dataNchan, 
    3555             :                                Vector<Int>& dataStart, Vector<Int>& dataStep,
    3556             :                                MRadialVelocity& /*mDataStart*/, 
    3557             :                                MRadialVelocity& /*mDataStep*/){
    3558             : 
    3559             : 
    3560             : 
    3561        1086 :   LogIO os(LogOrigin("Imager", "selectDataChannel()", WHERE));
    3562             : 
    3563             : 
    3564         543 :   if(dataMode=="channel") {
    3565         543 :       if (dataNchan.nelements() != spectralwindowids.nelements()){
    3566           0 :         if(dataNchan.nelements()==1){
    3567           0 :           dataNchan.resize(spectralwindowids.nelements(), true);
    3568           0 :           for(uInt k=1; k < spectralwindowids.nelements(); ++k){
    3569           0 :             dataNchan[k]=dataNchan[0];
    3570             :           }
    3571             :         }
    3572             :         else{
    3573             :           os << LogIO::SEVERE 
    3574             :              << "Vector of nchan has to be of size 1 or be of the same shape as spw " 
    3575           0 :              << LogIO::POST;
    3576           0 :           return false; 
    3577             :         }
    3578             :       }
    3579         543 :       if (dataStart.nelements() != spectralwindowids.nelements()){
    3580           0 :         if(dataStart.nelements()==1){
    3581           0 :           dataStart.resize(spectralwindowids.nelements(), true);
    3582           0 :           for(uInt k=1; k < spectralwindowids.nelements(); ++k){
    3583           0 :             dataStart[k]=dataStart[0];
    3584             :           }
    3585             :         }
    3586             :         else{
    3587             :           os << LogIO::SEVERE 
    3588             :              << "Vector of start has to be of size 1 or be of the same shape as spw " 
    3589           0 :              << LogIO::POST;
    3590           0 :           return false; 
    3591             :         }
    3592             :       }
    3593         543 :       if (dataStep.nelements() != spectralwindowids.nelements()){
    3594           0 :         if(dataStep.nelements()==1){
    3595           0 :           dataStep.resize(spectralwindowids.nelements(), true);
    3596           0 :           for(uInt k=1; k < spectralwindowids.nelements(); ++k){
    3597           0 :             dataStep[k]=dataStep[0];
    3598             :           }
    3599             :         }
    3600             :         else{
    3601             :           os << LogIO::SEVERE 
    3602             :              << "Vector of step has to be of size 1 or be of the same shape as spw " 
    3603           0 :              << LogIO::POST;
    3604           0 :           return false; 
    3605             :         }
    3606             :       }
    3607             : 
    3608         543 :       if(spectralwindowids.nelements()>0) {
    3609         543 :         Int nch=0;
    3610        1329 :         for(uInt i=0;i<spectralwindowids.nelements();++i) {
    3611         786 :           Int spwid=spectralwindowids(i);
    3612         786 :           Int numberChan=rvi_p->msColumns().spectralWindow().numChan()(spwid);
    3613         786 :           if(dataStart[i]<0) {
    3614             :             os << LogIO::SEVERE << "Illegal start pixel = " 
    3615           0 :                << dataStart[i]  << " for spw " << spwid
    3616           0 :                << LogIO::POST;
    3617           0 :             return false;
    3618             :           }
    3619             :          
    3620         786 :           if(dataNchan[i]<=0){ 
    3621          87 :             if(dataStep[i] <= 0)
    3622           0 :               dataStep[i]=1;
    3623          87 :             nch=(numberChan-dataStart[i])/Int(dataStep[i])+1;
    3624             :           }
    3625         699 :           else nch = dataNchan[i];
    3626         873 :           while((nch*dataStep[i]+dataStart[i]) > numberChan){
    3627          87 :             --nch;
    3628             :           }
    3629         786 :           Int end = Int(dataStart[i]) + Int(nch-1) * Int(dataStep[i]);
    3630         786 :           if(end < 0 || end > (numberChan)-1) {
    3631           0 :             os << LogIO::SEVERE << "Illegal step pixel = " << dataStep[i]
    3632             :                << " for spw " << spwid
    3633             :                << "\n end channel " << end 
    3634           0 :                << " is out of range " << dataStart[i] << " to " 
    3635             :                << (numberChan-1)
    3636           0 :                << LogIO::POST;
    3637           0 :             return false;
    3638             :           }
    3639             : 
    3640             :           os << LogIO::DEBUG1 // Too contentious for DEBUG1
    3641         786 :              << "Selecting within ";
    3642         786 :           if(nch > 1)
    3643             :             os << nch << " channels, starting at "
    3644         565 :                << dataStart[i]  << ", stepped by " << dataStep[i] << ",";
    3645             :           else
    3646         221 :             os << "channel " << dataStart[i];
    3647         786 :           os << " for spw " << spwid << LogIO::POST;
    3648             :           
    3649             :           ///////////This is totally funked ...does not respect the spw selection
    3650             :           //whatever you do the the ngroups is always all the spw in the ms !!!
    3651             :           //vi.allSelectedSpectralWindows gets borked because of that
    3652             :           //rvi_p->selectChannel(1, Int(dataStart[i]), Int(nch),
    3653             :           //                         Int(dataStep[i]), spwid);
    3654         786 :           dataNchan[i]=nch;
    3655             :         }
    3656             :         /////Temporary replacement via the multims one
    3657         543 :         Block<Vector<Int> > blspw(1);
    3658         543 :         Block<Vector<Int> > blngr(1);
    3659         543 :         Block<Vector<Int> > blstart(1);
    3660         543 :         Block<Vector<Int> > blwid(1);
    3661         543 :         Block<Vector<Int> > blinr(1);
    3662         543 :         blspw[0]=spectralwindowids;
    3663         543 :         blngr[0]=Vector<Int>(spectralwindowids.nelements(),1);
    3664         543 :         blstart[0]=dataStart;
    3665         543 :         blwid=dataNchan;
    3666         543 :         blinr[0]=dataStep;
    3667         543 :         rvi_p->selectChannel(blngr, blstart, blwid,
    3668             :                                      blinr, blspw);
    3669             :         ////////////////////////
    3670             : 
    3671         543 :       } else {
    3672           0 :         VisBufferAutoPtr vb (rvi_p);
    3673           0 :         rvi_p->originChunks ();
    3674           0 :         Int numberChan=vb->msColumns().spectralWindow().numChan()(0);
    3675             : 
    3676           0 :         if(dataNchan[0]<=0){
    3677           0 :           if(dataStep[0] <=0)
    3678           0 :             dataStep[0]=1;
    3679           0 :           dataNchan[0]=(numberChan-dataStart[0])/Int(dataStep[0])+1;
    3680             :           
    3681             :         }
    3682           0 :         while((dataNchan[0]*dataStep[0]+dataStart[0]) > numberChan)
    3683           0 :           --dataNchan[0];
    3684             : 
    3685           0 :         Int end = Int(dataStart[0]) + Int(dataNchan[0]-1) 
    3686           0 :           * Int(dataStep[0]);
    3687           0 :         if(end < 0 || end > (numberChan)-1) {
    3688           0 :           os << LogIO::SEVERE << "Illegal step pixel = " << dataStep[0]
    3689             :              << "\n end channel " << end << " is out of range 1 to " 
    3690             :              << (numberChan-1)
    3691           0 :              << LogIO::POST;
    3692           0 :           return false;
    3693             :         }
    3694           0 :         os << LogIO::DEBUG1 << "Selecting within "<< dataNchan[0] // Loglevel INFO
    3695             :            << " channels, starting at visibility channel "
    3696           0 :          << dataStart[0]  << " stepped by "
    3697           0 :            << dataStep[0] << LogIO::POST;
    3698           0 :       }
    3699             :   }
    3700             :   
    3701             : 
    3702         543 :   return true;
    3703             : 
    3704         543 : }
    3705             : 
    3706             : 
    3707           0 : Bool Imager::checkCoord(const CoordinateSystem& coordsys,  
    3708             :                         const String& imageName){ 
    3709             : 
    3710           0 :   PagedImage<Float> image(imageName);
    3711           0 :   CoordinateSystem imageCoord= image.coordinates();
    3712           0 :   Vector<Int> imageShape= image.shape().asVector();
    3713             : 
    3714           0 :   if(imageShape.nelements() > 3){
    3715           0 :     if(imageShape(3) != imageNchan_p)
    3716           0 :       return false;
    3717             :   }
    3718             :   else{
    3719           0 :     if(imageNchan_p >1)
    3720           0 :       return false;
    3721             :   }
    3722             : 
    3723           0 :   if(imageShape.nelements() > 2){
    3724           0 :     if(imageShape(2) != npol_p)
    3725           0 :       return false;
    3726             :   } 
    3727             :   else{
    3728           0 :     if(npol_p > 1)
    3729           0 :       return false;
    3730             :   }
    3731           0 :   if(imageShape(0) != nx_p)
    3732           0 :     return false;
    3733           0 :   if(imageShape(1) != ny_p)
    3734           0 :     return false;
    3735             : 
    3736             : 
    3737             :  
    3738           0 :   if(!imageCoord.near(coordsys)){
    3739           0 :     return false;
    3740             :   }
    3741             :   
    3742             :   /*
    3743             :   DirectionCoordinate dir1(coordsys.directionCoordinate(0));
    3744             :   DirectionCoordinate dir2(imageCoord.directionCoordinate(0));
    3745             :   if(dir1.increment()(0) != dir2.increment()(0))
    3746             :     return false;
    3747             :   if(dir1.increment()(1) != dir2.increment()(1))
    3748             :     return false;
    3749             :   SpectralCoordinate sp1(coordsys.spectralCoordinate(2));
    3750             :   SpectralCoordinate sp2(imageCoord.spectralCoordinate(2));
    3751             :   if(sp1.increment()(0) != sp2.increment()(0))
    3752             :     return false;
    3753             :   */
    3754           0 :   return true;
    3755           0 : }
    3756             : 
    3757           0 : void Imager::setImageParam(Int& nx, Int& ny, Int& npol, Int& nchan){
    3758             : 
    3759           0 :   nx_p=nx;
    3760           0 :   ny_p=ny;
    3761           0 :   npol_p=npol;
    3762           0 :   nchan_p=nchan;
    3763             : 
    3764           0 : }
    3765             : 
    3766        1023 : void Imager::makeVisSet(MeasurementSet& ms, 
    3767             :                         Bool compress, Bool mosaicOrder){
    3768             : 
    3769        1023 :   if(rvi_p) {
    3770           0 :     delete rvi_p;
    3771           0 :     rvi_p=0;
    3772           0 :     wvi_p=0;
    3773             :   }
    3774             : 
    3775        1023 :   Block<Int> sort(0);
    3776        1023 :   if(mosaicOrder){
    3777           0 :     sort.resize(4);
    3778           0 :     sort[0] = MS::FIELD_ID;
    3779           0 :     sort[1] = MS::ARRAY_ID;
    3780           0 :     sort[2] = MS::DATA_DESC_ID;
    3781           0 :     sort[3] = MS::TIME;
    3782             :  
    3783             :   }
    3784             :   //else use default sort order
    3785             :   else{
    3786        1023 :     sort.resize(4);
    3787        1023 :     sort[0] = MS::ARRAY_ID;
    3788        1023 :     sort[1] = MS::FIELD_ID;
    3789        1023 :     sort[2] = MS::DATA_DESC_ID;
    3790        1023 :     sort[3] = MS::TIME;
    3791             :   }
    3792        1023 :   Matrix<Int> noselection;
    3793        1023 :   Double timeInterval=0.0;
    3794             :   //if you want to use scratch col...make sure they are there
    3795        1023 :   if(useModelCol_p){
    3796             :     //VisSet(ms,sort,noselection,useModelCol_p,timeInterval,compress);
    3797         175 :     VisSetUtil::addScrCols(ms, true, false, true, compress);
    3798             :     //delete keyword models to make sure data column is read
    3799         175 :     VisModelData::clearModel(ms);
    3800             :   }
    3801        1023 :   if(imwgt_p.getType()=="none"){
    3802         480 :       imwgt_p=VisImagingWeight("natural");
    3803             :   }
    3804             : 
    3805        1023 :   if(!ms.isWritable()){
    3806           0 :     rvi_p=new ROVisibilityIterator(ms, sort, timeInterval);
    3807             :   }
    3808             :   else{
    3809        1023 :     wvi_p=new VisibilityIterator(ms, sort, timeInterval);
    3810        1023 :     rvi_p=wvi_p;    
    3811             :   }
    3812        1023 :   rvi_p->useImagingWeight(imwgt_p);
    3813             :   
    3814             :   //////////////////////
    3815             :   //rvi_p->setRowBlocking(35);
    3816             :   ////////////////////
    3817        1023 : }
    3818             : /*
    3819             : void Imager::makeVisSet(MeasurementSet& ms, 
    3820             :                         Bool compress, Bool mosaicOrder){
    3821             : 
    3822             : 
    3823             :   Block<Int> sort(0);
    3824             :   if(mosaicOrder){
    3825             :     sort.resize(4);
    3826             :     sort[0] = MS::FIELD_ID;
    3827             :     sort[1] = MS::ARRAY_ID;
    3828             :     sort[2] = MS::DATA_DESC_ID;
    3829             :     sort[3] = MS::TIME;
    3830             :   }
    3831             :   //else use default sort order
    3832             :   else{
    3833             :   
    3834             :     sort.resize(4);
    3835             :     sort[0] = MS::ARRAY_ID;
    3836             :     sort[1] = MS::FIELD_ID;
    3837             :     sort[2] = MS::DATA_DESC_ID;
    3838             :     sort[3] = MS::TIME;
    3839             :   }
    3840             :   Matrix<Int> noselection;
    3841             :   Double timeInterval=0;
    3842             : 
    3843             :   VisSet vs(ms,sort,noselection,useModelCol_p,timeInterval,compress);
    3844             : 
    3845             : }
    3846             : */
    3847             : 
    3848         115 : void Imager::writeHistory(LogIO& os){
    3849             : 
    3850         230 :   LogIO oslocal(LogOrigin("Imager", "writeHistory"));
    3851             :   try{
    3852             : 
    3853         115 :     os.postLocally();
    3854         115 :     if(!hist_p.null())
    3855         115 :       hist_p->addMessage(os);
    3856           0 :   }catch (AipsError x) {
    3857             :     oslocal << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    3858           0 :             << LogIO::POST;
    3859           0 :   } 
    3860         115 : }
    3861             : 
    3862         692 : void Imager::writeCommand(LogIO& os){
    3863             : 
    3864        1384 :   LogIO oslocal(LogOrigin("Imager", "writeCommand"));
    3865             :   try{
    3866         692 :     os.postLocally();
    3867         692 :     if(!hist_p.null())
    3868         692 :       hist_p->cliCommand(os);
    3869           0 :   }catch (AipsError x) {
    3870             :     oslocal << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    3871           0 :             << LogIO::POST;
    3872           0 :   } 
    3873         692 : }
    3874             : 
    3875           0 : Bool Imager::makePBImage(ImageInterface<Float>& pbImage, 
    3876             :                          Bool useSymmetricBeam){
    3877             : 
    3878           0 :   LogIO os(LogOrigin("Imager", "makePBImage()", WHERE));
    3879           0 :   CoordinateSystem imageCoord=pbImage.coordinates();
    3880           0 :    Int spectralIndex=imageCoord.findCoordinate(Coordinate::SPECTRAL);
    3881             :   SpectralCoordinate
    3882           0 :     spectralCoord=imageCoord.spectralCoordinate(spectralIndex);
    3883           0 :   Vector<String> units(1); units = "Hz";
    3884           0 :   spectralCoord.setWorldAxisUnits(units);       
    3885           0 :   Vector<Double> spectralWorld(1);
    3886           0 :   Vector<Double> spectralPixel(1);
    3887           0 :   spectralPixel(0) = 0;
    3888           0 :   spectralCoord.toWorld(spectralWorld, spectralPixel);  
    3889           0 :   Double freq  = spectralWorld(0);
    3890           0 :   Quantity qFreq( freq, "Hz" );
    3891           0 :   String telName=imageCoord.obsInfo().telescope();
    3892           0 :   if(telName=="UNKNOWN"){
    3893             :     os << LogIO::SEVERE << "Telescope encoded in image in not known " 
    3894           0 :        << LogIO::POST;
    3895           0 :           return false;
    3896             :   }
    3897             : 
    3898             :     
    3899           0 :   PBMath myPB(telName, useSymmetricBeam, qFreq);
    3900           0 :   return makePBImage(myPB, pbImage);
    3901             : 
    3902           0 : }
    3903             : 
    3904          12 : Bool Imager::makePBImage(const CoordinateSystem& imageCoord, 
    3905             :                          const String& telescopeName, 
    3906             :                          const String& diskPBName, 
    3907             :                          Bool useSymmetricBeam, Double diam){
    3908             : 
    3909          24 :   LogIO os(LogOrigin("Imager", "makePBImage()", WHERE));
    3910          12 :   Int spectralIndex=imageCoord.findCoordinate(Coordinate::SPECTRAL);
    3911             :   SpectralCoordinate
    3912          12 :     spectralCoord=imageCoord.spectralCoordinate(spectralIndex);
    3913          12 :   Vector<String> units(1); units = "Hz";
    3914          12 :   spectralCoord.setWorldAxisUnits(units);       
    3915          12 :   Vector<Double> spectralWorld(1);
    3916          12 :   Vector<Double> spectralPixel(1);
    3917          12 :   spectralPixel(0) = 0;
    3918          12 :   spectralCoord.toWorld(spectralWorld, spectralPixel);  
    3919          12 :   Double freq  = spectralWorld(0);
    3920          12 :   Quantity qFreq( freq, "Hz" );
    3921          12 :   String telName=telescopeName;
    3922          12 :   if(telName=="ALMA" &&  diam < 12.0)
    3923           0 :     telName="ACA";
    3924             :   //cerr << "Telescope Name is " << telName<< " qFreq " << qFreq << endl;
    3925             :   PBMath::CommonPB whichPB;
    3926          12 :   PBMath::enumerateCommonPB(telName, whichPB);  
    3927          12 :   PBMath myPB;
    3928          12 :   if(whichPB!=PBMath::UNKNOWN && whichPB!=PBMath::NONE){
    3929             :     
    3930          12 :     myPB=PBMath(telName, useSymmetricBeam, qFreq);
    3931             :   }
    3932           0 :   else if(diam > 0.0){
    3933           0 :     myPB=PBMath(diam,useSymmetricBeam, qFreq);
    3934             :   }
    3935             :   else{
    3936             :     os << LogIO::WARN << "Telescope " << telName << " is not known\n "
    3937             :        << "Not making the PB  image" 
    3938           0 :        << LogIO::POST;
    3939           0 :     return false; 
    3940             :   }
    3941          12 :   return makePBImage(imageCoord, myPB, diskPBName);
    3942             : 
    3943          12 : }
    3944             : 
    3945           0 : Bool Imager::makePBImage(const CoordinateSystem& imageCoord, 
    3946             :                          const Table& vpTable, const String& diskPBName){
    3947           0 :   ScalarColumn<TableRecord> recCol(vpTable, (String)"pbdescription");
    3948           0 :   PBMath myPB(recCol(0));
    3949           0 :   return makePBImage(imageCoord, myPB, diskPBName);
    3950             : 
    3951           0 : }
    3952             : 
    3953             : 
    3954           0 : Bool Imager::makePBImage(const Table& vpTable, ImageInterface<Float>& pbImage){
    3955           0 :   ScalarColumn<TableRecord> recCol(vpTable, (String)"pbdescription");
    3956           0 :   PBMath myPB(recCol(0));
    3957           0 :   return makePBImage(myPB, pbImage);
    3958             : 
    3959           0 : }
    3960             : 
    3961          12 : Bool Imager::makePBImage(const CoordinateSystem& /*imageCoord*/, PBMath& pbMath,
    3962             :                          const String& diskPBName){
    3963             : 
    3964          12 :   make(diskPBName);
    3965          12 :   PagedImage<Float> pbImage(diskPBName);
    3966          24 :   return makePBImage(pbMath, pbImage);
    3967          12 : }
    3968             : 
    3969             : 
    3970          12 : Bool Imager::makePBImage(PBMath& pbMath, ImageInterface<Float>& pbImage){
    3971             : 
    3972          12 :   CoordinateSystem imageCoord=pbImage.coordinates();
    3973          12 :   pbImage.set(0.0);
    3974          12 :   MDirection wcenter;  
    3975          12 :   Int directionIndex=imageCoord.findCoordinate(Coordinate::DIRECTION);
    3976             :   DirectionCoordinate
    3977          12 :     directionCoord=imageCoord.directionCoordinate(directionIndex);
    3978             : 
    3979          12 :   IPosition imShape=pbImage.shape();
    3980             :   //Vector<Double> pcenter(2);
    3981             :   // pcenter(0) = imShape(0)/2;
    3982             :   // pcenter(1) = imShape(1)/2;    
    3983             :   //directionCoord.toWorld( wcenter, pcenter );
    3984          12 :   VisBuffer vb(*rvi_p);
    3985          12 :   Int fieldCounter=0;
    3986          12 :   Vector<Int> fieldsDone;
    3987             :   
    3988          30 :   for(rvi_p->originChunks(); rvi_p->moreChunks(); rvi_p->nextChunk()){
    3989          18 :     Bool fieldDone=false;
    3990          24 :     for (uInt k=0;  k < fieldsDone.nelements(); ++k)
    3991             :       //hopefully there is not more than 10000 fields per ms
    3992           6 :       fieldDone=fieldDone || ((vb.msId()*10000)+vb.fieldId())==fieldsDone(k);
    3993          18 :     if(!fieldDone){
    3994          18 :       ++fieldCounter;
    3995          18 :       fieldsDone.resize(fieldCounter, true);
    3996          18 :       fieldsDone(fieldCounter-1)=vb.fieldId()+vb.msId()*10000;
    3997          18 :       wcenter=vb.msColumns().field().phaseDirMeas(vb.fieldId());
    3998          18 :       TempImage<Float> pbTemp(imShape, imageCoord);
    3999          18 :       TempImage<Complex> ctemp(imShape, imageCoord);
    4000          18 :       ctemp.set(1.0);
    4001          18 :       pbMath.applyPB(ctemp, ctemp, wcenter, Quantity(0.0, "deg"), BeamSquint::NONE);
    4002          18 :       StokesImageUtil::To(pbTemp, ctemp);
    4003          18 :       pbImage.copyData(  (LatticeExpr<Float>)(pbImage+pbTemp) );
    4004          18 :     }
    4005             :   }
    4006          12 :   LatticeExprNode elmax= max( pbImage );
    4007          12 :   Float fmax = abs(elmax.getFloat());
    4008             :   //If there are multiple overlap of beam such that the peak is larger than 1 then normalize
    4009             :   //otherwise leave as is
    4010          12 :   if(fmax>1.0)
    4011           6 :     pbImage.copyData((LatticeExpr<Float>)(pbImage/fmax));
    4012             : 
    4013          12 :   Float cutoffval=minPB_p;
    4014          24 :   LatticeExpr<Bool> lemask(iif(pbImage < cutoffval, 
    4015          12 :                                false, true));
    4016          12 :   ImageRegion outreg=pbImage.makeMask("mask0", false, true);
    4017          12 :   LCRegion& outmask=outreg.asMask();
    4018          12 :   outmask.copyData(lemask);
    4019          12 :   pbImage.defineRegion("mask0", outreg,RegionHandler::Masks, true); 
    4020          12 :   pbImage.setDefaultMask("mask0");
    4021             : 
    4022             : 
    4023             : 
    4024          12 :   return true;
    4025          12 : }
    4026           0 : void Imager::transferHistory(LoggerHolder& imagelog, MSHistoryColumns& msHis){
    4027           0 :   LogIO os(LogOrigin("imager", "transferHistory"));
    4028           0 :   LogSink& sink = imagelog.sink();
    4029           0 :   const ScalarColumn<Double> &time_col = msHis.time();
    4030           0 :   const ScalarColumn<String> &origin_col = msHis.origin();
    4031           0 :   const ArrayColumn<String> &cli_col = msHis.cliCommand();
    4032           0 :   const ScalarColumn<String> &message_col = msHis.message();
    4033           0 :   const ScalarColumn<String> &priority_col = msHis.priority();
    4034           0 :   std::map<String, LogMessage::Priority> prio={{"DEBUGGING", LogMessage::DEBUGGING},
    4035           0 :                                                {"DEBUG2", LogMessage::DEBUG2},{"DEBUG1", LogMessage::DEBUG1},  {"NORMAL5", LogMessage::NORMAL5}, {"NORMAL4",  LogMessage::NORMAL4}, {"NORMAL3", LogMessage::NORMAL3}, {"NORMAL2",   LogMessage::NORMAL2}, {"NORMAL1",  LogMessage::NORMAL1}, {"NORMAL",   LogMessage::NORMAL}, {"WARN",  LogMessage::WARN}, {"SEVERE", LogMessage::SEVERE}};
    4036           0 :   if (msHis.nrow()>0) {
    4037             :             //ostringstream oos;
    4038           0 :             uInt nmessages = time_col.nrow();
    4039           0 :             for (uInt i=0; i < nmessages; i++) {
    4040             :               try{
    4041           0 :                 ostringstream oos;
    4042           0 :                 oos << cli_col(i);
    4043           0 :                 LogMessage msg1(String("CLI_COMM: " + String(oos) + "; MESSAGE: " +message_col(i)), LogOrigin(origin_col(i)), prio.find(priority_col(i)) != prio.end() ? prio[priority_col(i)] :LogMessage::NORMAL);
    4044           0 :                 msg1.messageTime( MVTime(Quantity(time_col(i), "s")).getTime());
    4045             :            
    4046             :                 /*      String tmp=frmtTime(time_col(i));
    4047             :                 oos << tmp
    4048             :                     << "  HISTORY " << origin_col(i);
    4049             :                 oos << " " << cli_col(i) << " ";
    4050             :                 oos << message_col(i)
    4051             :                 << endl;*/
    4052             :                 
    4053           0 :                 sink.postLocally(msg1); 
    4054           0 :               }
    4055           0 :               catch(exception& y){
    4056           0 :                 os << LogIO::DEBUG2 << "Skipping history-table row " << i << " while filling output logsink-header " << LogIO::POST;
    4057           0 :               }
    4058             :               
    4059             :             }
    4060             :             // String historyline(oos);
    4061             :             //sink.postLocally(msg.message(oos.str()));
    4062             :           }
    4063             : 
    4064           0 : }
    4065         770 : void Imager::setObsInfo(ObsInfo& obsinfo){
    4066             : 
    4067         770 :   latestObsInfo_p=obsinfo;
    4068         770 : }
    4069             : 
    4070           0 : ObsInfo& Imager::latestObsInfo(){
    4071           0 :   return latestObsInfo_p;
    4072             : }
    4073             : 
    4074         270 : Bool Imager::makeEmptyImage(CoordinateSystem& coords, String& name, Int fieldID){
    4075             : 
    4076         270 :   Int tilex=32;
    4077         270 :   if(imageTileVol_p >0){
    4078           0 :     tilex=static_cast<Int>(ceil(sqrt(imageTileVol_p/min(4, npol_p)/min(32, imageNchan_p))));
    4079           0 :     if(tilex >0){
    4080           0 :       if(tilex > min(nx_p, ny_p))
    4081           0 :         tilex=min(nx_p, ny_p);
    4082             :       else
    4083           0 :         tilex=nx_p/Int(nx_p/tilex);
    4084             :     }    
    4085             :     //Not too small in x-y tile
    4086           0 :     if(tilex < 10)
    4087           0 :       tilex=10;
    4088             :   }
    4089         270 :   IPosition tileShape(4, min(tilex, nx_p), min(tilex, ny_p),
    4090         540 :                      min(4, npol_p), min(32, imageNchan_p));
    4091         270 :   IPosition imageShape(4, nx_p, ny_p, npol_p, imageNchan_p);
    4092         270 :   PagedImage<Float> modelImage(TiledShape(imageShape, tileShape), coords, name);
    4093         270 :   modelImage.set(0.0);
    4094         270 :   modelImage.table().markForDelete();
    4095             :     
    4096             :   // Fill in miscellaneous information needed by FITS
    4097         270 :   MSColumns msc(*ms_p);
    4098         270 :   Record info;
    4099         270 :   String object=msc.field().name()(fieldID)
    4100             : ;  //defining object name
    4101         270 :   String objectName=msc.field().name()(fieldID);
    4102         270 :   ImageInfo iinfo=modelImage.imageInfo();
    4103         270 :   iinfo.setObjectName(objectName);
    4104         270 :   modelImage.setImageInfo(iinfo);
    4105         270 :   String telescop=msc.observation().telescopeName()(0);
    4106         270 :   info.define("INSTRUME", telescop);
    4107         270 :   info.define("distance", 0.0);
    4108         270 :   modelImage.setMiscInfo(info);
    4109         270 :   modelImage.table().tableInfo().setSubType("GENERIC");
    4110         270 :   modelImage.setUnits(Unit("Jy/beam"));
    4111         270 :   modelImage.table().unmarkForDelete();
    4112         270 :   modelImage.table().relinquishAutoLocks(true);
    4113         270 :   modelImage.table().unlock();
    4114             : 
    4115         270 :   return true;
    4116             :   
    4117         270 : }
    4118             : 
    4119           0 : String Imager::frmtTime(const Double time) {
    4120           0 :   MVTime mvtime(Quantity(time, "s"));
    4121           0 :   Time t=mvtime.getTime();
    4122           0 :   ostringstream os;
    4123           0 :   os << t;
    4124           0 :   return os.str();
    4125           0 : }
    4126             : 
    4127         938 : Bool Imager::getRestFreq(Vector<Double>& restFreq, const Int& spw){
    4128             :   // MS Doppler tracking utility
    4129         938 :   MSDopplerUtil msdoppler(*ms_p);
    4130         938 :   restFreq.resize();
    4131         938 :   if(restFreq_p.getValue() > 0){// User defined restfrequency
    4132         900 :     restFreq.resize(1);
    4133         900 :     restFreq[0]=restFreq_p.getValue("Hz");
    4134             :   }
    4135             :   else{
    4136             :     // Look up first rest frequency found (for now)
    4137             : 
    4138          38 :     Int fieldid = (datafieldids_p.nelements()>0 ? datafieldids_p(0) : 
    4139          38 :                    fieldid_p);
    4140             :     try{
    4141          38 :       msdoppler.dopplerInfo(restFreq ,spw,fieldid);
    4142             :     }
    4143           0 :     catch(...){
    4144           0 :       restFreq.resize();
    4145           0 :     }
    4146             :   }
    4147         938 :   if(restFreq.nelements() >0) 
    4148         922 :     return true;
    4149          16 :   return false;
    4150         938 : }
    4151             : 
    4152             : 
    4153         130 : void Imager::setSkyEquation(){
    4154             :   /*  if(sm_p->nmodels() >0){
    4155             :     Long npix=0;
    4156             :     for (Int model=0; model < sm_p->nmodels(); ++model){
    4157             :       Long pixmod=sm_p->image(model).product();
    4158             :       npix=max(pixmod, npix);
    4159             :     }
    4160             :     Long pixInMem=(HostInfo::memoryTotal()/8)*1024;
    4161             :     if(npix > (pixInMem/2)){
    4162             :       se_p = new CubeSkyEquation(*sm_p, *vs_p, *ft_p, *cft_p, !useModelCol_p); 
    4163             :       return;
    4164             :     }
    4165             :     //else lets make the base SkyEquation for now
    4166             :   }
    4167             :   
    4168             :   se_p = new SkyEquation(*sm_p, *vs_p, *ft_p, *cft_p, !useModelCol_p);
    4169             : 
    4170             :   */
    4171             : //  if (ft_p->name() == "PBWProjectFT")
    4172             : //    {
    4173             : //      logSink_p.clearLocally();
    4174             : //      LogIO os(LogOrigin("imager", "setSkyEquation()"), logSink_p);
    4175             : //      os << "Creating SkyEquation for PBWProjectFT" << LogIO::POST;
    4176             : //     se_p = new SkyEquation(*sm_p, *vs_p, *ft_p, *cft_p, !useModelCol_p);
    4177             : //    }
    4178             : //  else
    4179         130 :   se_p = new CubeSkyEquation(*sm_p, *rvi_p, *ft_p, *cft_p, !useModelCol_p);
    4180         130 :   return;
    4181             : }
    4182             : 
    4183           0 : void Imager::savePSF(const Vector<String>& psf){
    4184             : 
    4185           0 :   if( (psf.nelements() > 0) && (Int(psf.nelements()) <= sm_p->numberOfModels())){
    4186             : 
    4187           0 :     for (Int thismodel=0;thismodel<Int(psf.nelements());++thismodel) {
    4188           0 :       if(removeTable(psf(thismodel))) {
    4189           0 :         Int whichmodel=thismodel;
    4190           0 :         if(facets_p >1 && thismodel > 0)
    4191           0 :           whichmodel=facets_p*facets_p-1+thismodel;
    4192           0 :         IPosition shape=images_p[thismodel]->shape();
    4193             :         PagedImage<Float> psfimage(shape,
    4194           0 :                                    images_p[thismodel]->coordinates(),
    4195           0 :                                    psf(thismodel));
    4196           0 :         if(freqFrameValid_p){
    4197           0 :           CoordinateSystem cs=psfimage.coordinates();
    4198           0 :           String errorMsg;
    4199           0 :           if (cs.setSpectralConversion (errorMsg, MFrequency::showType(freqFrame_p))) {
    4200           0 :             psfimage.setCoordinateInfo(cs);
    4201             :           }
    4202           0 :         }
    4203           0 :         psfimage.set(0.0);
    4204           0 :         if((shape[0]*shape[1]) > ((sm_p->PSF(whichmodel)).shape()[0]*(sm_p->PSF(whichmodel)).shape()[1])){
    4205           0 :           IPosition blc(4, 0, 0, 0, 0);
    4206           0 :           IPosition trc=shape-1;
    4207           0 :           blc[0]=(shape[0]-(sm_p->PSF(whichmodel)).shape()[0])/2;
    4208           0 :           trc[0]=(sm_p->PSF(whichmodel)).shape()[0]+blc[0]-1;
    4209           0 :           blc[1]=(shape[1]-(sm_p->PSF(whichmodel)).shape()[1])/2;
    4210           0 :           trc[1]=(sm_p->PSF(whichmodel)).shape()[1]+blc[1]-1;
    4211           0 :           Slicer sl(blc, trc, Slicer::endIsLast);
    4212           0 :           SubImage<Float> sub(psfimage, sl, true);
    4213           0 :           sub.copyData(sm_p->PSF(whichmodel));         
    4214           0 :         }
    4215             :         else{
    4216           0 :           psfimage.copyData(sm_p->PSF(whichmodel));
    4217             :         }
    4218             :         //sm_p->PSF(whichmodel).clearCache();
    4219           0 :       }
    4220             :     }
    4221             : 
    4222             : 
    4223             : 
    4224             :   }  
    4225             : 
    4226           0 : }
    4227             : 
    4228           0 : void Imager::setMosaicFTMachine(Bool useDoublePrec){
    4229           0 :   LogIO os(LogOrigin("Imager", "setmosaicftmachine", WHERE));
    4230           0 :   MSColumns msc(*ms_p);
    4231           0 :   String telescop=msc.observation().telescopeName()(0);
    4232             :   PBMath::CommonPB kpb;
    4233           0 :   PBMath::enumerateCommonPB(telescop, kpb);
    4234           0 :   if(!((kpb == PBMath::UNKNOWN) || 
    4235           0 :        (kpb==PBMath::OVRO) || (kpb==PBMath::ALMA) || (kpb==PBMath::ACA) || (kpb==PBMath::EVLA) || !doDefaultVP_p)){
    4236             :     
    4237           0 :     if(!gvp_p) {
    4238           0 :       MSColumns msc(*ms_p);
    4239           0 :       if (doDefaultVP_p) {
    4240             :         os << LogIO::NORMAL // Loglevel INFO
    4241           0 :            << "Using defaults for primary beams used in gridding" << LogIO::POST;
    4242           0 :         gvp_p=new VPSkyJones(msc, true, parAngleInc_p, squintType_p,
    4243           0 :                              skyPosThreshold_p);
    4244             :             } /*else {
    4245             :         os << LogIO::NORMAL // Loglevel INFO
    4246             :            << "Using VP as defined in " << vpTableStr_p <<  LogIO::POST;
    4247             :         Table vpTable( vpTableStr_p ); 
    4248             :         gvp_p=new VPSkyJones(msc, vpTable, parAngleInc_p, squintType_p,
    4249             :                              skyPosThreshold_p);
    4250             :       }
    4251             :         */
    4252           0 :     } 
    4253           0 :     gvp_p->setThreshold(minPB_p);
    4254             :   }
    4255             :   
    4256           0 :   ft_p = new MosaicFT(gvp_p, mLocation_p, stokes_p, cache_p/2, tile_p, true, 
    4257           0 :                       useDoublePrec);
    4258             : 
    4259           0 :   if((kpb == PBMath::UNKNOWN) || (kpb==PBMath::OVRO) || (kpb==PBMath::ACA)
    4260           0 :      || (kpb==PBMath::ALMA) || (kpb==PBMath::EVLA) || (!doDefaultVP_p)){
    4261             :     os << LogIO::NORMAL // Loglevel INFO
    4262             :        << "Using antenna primary beams for determining beams for gridding"
    4263           0 :        << LogIO::POST;
    4264             :     //Use 1D-Airy
    4265           0 :     PBMathInterface::PBClass pbtype= (kpb==PBMath::EVLA) ? PBMathInterface::COMMONPB : PBMathInterface::AIRY;
    4266             :     //Temporary special case for ALMA to use 2D images
    4267             :     //Temporary till it is made fully that with automatic image selections
    4268           0 :     if((kpb==PBMath::ACA) ||  (kpb==PBMath::ALMA)){
    4269           0 :       String useimage="false";
    4270           0 :       Aipsrc::find(useimage, "alma.vp.image", "false");
    4271           0 :       useimage.downcase();
    4272           0 :       if(useimage.contains("true")){
    4273           0 :         pbtype=PBMathInterface::IMAGE;
    4274             : 
    4275             :       }
    4276           0 :     }
    4277           0 :     if(!doDefaultVP_p){
    4278           0 :         pbtype=PBMathInterface::IMAGE;
    4279             :     }
    4280             :     else{
    4281           0 :       vpTableStr_p="";
    4282             :     }
    4283           0 :     CountedPtr<SimplePBConvFunc> mospb=new HetArrayConvFunc(pbtype, vpTableStr_p);
    4284             :         
    4285           0 :     static_cast<MosaicFT &>(*ft_p).setConvFunc(mospb);
    4286           0 :   }
    4287             :   
    4288           0 : }
    4289           0 : ATerm* Imager::createTelescopeATerm(MeasurementSet& ms, const Bool& isATermOn)
    4290             : {
    4291           0 :   LogIO log_l(LogOrigin("Imager", "createTelescopeATerm"));
    4292             : 
    4293           0 :   if (!isATermOn) return new NoOpATerm();
    4294             : 
    4295           0 :   MSObservationColumns msoc(ms.observation());
    4296           0 :   String ObsName=msoc.telescopeName()(0);
    4297           0 :   if ((ObsName == "EVLA") || (ObsName == "VLA"))
    4298           0 :     return new EVLAAperture();
    4299             :   else
    4300             :     {
    4301           0 :       log_l << "Telescope name ('"+
    4302           0 :         ObsName+"') in the MS not recognized to create the telescope specific ATerm" 
    4303           0 :             << LogIO::WARN;
    4304             :     }
    4305             : 
    4306           0 :   return NULL;
    4307           0 : }
    4308             : 
    4309             : //use SubMS::calcChanFreqs to calculate spectral gridding 
    4310             : //call from imagecoodinates2
    4311         774 : Bool Imager::calcImFreqs(Vector<Double>& imgridfreqs,
    4312             :                           Vector<Double>& imfreqres,
    4313             :                           const MFrequency::Types& oldRefFrame,
    4314             :                           const MEpoch& obsEpoch,
    4315             :                           const MPosition& obsPosition,
    4316             :                           const Double& restFreq 
    4317             :                           )
    4318             : { 
    4319             : 
    4320         774 :   logSink_p.clearLocally();
    4321        1548 :   LogIO os(LogOrigin("imager", "setGridFreqs()"), logSink_p);
    4322             : 
    4323         774 :   MSColumns msc(*ms_p);
    4324         774 :   Vector<Double> oldChanFreqs;
    4325         774 :   Vector<Double> oldFreqResolution;
    4326         774 :   String veltype;
    4327         774 :   String mode;
    4328         774 :   String restfreq;
    4329         774 :   String start;
    4330         774 :   String width;
    4331         774 :   String outframe;
    4332         774 :   Bool reversevec(false);
    4333         774 :   Bool descendfreq(false);
    4334             :   
    4335         774 :   if (imageMode_p.contains("RADIO")) {
    4336          36 :     veltype="radio";
    4337          36 :     mode="velocity";
    4338          36 :     start=dQuantitytoString(mImageStart_p.get("m/s"));
    4339          36 :     width=dQuantitytoString(mImageStep_p.get("m/s"));
    4340          36 :     if (!width.contains(casacore::Regex("^-"))) {
    4341             :       //positive vel. width (descending frequencies) 
    4342             :       //reversevec=true;
    4343          36 :       descendfreq=true;
    4344             :     }
    4345             :   }
    4346         738 :   else if (imageMode_p.contains("OPTICAL")) {
    4347           0 :     veltype="optical";
    4348           0 :     mode="velocity";
    4349           0 :     start=dQuantitytoString(mImageStart_p.get("m/s"));
    4350           0 :     width=dQuantitytoString(mImageStep_p.get("m/s"));
    4351             :     //cerr<<"optical vel width USED="<<width<<endl;
    4352           0 :     if (!width.contains(casacore::Regex("^-"))) {
    4353             :       //positive vel. width (descending frequencies)
    4354             :       //reversevec=true;
    4355           0 :       descendfreq=true;
    4356             :     }
    4357             :   }
    4358         738 :   else if (imageMode_p.contains("FREQ")) {
    4359          24 :     veltype="radio";
    4360          24 :     mode="frequency";
    4361          24 :     start=dQuantitytoString(mfImageStart_p.get("Hz"));
    4362          24 :     width=dQuantitytoString(mfImageStep_p.get("Hz"));
    4363          24 :     if (width.contains(casacore::Regex("^-"))) {
    4364             :       //reversevec=true;
    4365           0 :       descendfreq=true;
    4366             :     }
    4367             :   }
    4368         714 :   else if (imageMode_p.contains("CHANNEL")) {
    4369         714 :     veltype="radio";
    4370         714 :     mode="channel";
    4371         714 :     start=String::toString(imageStart_p);
    4372         714 :     width=String::toString(imageStep_p);
    4373         714 :     if (width.contains(casacore::Regex("^-"))) {
    4374             :       // means here going to lower chan index
    4375           0 :       descendfreq=true;
    4376             :     }
    4377             :   }
    4378           0 :   else if (imageMode_p.contains("MFS")) {
    4379           0 :     veltype="radio";
    4380           0 :     mode="mfs";
    4381           0 :     start=String::toString(imageStart_p);
    4382             :   }
    4383             :  
    4384         774 :   restfreq = dQuantitytoString(Quantity(restFreq,"Hz"));
    4385             :   //MFrequency::getType(freqFrame_p, outframe);
    4386         774 :   if (freqFrame_p!=oldRefFrame) {
    4387         132 :     outframe=MFrequency::showType(freqFrame_p);
    4388             :   }
    4389             :   else {
    4390         642 :     outframe="";
    4391             :   }
    4392             : 
    4393             :  
    4394             :   try {
    4395             :     /***
    4396             :     if(spectralwindowids_p.nelements()==1){
    4397             :       if(spectralwindowids_p[0]<0){
    4398             :         spectralwindowids_p.resize();
    4399             :         if(dataspectralwindowids_p.nelements()==0){
    4400             :           Int nspwinms=ms_p->spectralWindow().nrow();
    4401             :           dataspectralwindowids_p.resize(nspwinms);
    4402             :           indgen(dataspectralwindowids_p);
    4403             :         }
    4404             :         spectralwindowids_p=dataspectralwindowids_p;
    4405             :       }
    4406             :     }
    4407             :     ***/
    4408         774 :     Vector<Int> spwlist; 
    4409         774 :     if (mode=="frequency" || mode=="velocity") {
    4410          60 :        spwlist = dataspectralwindowids_p;
    4411             :     }
    4412             :     else {
    4413         714 :        spwlist = spectralwindowids_p;
    4414             :     }
    4415         774 :     if(spwlist.nelements()==1) {
    4416         672 :       oldChanFreqs=msc.spectralWindow().chanFreq()(spwlist[0]);  
    4417         672 :       oldFreqResolution=msc.spectralWindow().chanWidth()(spwlist[0]);
    4418             :     }
    4419             :     else {
    4420         102 :       SubMS thems(*ms_p);
    4421         102 :       if(!thems.combineSpws(spwlist,true,oldChanFreqs,oldFreqResolution)){
    4422           0 :         os << LogIO::SEVERE << "Error combining SpWs" << LogIO::POST;
    4423             :       }
    4424         102 :     }
    4425         774 :     Bool isDescendingData=false;
    4426             :     // Some descending order data has positive channel widths...so check chan freqs
    4427             :     // first...
    4428             :     //if (oldFreqResolution(0) < 0) isDescendingData=true;
    4429         774 :     if (oldChanFreqs.nelements()>1) {
    4430         396 :       if ((oldChanFreqs[1] - oldChanFreqs[0])<0) isDescendingData=true;
    4431             :     }
    4432         378 :     else if (oldFreqResolution(0) < 0) {
    4433          18 :       isDescendingData=true;
    4434             :     }
    4435             :     
    4436             :     // need theOldRefFrame,theObsTime,mObsPos,mode,nchan,start,width,restfreq,
    4437             :     // outframe,veltype
    4438             :     //
    4439             : 
    4440        1548 :     Bool rst=SubMS::calcChanFreqs(os,
    4441             :                            imgridfreqs, 
    4442             :                            imfreqres,
    4443             :                            oldChanFreqs, 
    4444             :                            oldFreqResolution,
    4445         774 :                            phaseCenter_p,
    4446             :                            oldRefFrame,
    4447             :                            obsEpoch,
    4448             :                            obsPosition,
    4449             :                            mode, 
    4450             :                            imageNchan_p, 
    4451             :                            start, 
    4452             :                            width,
    4453             :                            restfreq, 
    4454             :                            outframe,
    4455             :                            veltype
    4456             :                            );
    4457             :     
    4458         774 :     if (!rst) {
    4459             :       os << LogIO::SEVERE << "calcChanFreqs failed, check input start and width parameters"
    4460           0 :          << LogIO::EXCEPTION;
    4461           0 :       return false;
    4462             :     }
    4463             : 
    4464             :     //cout<<"=================calcChanFreqs arguments ======================"<<endl;
    4465             :     //cout.precision(10);
    4466             :     //cout<<"imgridfreqs(0)="<<imgridfreqs(0)<<endl;
    4467             :     //cout<<"imgridfreqs("<<imgridfreqs.nelements()-1<<")="<<imgridfreqs(imgridfreqs.nelements()-1)<<endl;
    4468             :     //cout<<"oldChanFreqs(0)="<<oldChanFreqs(0)<<endl;
    4469             :     //cout<<"oldChanFreqs("<<oldChanFreqs.nelements()-1<<")="<<oldChanFreqs(oldChanFreqs.nelements()-1)<<endl;
    4470             :     //cout<<"phaseCenter_p="<<phaseCenter_p<<endl;
    4471             :     //cout<<"oldRefFrame="<<oldRefFrame<<endl;
    4472             :     //cout<<"outframe="<<outframe<<endl;
    4473             :     //cout<<"obsEpoch="<<obsEpoch<<endl;
    4474             :     //cout<<"obsPosition="<<obsPosition<<endl;
    4475             :     //cout<<"start="<<start<<" width="<<width<<endl;
    4476             :     //cout<<"restfreq="<<restfreq<<endl;
    4477             :     //cout<<"veltype="<<veltype<<endl;
    4478             :     //cout<<"=================calcChanFreqs arguments end==================="<<endl;
    4479         774 :     Bool isDescendingNewData=false;
    4480         774 :     if (imgridfreqs(0)-imgridfreqs(1)>0) isDescendingNewData=true;
    4481             :     //reverse frequency vector? 
    4482             :     //evaluate reversing condition differ for chan mode from other modes
    4483         774 :     if(mode.contains("channel")) {
    4484         714 :       if ((descendfreq && !isDescendingNewData && !isDescendingData) |
    4485        1428 :           (descendfreq && isDescendingNewData && isDescendingData) |
    4486         714 :           (!descendfreq && !isDescendingNewData && isDescendingData)) {
    4487           0 :         reversevec = true;
    4488             :       }
    4489             :     }
    4490             :     else {
    4491         120 :       if ((descendfreq && !isDescendingNewData) | 
    4492          60 :           (!descendfreq && isDescendingNewData)) { 
    4493          30 :         reversevec = true;
    4494             :       }
    4495             :     }
    4496         774 :     if (reversevec) {
    4497             :     //if(reversevec && isAscendingData ) {
    4498             :       //Int ndata=imgridfreqs.nelements();
    4499             :       //tempimgridfreqs.resize(ndata);
    4500             :       /**
    4501             :       for (Int i=0;i<ndata;i++) {
    4502             :         tempimgridfreqs[i] = imgridfreqs[ndata - 1 - i];
    4503             :       }    
    4504             :       for (Int i=0;i<ndata;i++) {
    4505             :         std::swap(imgridfreqs[ndata-1-i],tempimgridfreqs[i]);
    4506             :       }  
    4507             :       **/
    4508          30 :       std::vector<double>  stlimgridfreqs;
    4509          30 :       imgridfreqs.tovector(stlimgridfreqs);
    4510          30 :       std::reverse(stlimgridfreqs.begin(),stlimgridfreqs.end());  
    4511          30 :       imgridfreqs=Vector<Double>(stlimgridfreqs);
    4512          30 :     }
    4513             :     //cerr<<"Final imgridfreqs(0)="<<imgridfreqs(0)<<endl;
    4514             :     
    4515         774 :   } catch (AipsError x) {
    4516           0 :     this->unlock();
    4517             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
    4518           0 :        << LogIO::EXCEPTION;
    4519           0 :     return false;
    4520           0 :   } 
    4521         774 :   return true;
    4522         774 : }//end of calcImFreqs
    4523             : 
    4524             : // convert a double precision quanity to a String
    4525         894 : String Imager::dQuantitytoString(const Quantity& dq) {
    4526         894 :   std::ostringstream ss;
    4527         894 :   ss.precision(std::numeric_limits<double>::digits10);
    4528         894 :   ss << dq;
    4529        2682 :   return ss.str();
    4530         894 : } 
    4531             : 
    4532             : #define INITIALIZE_DIRECTION_VECTOR(name) \
    4533             :     do { \
    4534             :         if (name.nelements() < 2) { \
    4535             :                 name.resize(2); \
    4536             :                 name = 0.0; \
    4537             :         } \
    4538             :     } while (false)
    4539             : 
    4540          11 : Bool Imager::mapExtent(const String &referenceFrame, const String &movingSource,
    4541             :         const String &pointingColumn, Vector<Double> &center, Vector<Double> &blc,
    4542             :         Vector<Double> &trc, Vector<Double> &extent) {
    4543          11 :     return getMapExtent(*mssel_p, referenceFrame, movingSource, pointingColumn,
    4544          11 :             center, blc, trc, extent);
    4545             : }
    4546             : 
    4547          28 : Bool Imager::getMapExtent(const MeasurementSet &ms, const String &referenceFrame,
    4548             :         const String &movingSource, const String &pointingColumn,
    4549             :         Vector<Double> &center, Vector<Double> &blc, Vector<Double> &trc, Vector<Double> &extent) {
    4550          28 :     INITIALIZE_DIRECTION_VECTOR(center);
    4551          28 :     INITIALIZE_DIRECTION_VECTOR(blc);
    4552          28 :     INITIALIZE_DIRECTION_VECTOR(trc);
    4553          28 :     INITIALIZE_DIRECTION_VECTOR(extent);
    4554             : 
    4555             :     try {
    4556             :         //cout << "ms.nrow() = " << ms.nrow() << endl;
    4557          28 :         PointingDirectionCalculator calc(ms);
    4558             :         //cout << "calc instantiated" << endl;
    4559             : 
    4560          28 :         calc.setDirectionColumn(pointingColumn);
    4561             :         //cout << "set pointing direction column to " << pointingColumn << endl;
    4562          28 :         calc.setFrame(referenceFrame);
    4563             :         //cout << "set reference frame to " << referenceFrame << endl;
    4564          28 :         MDirection::Types refType = MDirection::J2000; // any non planet value
    4565          28 :         Bool status = false;
    4566             :         //cout << "movingSource = " << movingSource << endl;
    4567             :         //cout << "getType" << endl;
    4568          28 :         status = MDirection::getType(refType, movingSource);
    4569             :         //cout << "refType string = " << MDirection::showType(refType) << endl;
    4570             :         //cout << "status = " << status << endl;
    4571          60 :         Bool doMovingSourceCorrection = (status == true &&
    4572          32 :                 MDirection::N_Types < refType &&
    4573           4 :                 refType < MDirection::N_Planets);
    4574          28 :         Bool isOffsetColumn = (pointingColumn.contains("OFFSET")
    4575          28 :                 || pointingColumn.contains("Offset")
    4576          56 :                 || pointingColumn.contains("offset"));
    4577          28 :         if (doMovingSourceCorrection) {
    4578             :             //cout << "need moving source correction" << endl;
    4579           4 :             calc.setMovingSource(movingSource);
    4580             :             //cout << "set moving source name " << movingSource << endl;
    4581             :         }
    4582             :         //cout << "set direction matrix shape to COLUMN_MAJOR" << endl;
    4583          28 :         calc.setDirectionListMatrixShape(PointingDirectionCalculator::COLUMN_MAJOR);
    4584             : 
    4585             :         //cout << "start getDirection" << endl;
    4586          28 :         Matrix<Double> directionList = calc.getDirection();
    4587             :         //cout << "end getDirection shape " << directionList.shape() << endl;
    4588          28 :         Vector<Double> longitude = directionList.column(0);
    4589          28 :         Vector<Double> latitude = directionList.column(1);
    4590             :         //cout << "longitude.nelements() = " << longitude.nelements() << endl;
    4591             :         //cout << "latitude.nelements() = " << latitude.nelements() << endl;
    4592             : 
    4593             :         // Diagnose if longitude values are divided by periodic boundary surface
    4594             :         // (+-pi or 0, 2pi)
    4595             :         // In this case, mean of longitude should be around 0 (+-pi) or pi (0,2pi)
    4596             :         // and stddev of longitude array be around pi.
    4597             :         //cout << "diagnose longitude distribution" << endl;
    4598          28 :         Double longitudeMean = mean(longitude);
    4599          28 :         Double longitudeStddev = stddev(longitude);
    4600             :         //cout << "mean " << longitudeMean << " stddev " << longitudeStddev << endl;
    4601          28 :         if (longitudeStddev > 2.0 / 3.0 * C::pi) {
    4602             :             // likely to be the case
    4603             :             //cout << "likely to be the case" << endl;
    4604           0 :             if (abs(longitudeMean) < 0.5 * C::pi) {
    4605             :                 // periodic boundary surface would be +-pi
    4606             :                 //cout << "periodic boundary surface would be +-pi" << endl;
    4607           0 :                 for (size_t i = 0; i < longitude.nelements(); ++i) {
    4608           0 :                     if (longitude[i] < 0.0) {
    4609           0 :                         longitude[i] += C::_2pi;
    4610             :                     }
    4611             :                 }
    4612             :             }
    4613           0 :             else if (abs(longitudeMean - C::pi) < 0.5 * C::pi ) {
    4614             :                 // periodic boundary surface would be 0,2pi
    4615             :                 //cout << "periodic boundary surface would be 0,2pi" << endl;
    4616           0 :                 for (size_t i = 0; i < longitude.nelements(); ++i) {
    4617           0 :                     if (longitude[i] < C::pi) {
    4618           0 :                         longitude[i] += C::_2pi;
    4619             :                     }
    4620             :                 }
    4621             :             }
    4622             :         }
    4623             : 
    4624          28 :         blc[0] = min(longitude);
    4625          28 :         trc[0] = max(longitude);
    4626          28 :         blc[1] = min(latitude);
    4627          28 :         trc[1] = max(latitude);
    4628          28 :         extent = trc - blc;
    4629             :         //cout << "result: blc " << blc << " trc " << trc << endl;
    4630             :         //cout << "result: extent " << extent << endl;
    4631             : 
    4632             :         // declination correction factor
    4633          28 :         Double declinationCorrection = 0.0;
    4634             :         // center
    4635          28 :         if (isOffsetColumn) {
    4636           0 :             center = 0.0;
    4637           0 :             declinationCorrection = cos((blc[1] + trc[1]) / 2.0);
    4638             :         }
    4639          28 :         else if (doMovingSourceCorrection) {
    4640             :             // shift center to moving source position at the time
    4641             :             // that will be used for imaging
    4642           4 :             VisBuffer vb(*rvi_p);
    4643           4 :             MEpoch referenceEpoch = vb.msColumns().timeMeas()(vb.rowIds()[0]);
    4644           4 :             MPosition referencePosition = vb.msColumns().antenna().positionMeas()(vb.antenna1()[0]);
    4645           4 :             MDirection::Types const &outDirectionType = calc.getDirectionType();
    4646           4 :             MDirection const &movingSourceDir = calc.getMovingSourceDirection();
    4647           4 :             MeasFrame referenceMeasFrame(referenceEpoch, referencePosition);
    4648           4 :             MDirection::Ref azelRef(MDirection::AZEL, referenceMeasFrame);
    4649           4 :             MDirection azelDir = MDirection::Convert(movingSourceDir, azelRef)();
    4650           4 :             MDirection::Ref outRef(outDirectionType, referenceMeasFrame);
    4651           4 :             MDirection sourceDirection = MDirection::Convert(azelDir, outRef)();
    4652           4 :             center = sourceDirection.getAngle("rad").getValue();
    4653           4 :             declinationCorrection = cos(center[1]);
    4654           4 :         }
    4655             :         else {
    4656          24 :             center = (blc + trc) / 2.0;
    4657          24 :             declinationCorrection = cos(center[1]);
    4658             :         }
    4659          28 :         assert(declinationCorrection != 0.0);
    4660             :         //cout << "declinationCorrection = " << declinationCorrection << endl;
    4661             :         //cout << "result: center " << center << endl;
    4662             : 
    4663             :         // apply declinationCorrection to extent[0]
    4664          28 :         extent[0] *= declinationCorrection;
    4665          28 :     }
    4666           0 :     catch (AipsError &e) {
    4667           0 :         LogIO os(LogOrigin("Imager", "getMapExtent", WHERE));
    4668           0 :         os << LogIO::SEVERE << "Failed due to the rror \"" << e.getMesg() << "\"" << LogIO::POST;
    4669           0 :         return false;
    4670           0 :     }
    4671           0 :     catch (...) {
    4672           0 :         LogIO os(LogOrigin("Imager", "getMapExtent", WHERE));
    4673           0 :         os << LogIO::SEVERE << "Failed due to unknown error" << LogIO::POST;
    4674           0 :         throw;
    4675             :         return false;
    4676           0 :     }
    4677             : 
    4678          28 :     return true;
    4679             : }
    4680             : 
    4681         258 : Bool Imager::pointingSampling(const String &referenceFrame,
    4682             :                               const String &movingSource,
    4683             :                               const String &pointingColumn,
    4684             :                               const String &antenna,
    4685             :                               Quantum<Vector<Double>> &sampling,
    4686             :                               Quantity &positionAngle) {
    4687             :   try {
    4688         258 :     SingleDishBeamUtil sdBeamU(*mssel_p, referenceFrame, movingSource,
    4689         258 :                                pointingColumn, antenna);
    4690         258 :     sdBeamU.getPointingSamplingRaster(sampling, positionAngle);
    4691         258 :   }
    4692           0 :   catch (AipsError &e) {
    4693           0 :     LogIO os(LogOrigin("Imager", "pointingSampling", WHERE));
    4694           0 :     os << LogIO::SEVERE << "Failed due to the rror \"" << e.getMesg() << "\"" << LogIO::POST;
    4695           0 :     return false;
    4696           0 :   }
    4697           0 :   catch (...) {
    4698           0 :     LogIO os(LogOrigin("Imager", "pointingSampling", WHERE));
    4699           0 :     os << LogIO::SEVERE << "Failed due to unknown error" << LogIO::POST;
    4700           0 :     throw;
    4701             :     return false;
    4702           0 :   }
    4703         258 :   return true;
    4704             : }
    4705             : 
    4706             : } //# NAMESPACE CASA - END
    4707             : 
    4708             : 
    4709             : 
    4710             : 
    4711             : 
    4712             : 
    4713             :   // else if ((ftmachine_p == "wbawp") || (ftmachine_p == "wbmosaic")){
    4714             : 
    4715             :   //   if (wprojPlanes_p<=1)
    4716             :   //     {
    4717             :   //    os << LogIO::NORMAL
    4718             :   //       << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    4719             :   //       << LogIO::POST;
    4720             :   //    os << LogIO::NORMAL << "Performing WBA-Projection" << LogIO::POST; // Loglevel PROGRESS
    4721             :   //     }
    4722             :   //   if((wprojPlanes_p>1)&&(wprojPlanes_p<64)) 
    4723             :   //     {
    4724             :   //    os << LogIO::WARN
    4725             :   //       << "No. of w-planes set too low for W projection - recommend at least 128"
    4726             :   //       << LogIO::POST;
    4727             :   //    os << LogIO::NORMAL << "Performing WBAW-Projection" << LogIO::POST; // Loglevel PROGRESS
    4728             :   //     }
    4729             : 
    4730             :   //   // if(!gvp_p) 
    4731             :   //   //   {
    4732             :   //   //       os << LogIO::NORMAL // Loglevel INFO
    4733             :   //   //        << "Using defaults for primary beams used in gridding" << LogIO::POST;
    4734             :   //   //       gvp_p = new VPSkyJones(*ms_p, true, parAngleInc_p, squintType_p,
    4735             :   //   //                            skyPosThreshold_p);
    4736             :   //   //   }
    4737             :   //   useDoublePrecGrid=false;
    4738             :   //   CountedPtr<ATerm> apertureFunction = createTelescopeATerm(*ms_p,true);
    4739             :   //   CountedPtr<PSTerm> psTerm = new PSTerm();
    4740             :   //   CountedPtr<WTerm> wTerm = new WTerm();
    4741             :   //   //    psTerm->setOpCode(CFTerms::NOOP);
    4742             :   //   CountedPtr<ConvolutionFunction> awConvFunc;
    4743             :   //   if (ftmachine_p=="wbawp") awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm);
    4744             :   //   else                      awConvFunc = new AWConvFuncEPJones(apertureFunction,psTerm,wTerm);
    4745             : 
    4746             :   //   CountedPtr<VisibilityResamplerBase> visResampler = new AWVisResampler();
    4747             : 
    4748             :   //   //    CountedPtr<VisibilityResamplerBase> visResampler = new VisibilityResampler();
    4749             : 
    4750             :   //   // CountedPtr<VisibilityResamplerBase> mthVisResampler = 
    4751             :   //   //   new MultiThreadedVisibilityResampler(useDoublePrecGrid, visResampler);
    4752             :   //   CountedPtr<CFCache> cfcache = new CFCache();
    4753             :   //   cfcache->setCacheDir(cfCacheDirName_p.data());
    4754             :   //   cerr << "cfcache->initCache2()" << endl;
    4755             :   //   cfcache->initCache2();
    4756             : 
    4757             :   //   ft_p = new AWProjectWBFT(wprojPlanes_p, cache_p/2, 
    4758             :   //                         cfcache, awConvFunc, 
    4759             :   //                         //                      mthVisResampler,
    4760             :   //                         visResampler,
    4761             :   //                         /*true */doPointing, doPBCorr, 
    4762             :   //                         tile_p, paStep_p, pbLimit_p, true);
    4763             :       
    4764             :   //   ((AWProjectWBFT *)ft_p)->setObservatoryLocation(mLocation_p);
    4765             :   //   //
    4766             :   //   // Explicit type casting of ft_p does not look good.  It does not
    4767             :   //   // pick up the setPAIncrement() method of PBWProjectFT without
    4768             :   //   // this
    4769             :   //   //
    4770             :   //   // os << LogIO::NORMAL << "Setting PA increment to " << parAngleInc_p.getValue("deg") << " deg" << endl;
    4771             :   //   ((AWProjectFT *)ft_p)->setPAIncrement(parAngleInc_p);
    4772             : 
    4773             :   //   if (doPointing) 
    4774             :   //     {
    4775             :   //    try
    4776             :   //      {
    4777             :   //        // Warn users we are have temporarily disabled pointing cal
    4778             :   //        //      throw(AipsError("Pointing calibration temporarily disabled (gmoellen 06Nov20)."));
    4779             :   //        //  TBD: Bring this up-to-date with new VisCal mechanisms
    4780             :   //        VisSet elVS(*rvi_p);
    4781             :   //        epJ = new EPJones(elVS, *ms_p);
    4782             :   //        RecordDesc applyRecDesc;
    4783             :   //        applyRecDesc.addField("table", TpString);
    4784             :   //        applyRecDesc.addField("interp",TpString);
    4785             :   //        Record applyRec(applyRecDesc);
    4786             :   //        applyRec.define("table",epJTableName_p);
    4787             :   //        applyRec.define("interp", "nearest");
    4788             :   //        epJ->setApply(applyRec);
    4789             :   //        ((AWProjectFT *)ft_p)->setEPJones(epJ);
    4790             :   //      }
    4791             :   //    catch(AipsError& x)
    4792             :   //      {
    4793             :   //        //
    4794             :   //        // Add some more useful info. to the message and translate
    4795             :   //        // the generic AipsError exception object to a more specific
    4796             :   //        // SynthesisError object.
    4797             :   //        //
    4798             :   //        String mesg = x.getMesg();
    4799             :   //        mesg += ". Error in loading pointing offset table.";
    4800             :   //        SynthesisError err(mesg);
    4801             :   //        throw(err);
    4802             :   //      }
    4803             :   //     }
    4804             :   //   AlwaysAssert(ft_p, AipsError);
    4805             :   //   cft_p = new SimpleComponentFTMachine();
    4806             :   //   AlwaysAssert(cft_p, AipsError);
    4807             : 
    4808             :   // }
    4809             :   // else if (ftmachine_p == "awp")
    4810             :   //   {
    4811             :   //     if (wprojPlanes_p<=1)
    4812             :   //    {
    4813             :   //      os << LogIO::NORMAL
    4814             :   //         << "You are using wprojplanes=1. Doing co-planar imaging (no w-projection needed)" 
    4815             :   //         << LogIO::POST;
    4816             :   //      os << LogIO::NORMAL << "Performing A-Projection" << LogIO::POST; // Loglevel PROGRESS
    4817             :   //    }
    4818             :   //     if((wprojPlanes_p>1)&&(wprojPlanes_p<64)) 
    4819             :   //    {
    4820             :   //      os << LogIO::WARN
    4821             :   //         << "No. of w-planes set too low for W projection - recommend at least 128"
    4822             :   //         << LogIO::POST;
    4823             :   //      os << LogIO::NORMAL << "Performing AW-Projection"
    4824             :   //         << LogIO::POST; // Loglevel PROGRESS
    4825             :   //    }
    4826             :   //     // if(!gvp_p) 
    4827             :   //     //     {
    4828             :   //     //       os << LogIO::NORMAL // Loglevel INFO
    4829             :   //     //          << "Using defaults for primary beams used in gridding" << LogIO::POST;
    4830             :   //     //       gvp_p = new VPSkyJones(*ms_p, true, parAngleInc_p, squintType_p,
    4831             :   //     //                              skyPosThreshold_p);
    4832             :   //     //     }
    4833             :   //     //      CountedPtr<ATerm> evlaAperture = new EVLAAperture();
    4834             :   //     useDoublePrecGrid=false;
    4835             :   //     CountedPtr<ATerm> apertureFunction = createTelescopeATerm(*ms_p,true);
    4836             :   //     CountedPtr<PSTerm> psTerm = new PSTerm();
    4837             :   //     CountedPtr<WTerm> wTerm = new WTerm();
    4838             :   //     psTerm->setOpCode(CFTerms::NOOP);
    4839             :   //     CountedPtr<ConvolutionFunction> awConvFunc=new AWConvFunc(apertureFunction,psTerm,wTerm);
    4840             :   //     CountedPtr<VisibilityResamplerBase> visResampler = new AWVisResampler();
    4841             :   //     //      CountedPtr<VisibilityResamplerBase> visResampler = new VisibilityResampler();
    4842             :   //     // CountedPtr<VisibilityResamplerBase> mthVisResampler = new MultiThreadedVisibilityResampler(useDoublePrecGrid,
    4843             :   //     //                                                                                              visResampler);
    4844             :   //     CountedPtr<CFCache> cfcache=new CFCache();
    4845             :   //     cfcache->setCacheDir(cfCacheDirName_p.data());
    4846             :   //     cfcache->initCache2();
    4847             :   //     ft_p = new AWProjectFT(wprojPlanes_p, cache_p/2,
    4848             :   //                         cfcache, awConvFunc, 
    4849             :   //                         //                      mthVisResampler,
    4850             :   //                         visResampler,
    4851             :   //                         doPointing, doPBCorr,
    4852             :   //                         tile_p, pbLimit_p, true);
    4853             :   //     ((AWProjectFT *)ft_p)->setObservatoryLocation(mLocation_p);
    4854             :   //     //
    4855             :   //     // Explicit type casting of ft_p does not look good.  It does not
    4856             :   //     // pick up the setPAIncrement() method of PBWProjectFT without
    4857             :   //     // this
    4858             :   //     //
    4859             :   //     Quantity paInc(paStep_p,"deg");
    4860             :   //     // os << LogIO::NORMAL << "Setting PA increment to " 
    4861             :   //     //      << paInc.getValue("deg") << " deg" << endl;
    4862             :   //     ((AWProjectFT *)ft_p)->setPAIncrement(parAngleInc_p);
    4863             : 
    4864             :   //     if (doPointing) 
    4865             :   //    {
    4866             :   //      try
    4867             :   //        {
    4868             :   //          VisSet elVS(*rvi_p);
    4869             :   //          epJ = new EPJones(elVS, *ms_p);
    4870             :   //          RecordDesc applyRecDesc;
    4871             :   //          applyRecDesc.addField("table", TpString);
    4872             :   //          applyRecDesc.addField("interp",TpString);
    4873             :   //          Record applyRec(applyRecDesc);
    4874             :   //          applyRec.define("table",epJTableName_p);
    4875             :   //          applyRec.define("interp", "nearest");
    4876             :   //          epJ->setApply(applyRec);
    4877             :   //          ((AWProjectFT *)ft_p)->setEPJones(epJ);
    4878             :   //      }
    4879             :   //      catch(AipsError& x)
    4880             :   //        {
    4881             :   //          //
    4882             :   //          // Add some more useful info. to the message and translate
    4883             :   //          // the generic AipsError exception object to a more specific
    4884             :   //          // SynthesisError object.
    4885             :   //          //
    4886             :   //          String mesg = x.getMesg();
    4887             :   //          mesg += ". Error in loading pointing offset table.";
    4888             :   //          SynthesisError err(mesg);
    4889             :   //          throw(err);
    4890             :   //        }
    4891             :   //    }
    4892             :   //     AlwaysAssert(ft_p, AipsError);
    4893             :   //     cft_p = new SimpleComponentFTMachine();
    4894             :   //     AlwaysAssert(cft_p, AipsError);
    4895             :   //   }

Generated by: LCOV version 1.16