LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - AWProjectFT.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 1216 0.0 %
Date: 2024-10-09 13:55:54 Functions: 0 48 0.0 %

          Line data    Source code
       1             : // -*- C++ -*-
       2             : //# AWProjectFT.cc: Implementation of AWProjectFT class
       3             : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
       4             : //# Associated Universities, Inc. Washington DC, USA.
       5             : //#
       6             : //# This library is free software; you can redistribute it and/or modify it
       7             : //# under the terms of the GNU Library General Public License as published by
       8             : //# the Free Software Foundation; either version 2 of the License, or (at your
       9             : //# option) any later version.
      10             : //#
      11             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      12             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      14             : //# License for more details.
      15             : //#
      16             : //# You should have received a copy of the GNU Library General Public License
      17             : //# along with this library; if not, write to the Free Software Foundation,
      18             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      19             : //#
      20             : //# Correspondence concerning AIPS++ should be addressed as follows:
      21             : //#        Internet email: casa-feedback@nrao.edu.
      22             : //#        Postal address: AIPS++ Project Office
      23             : //#                        National Radio Astronomy Observatory
      24             : //#                        520 Edgemont Road
      25             : //#                        Charlottesville, VA 22903-2475 USA
      26             : //#
      27             : //# $Id$
      28             : 
      29             : #include <casacore/casa/Quanta/UnitMap.h>
      30             : #include <casacore/casa/Quanta/MVTime.h>
      31             : #include <casacore/casa/Quanta/UnitVal.h>
      32             : #include <casacore/casa/Containers/Block.h>
      33             : #include <casacore/casa/Containers/Record.h>
      34             : #include <casacore/casa/Arrays/Array.h>
      35             : #include <casacore/casa/OS/HostInfo.h>
      36             : #include <sstream>
      37             : 
      38             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      39             : #include <casacore/images/Images/ImageInterface.h>
      40             : 
      41             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      42             : #include <synthesis/TransformMachines/SynthesisError.h>
      43             : #include <synthesis/TransformMachines2/AWProjectFT.h>
      44             : #include <synthesis/TransformMachines2/CFStore2.h>
      45             : #include <synthesis/MeasurementComponents/ExpCache.h>
      46             : #include <synthesis/MeasurementComponents/CExp.h>
      47             : #include <synthesis/TransformMachines2/AWVisResampler.h>
      48             : #include <synthesis/TransformMachines2/VBStore.h>
      49             : 
      50             : #include <casacore/scimath/Mathematics/FFTServer.h>
      51             : #include <casacore/scimath/Mathematics/MathFunc.h>
      52             : #include <casacore/measures/Measures/MeasTable.h>
      53             : #include <iostream>
      54             : #include <casacore/casa/OS/Timer.h>
      55             : 
      56             : #include <synthesis/TransformMachines2/ATerm.h>
      57             : #include <synthesis/TransformMachines2/NoOpATerm.h>
      58             : #include <synthesis/TransformMachines2/AWConvFunc.h>
      59             : #include <synthesis/TransformMachines2/EVLAAperture.h>
      60             : #include <iomanip>
      61             : //#define CONVSIZE (1024*2)
      62             : // #define OVERSAMPLING 2
      63             : #define USETABLES 0           // If equal to 1, use tabulated exp() and
      64             :                               // complex exp() functions.
      65             : #define MAXPOINTINGERROR 250.0 // Max. pointing error in arcsec used to
      66             : // determine the resolution of the
      67             : // tabulated exp() function.
      68             : #define DORES true
      69             : 
      70             : 
      71             : using namespace casacore;
      72             : namespace casa { //# NAMESPACE CASA - BEGIN
      73             :   using namespace vi;  
      74             : #define NEED_UNDERSCORES
      75             :   namespace refim{
      76             :   extern "C" 
      77             :   {
      78             :     //
      79             :     // The Gridding Convolution Function (GCF) used by the underlying
      80             :     // gridder written in FORTRAN.
      81             :     //
      82             :     // The arguments must all be pointers and the value of the GCF at
      83             :     // the given (u,v) point is returned in the weight variable.  Making
      84             :     // this a function which returns a complex value (namely the weight)
      85             :     // has problems when called in FORTRAN - I (SB) don't understand
      86             :     // why.
      87             :     //
      88             : #if defined(NEED_UNDERSCORES)
      89             : #define nwcppeij nwcppeij_
      90             : #endif
      91             :     //
      92             :     //---------------------------------------------------------------
      93             :     //
      94             :     IlluminationConvFunc awEij2;
      95           0 :     void awcppeij2(Double *griduvw, Double *area,
      96             :                  Double *raoff1, Double *decoff1,
      97             :                  Double *raoff2, Double *decoff2, 
      98             :                  Int *doGrad,
      99             :                  Complex *weight,
     100             :                  Complex *dweight1,
     101             :                  Complex *dweight2,
     102             :                  Double *currentCFPA)
     103             :     {
     104           0 :       Complex w,d1,d2;
     105           0 :       awEij2.getValue(griduvw, raoff1, raoff2, decoff1, decoff2,
     106             :                     area,doGrad,w,d1,d2,*currentCFPA);
     107           0 :       *weight   = w;
     108           0 :       *dweight1 = d1;
     109           0 :       *dweight2 = d2;
     110           0 :     }
     111             :   }
     112             : 
     113           0 :   ATerm* AWProjectFT::createTelescopeATerm(const String& telescopeName, const Bool& isATermOn)
     114             :   {
     115             :     
     116           0 :     if (!isATermOn) return new NoOpATerm();
     117             :     
     118             :     // MSObservationColumns msoc(ms.observation());
     119             :     // String ObsName=msoc.telescopeName()(0);
     120           0 :     if ((telescopeName == "EVLA") || (telescopeName == "VLA"))
     121           0 :       return new EVLAAperture();
     122             :     else
     123             :       {
     124           0 :         LogIO os(LogOrigin("AWProjectFT2", "createTelescopeATerm",WHERE));
     125           0 :         os << "Telescope name ('"+
     126           0 :           telescopeName+"') in the MS not recognized to create the telescope specific ATerm" 
     127           0 :            << LogIO::EXCEPTION;
     128           0 :       }
     129             :     
     130           0 :     return NULL;
     131             :   }
     132             : 
     133           0 :   CountedPtr<ConvolutionFunction> AWProjectFT::makeCFObject(const String& telescopeName,
     134             :                                                             const Bool aTermOn,
     135             :                                                             const Bool psTermOn,
     136             :                                                             const Bool wTermOn,
     137             :                                                             const Bool,// mTermOn,
     138             :                                                             const Bool wbAWP,
     139             :                                                             const Bool conjBeams)
     140             :   {
     141             :     (void)wTermOn;//Unused
     142           0 :     CountedPtr<ATerm> apertureFunction = AWProjectFT::createTelescopeATerm(telescopeName, aTermOn);
     143           0 :     CountedPtr<PSTerm> psTerm = new PSTerm();
     144           0 :     CountedPtr<WTerm> wTerm = new WTerm();
     145             :     //if (cfBufferSize > 0) apertureFunction->setConvSize(cfBufferSize);
     146             :     //
     147             :     // Selectively switch off CFTerms.
     148             :     //
     149           0 :     if (aTermOn == false) {apertureFunction->setOpCode(CFTerms::NOOP);}
     150           0 :     if (psTermOn == false) psTerm->setOpCode(CFTerms::NOOP);
     151           0 :     if (wTermOn == False) wTerm->setOpCode(CFTerms::NOOP);
     152             :     //
     153             :     // Construct the CF object with appropriate CFTerms.
     154             :     //
     155           0 :     CountedPtr<ConvolutionFunction> awConvFunc;
     156             :     //    awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm, !wbAWP);
     157             :     //if ((ftmName=="mawprojectft") || (mTermOn))
     158             : 
     159           0 :     awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm,wbAWP, conjBeams);
     160             : 
     161           0 :     return awConvFunc;
     162           0 :   }
     163             :   //
     164             :   //---------------------------------------------------------------
     165             :   //
     166           0 :   AWProjectFT::AWProjectFT()
     167           0 :     : FTMachine(), padding_p(1.0), nWPlanes_p(1),
     168           0 :       imageCache(0), cachesize(0), tilesize(16),
     169           0 :       gridder(0), isTiled(false), lattice( ), 
     170           0 :       maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
     171           0 :       pointingToImage(0), usezero_p(false), avgPB_p(nullptr), 
     172           0 :       epJ_p(nullptr),
     173           0 :       doPBCorrection(true), conjBeams_p(true),/*cfCache_p(cfcache),*/ paChangeDetector(),
     174           0 :       rotateOTFPAIncr_p(0.1),
     175           0 :       Second("s"),Radian("rad"),Day("d"), pbNormalized_p(false), paNdxProcessed_p(),
     176           0 :       visResampler_p(nullptr), sensitivityPatternQualifier_p(-1),sensitivityPatternQualifierStr_p(""),
     177           0 :     rotatedConvFunc_p(),
     178           0 :       runTime1_p(0.0), previousSPWID_p(-1), self_p(nullptr), vb2CFBMap_p(nullptr), po_p(nullptr),wbAWP_p(true), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0)
     179             :   {
     180             :     //    convSize=0;
     181           0 :     tangentSpecified_p=false;
     182           0 :     lastIndex_p=0;
     183           0 :     paChangeDetector.reset();
     184           0 :     pbLimit_p=5e-2;
     185             :     //
     186             :     // Get various parameters from the visibilities.  
     187             :     //
     188           0 :     doPointing=1; 
     189             : 
     190           0 :     maxConvSupport=-1;  
     191             :     //
     192             :     // Set up the Conv. Func. disk cache manager object.
     193             :     //
     194             :     // if (!cfCache_p.null()) delete &cfCache_p;
     195             :     // cfCache_p=cfcache;
     196           0 :     convSampling=-1;
     197             :     //convSize=CONVSIZE;
     198           0 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     199           0 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     200           0 :     if (cachesize > hostRAM) cachesize=hostRAM;
     201           0 :     sigma=1.0;
     202           0 :     canComputeResiduals_p=DORES;
     203             :     // cfs2_p = &cfCache_p->memCache2_p[0];//new CFStore2;
     204             :     // cfwts2_p =  &cfCache_p->memCacheWt2_p[0];//new CFStore2;
     205           0 :     pop_p->init();
     206           0 :     CFBuffer::initCFBStruct(cfbst_pub);
     207             :     //    rotatedConvFunc_p.data=new Array<Complex>();    
     208             :     //    self_p.reset(this);
     209           0 :     vb2CFBMap_p = new VB2CFBMap();
     210           0 :     po_p = new PointingOffsets();
     211           0 :     po_p->setOverSampling(convSampling);
     212           0 :   }
     213             :   //
     214             :   //---------------------------------------------------------------
     215             :   //
     216           0 :   AWProjectFT::AWProjectFT(Int nWPlanes, Long icachesize, 
     217             :                            CountedPtr<CFCache>& cfcache,
     218             :                            CountedPtr<ConvolutionFunction>& cf,
     219             :                            CountedPtr<VisibilityResamplerBase>& visResampler,
     220             :                            Bool applyPointingOffset,
     221             :                            vector<float> pointingOffsetSigDev,
     222             :                            Bool doPBCorr,
     223             :                            Int itilesize, 
     224             :                            Float pbLimit,
     225             :                            Bool usezero,
     226             :                            Bool conjBeams,
     227             :                            Bool doublePrecGrid,
     228           0 :                            PolOuterProduct::MuellerType muellerType)
     229           0 :     : FTMachine(cfcache,cf), padding_p(1.0), nWPlanes_p(nWPlanes),
     230           0 :       imageCache(0), cachesize(icachesize), tilesize(itilesize),
     231           0 :       gridder(0), isTiled(false), lattice( ), 
     232           0 :       maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
     233           0 :       pointingToImage(0), usezero_p(usezero), avgPB_p(nullptr),
     234             :       // convFunc_p(), convWeights_p(),
     235           0 :       epJ_p(),
     236           0 :       doPBCorrection(doPBCorr), conjBeams_p(conjBeams), 
     237           0 :       /*cfCache_p(cfcache),*/ paChangeDetector(),
     238           0 :       rotateOTFPAIncr_p(0.1),
     239           0 :       Second("s"),Radian("rad"),Day("d"), pbNormalized_p(false),
     240           0 :       visResampler_p(visResampler), sensitivityPatternQualifier_p(-1),sensitivityPatternQualifierStr_p(""),
     241           0 :       rotatedConvFunc_p(), runTime1_p(0.0),  previousSPWID_p(-1),self_p(nullptr), vb2CFBMap_p(nullptr), po_p(nullptr),wbAWP_p(true), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0)
     242             :   {
     243             :     //convSize=0;
     244           0 :     tangentSpecified_p=false;
     245           0 :     lastIndex_p=0;
     246           0 :     paChangeDetector.reset();
     247           0 :     pbLimit_p=pbLimit;
     248             :     //
     249             :     // Get various parameters from the visibilities.  
     250             :     //
     251           0 :     if (applyPointingOffset) doPointing=1; else doPointing=0;
     252             : 
     253           0 :     maxConvSupport=-1;  
     254             :     //
     255             :     // Set up the Conv. Func. disk cache manager object.
     256             :     //
     257             :     // if (!cfCache_p.null()) delete &cfCache_p;
     258             :     // cfCache_p=cfcache;
     259           0 :     convSampling=convFuncCtor_p->getOversampling();
     260             :     //convSize=CONVSIZE;
     261           0 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     262           0 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     263           0 :     if (cachesize > hostRAM) cachesize=hostRAM;
     264           0 :     sigma=1.0;
     265           0 :     canComputeResiduals_p=DORES;
     266           0 :     if (!cfCache_p.null())
     267             :       {
     268           0 :         cfs2_p = CountedPtr<CFStore2>(&(cfCache_p->memCache2_p)[0],false);//new CFStore2;
     269           0 :         cfwts2_p =  CountedPtr<CFStore2>(&cfCache_p->memCacheWt2_p[0],false);//new CFStore2;
     270             :       }
     271           0 :     pop_p->init();
     272           0 :     useDoubleGrid_p=doublePrecGrid;
     273             :     //    rotatedConvFunc_p.data=new Array<Complex>();
     274           0 :     CFBuffer::initCFBStruct(cfbst_pub);
     275           0 :     muellerType_p = muellerType;
     276             :     //    self_p.reset(this);
     277           0 :     vb2CFBMap_p = new VB2CFBMap();
     278           0 :     po_p = new PointingOffsets();
     279           0 :     po_p->setOverSampling(convSampling);
     280           0 :     vb2CFBMap_p->setPOSigmaDev(pointingOffsetSigDev);
     281           0 :     wbAWP_p=convFuncCtor_p->isWBAWP();
     282             : 
     283           0 :   }
     284             :   //
     285             :   //---------------------------------------------------------------
     286             :   //
     287           0 :   AWProjectFT::AWProjectFT(const RecordInterface& stateRec)
     288           0 :     : FTMachine(),Second("s"),Radian("rad"),Day("d"),visResampler_p(nullptr), self_p(nullptr), vb2CFBMap_p(nullptr), po_p(nullptr),wbAWP_p(true), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0)
     289             :   {
     290             :     //
     291             :     // Construct from the input state record
     292             :     //
     293           0 :     String error;
     294             :     
     295           0 :     if (!fromRecord(stateRec)) {
     296           0 :       LogIO log_l(LogOrigin("AWProjectFT2", "AWProjectFT[R&D]"));
     297           0 :       log_l << "Failed to create " << name() << " object." << LogIO::EXCEPTION;
     298           0 :     };
     299           0 :     maxConvSupport=-1;
     300             :     //convSampling=OVERSAMPLING;
     301           0 :     convSampling=-1;
     302           0 :     visResampler_p->init(useDoubleGrid_p);
     303             :     //convSize=CONVSIZE;
     304           0 :     canComputeResiduals_p=DORES;
     305           0 :     if (!cfCache_p.null())
     306             :       {
     307           0 :         cfs2_p = CountedPtr<CFStore2>(&cfCache_p->memCache2_p[0],false);//new CFStore2;
     308           0 :         cfwts2_p =  CountedPtr<CFStore2>(&cfCache_p->memCacheWt2_p[0],false);//new CFStore2;
     309             :       }
     310           0 :     pop_p->init();
     311             :     //    self_p.reset(this);
     312           0 :     vb2CFBMap_p = new VB2CFBMap();
     313           0 :     po_p = new PointingOffsets();
     314           0 :     po_p->setOverSampling(convSampling);
     315           0 :   }
     316             :   //
     317             :   //----------------------------------------------------------------------
     318             :   //
     319           0 :   AWProjectFT::AWProjectFT(const AWProjectFT& other):FTMachine()
     320             :   {
     321           0 :     operator=(other);
     322           0 :   }
     323             :   //
     324             :   //---------------------------------------------------------------
     325             :   //
     326             :   // This is nasty, we should use CountedPointers here.
     327           0 :   AWProjectFT::~AWProjectFT() 
     328             :   {
     329           0 :       if(imageCache) delete imageCache;
     330           0 :       imageCache=0;
     331           0 :       if(gridder) delete gridder;
     332           0 :       gridder=0;
     333           0 :   }
     334             :   //
     335             :   //---------------------------------------------------------------
     336             :   //
     337           0 :   AWProjectFT& AWProjectFT::operator=(const AWProjectFT& other)
     338             :   {
     339           0 :     if(this!=&other) 
     340             :       {
     341             :         //Do the base parameters
     342           0 :         FTMachine::operator=(other);
     343             : 
     344             :         
     345           0 :         padding_p=other.padding_p;
     346             :         
     347           0 :         nWPlanes_p=other.nWPlanes_p;
     348           0 :         imageCache=other.imageCache;
     349           0 :         cachesize=other.cachesize;
     350           0 :         tilesize=other.tilesize;
     351           0 :         cfRefFreq_p = other.cfRefFreq_p;
     352           0 :         if(other.gridder==0)
     353           0 :           gridder=0;
     354             :         else
     355             :           {
     356           0 :             uvScale.resize();
     357           0 :             uvOffset.resize();
     358           0 :             uvScale=other.uvScale;
     359           0 :             uvOffset=other.uvOffset;
     360           0 :             gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     361           0 :                                                            uvScale, uvOffset,
     362           0 :                                                            "SF");
     363             :           }
     364             : 
     365           0 :         isTiled=other.isTiled;
     366           0 :         lattice=0;
     367             : 
     368           0 :         maxAbsData=other.maxAbsData;
     369           0 :         centerLoc=other.centerLoc;
     370           0 :         offsetLoc=other.offsetLoc;
     371           0 :         pointingToImage=other.pointingToImage;
     372           0 :         usezero_p=other.usezero_p;
     373             : 
     374             :         
     375           0 :         padding_p=other.padding_p;
     376           0 :         imageCache=other.imageCache;
     377           0 :         cachesize=other.cachesize;
     378           0 :         tilesize=other.tilesize;
     379           0 :         isTiled=other.isTiled;
     380           0 :         maxAbsData=other.maxAbsData;
     381           0 :         centerLoc=other.centerLoc;
     382           0 :         offsetLoc=other.offsetLoc;
     383           0 :         pointingToImage=other.pointingToImage;
     384           0 :          useDoubleGrid_p=other.useDoubleGrid_p;
     385           0 :         doPBCorrection = other.doPBCorrection;
     386           0 :         maxConvSupport= other.maxConvSupport;
     387             : 
     388           0 :         epJ_p=other.epJ_p;
     389             :         //convSize=other.convSize;
     390           0 :         lastIndex_p=other.lastIndex_p;
     391           0 :         paChangeDetector=other.paChangeDetector;
     392           0 :         pbLimit_p=other.pbLimit_p;
     393             :         //
     394             :         // Get various parameters from the visibilities.  
     395             :         //
     396           0 :         doPointing=other.doPointing;
     397             : 
     398           0 :         maxConvSupport=other.maxConvSupport;
     399             :         //
     400             :         // Set up the Conv. Func. disk cache manager object.
     401             :         //
     402           0 :         cfCache_p=other.cfCache_p;
     403           0 :         convSampling=other.convSampling;
     404             :         //convSize=other.convSize;
     405           0 :         cachesize=other.cachesize;
     406             :     
     407           0 :         currentCFPA=other.currentCFPA;
     408           0 :         lastPAUsedForWtImg = other.lastPAUsedForWtImg;
     409           0 :         avgPB_p = other.avgPB_p;
     410             : 
     411           0 :         convFuncCtor_p = other.convFuncCtor_p;
     412           0 :         pbNormalized_p = other.pbNormalized_p;
     413           0 :         sensitivityPatternQualifier_p = other.sensitivityPatternQualifier_p;
     414           0 :         sensitivityPatternQualifierStr_p = other.sensitivityPatternQualifierStr_p;
     415           0 :         visResampler_p=other.visResampler_p; // Copy the counted pointer
     416             :         //      visResampler_p=other.visResampler_p->clone();
     417             :         //      *visResampler_p = *other.visResampler_p; // Call the appropriate operator=()
     418             : 
     419           0 :         rotatedConvFunc_p = other.rotatedConvFunc_p;
     420           0 :         cfs2_p = other.cfs2_p;
     421           0 :         cfwts2_p = other.cfwts2_p;
     422           0 :         paNdxProcessed_p = other.paNdxProcessed_p;
     423           0 :         imRefFreq_p = other.imRefFreq_p;
     424           0 :         conjBeams_p = other.conjBeams_p;
     425           0 :         rotateOTFPAIncr_p=other.rotateOTFPAIncr_p;
     426           0 :         computePAIncr_p=other.computePAIncr_p;
     427           0 :         runTime1_p = other.runTime1_p;
     428           0 :         muellerType_p = other.muellerType_p;
     429           0 :         previousSPWID_p = other.previousSPWID_p;
     430           0 :         vb2CFBMap_p = other.vb2CFBMap_p;
     431           0 :         po_p = other.po_p;
     432             :         //      self_p = other.self_p;
     433           0 :         wbAWP_p=other.wbAWP_p;
     434           0 :         timemass_p=0.0;
     435           0 :         timegrid_p=0.0;
     436           0 :         timedegrid_p=0.0;
     437             :       };
     438           0 :     return *this;
     439             :   };
     440             :   //
     441             :   //----------------------------------------------------------------------
     442             :   //
     443           0 :   void AWProjectFT::init() 
     444             :   {
     445           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "init[R&D]"));
     446             : 
     447           0 :     nx    = image->shape()(0);
     448           0 :     ny    = image->shape()(1);
     449           0 :     npol  = image->shape()(2);
     450           0 :     nchan = image->shape()(3);
     451             :     
     452             :     
     453           0 :     sumWeight.resize(npol, nchan);
     454           0 :     sumCFWeight.resize(npol, nchan);
     455             :     
     456           0 :     wConvSize=max(1, nWPlanes_p);
     457             :     
     458           0 :     CoordinateSystem cs=image->coordinates();
     459           0 :     uvScale.resize(3);
     460           0 :     uvScale=0.0;
     461           0 :     uvScale(0)=Float(nx)*cs.increment()(0); 
     462           0 :     uvScale(1)=Float(ny)*cs.increment()(1); 
     463           0 :     uvScale(2)=Float(wConvSize)*abs(cs.increment()(0));
     464             :     
     465           0 :     Int index= cs.findCoordinate(Coordinate::SPECTRAL);
     466           0 :     SpectralCoordinate spCS = cs.spectralCoordinate(index);
     467           0 :     imRefFreq_p = spCS.referenceValue()(0);
     468             :     
     469           0 :     uvOffset.resize(3);
     470           0 :     uvOffset(0)=nx/2;
     471           0 :     uvOffset(1)=ny/2;
     472           0 :     uvOffset(2)=0;
     473             :     
     474           0 :     if(gridder) delete gridder;
     475           0 :     gridder=0;
     476           0 :     gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     477           0 :                                                    uvScale, uvOffset,
     478           0 :                                                    "SF");
     479             :     
     480             :     // Set up image cache needed for gridding. 
     481           0 :     if(imageCache) delete imageCache;
     482           0 :     imageCache=0;
     483             :     
     484             :     // The tile size should be large enough that the
     485             :     // extended convolution function can fit easily
     486           0 :     if(isTiled) 
     487             :       {
     488           0 :         Float tileOverlap=0.5;
     489           0 :         tilesize=min(256,tilesize);
     490           0 :         IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
     491           0 :         Vector<Float> tileOverlapVec(4);
     492           0 :         tileOverlapVec=0.0;
     493           0 :         tileOverlapVec(0)=tileOverlap;
     494           0 :         tileOverlapVec(1)=tileOverlap;
     495             :         if (sizeof(long) < 4)  // 32-bit machine
     496             :           {
     497             :             Int tmpCacheVal=static_cast<Int>(cachesize);
     498             :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     499             :                                                    tileOverlapVec,
     500             :                                                    (tileOverlap>0.0));
     501             :           }
     502             :         else  // 64-bit machine
     503             :           {
     504           0 :             Long tmpCacheVal=cachesize;
     505           0 :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     506             :                                                    tileOverlapVec,
     507           0 :                                                    (tileOverlap>0.0));
     508             :           }
     509           0 :       }
     510             :     
     511             : #if(USETABLES)
     512             :     Double StepSize;
     513             :     Int N=500000;
     514             :     StepSize = abs((((2*nx)/uvScale(0))/(sigma) + 
     515             :                     MAXPOINTINGERROR*1.745329E-02*(sigma)/3600.0))/N;
     516             :     if (!awEij2.isReady())
     517             :       {
     518             :         log_l << "Making lookup table for exp function with a resolution of " 
     519             :               << StepSize << " radians.  "
     520             :               << "Memory used: " << sizeof(Float)*N/(1024.0*1024.0)<< " MB." 
     521             :               << LogIO::NORMAL 
     522             :               <<LogIO::POST;
     523             :         
     524             :         awEij2.setSigma(sigma);
     525             :         awEij2.initExpTable(N,StepSize);
     526             :         //    ExpTab.build(N,StepSize);
     527             :         
     528             :         log_l << "Making lookup table for complex exp function with a resolution of " 
     529             :               << 2*M_PI/N << " radians.  "
     530             :               << "Memory used: " << 2*sizeof(Float)*N/(1024.0*1024.0) << " MB." 
     531             :               << LogIO::NORMAL
     532             :               << LogIO::POST;
     533             :         awEij2.initCExpTable(N);
     534             :         //    CExpTab.build(N);
     535             :       }
     536             : #endif
     537             :     //    vpSJ->reset();
     538           0 :     paChangeDetector.reset();
     539           0 :     makingPSF = false;
     540             :     
     541           0 :     log_l << "Using " << visResampler_p->name() << " visibility resampler (a.k.a. \"gridder/degridder\")" << LogIO::POST;
     542           0 :     vb2CFBMap_p->computePhaseScreen_p = visResampler_p->needCFPhaseScreen();
     543             :     //cerr << "Current runTime = " << runTime << endl;
     544           0 :   }
     545             :   //
     546             :   //---------------------------------------------------------------
     547             :   //
     548           0 :   MDirection::Convert AWProjectFT::makeCoordinateMachine(const VisBuffer2& vb,
     549             :                                                          const MDirection::Types& From,
     550             :                                                          const MDirection::Types& To,
     551             :                                                          MEpoch& last)
     552             :   {
     553           0 :     LogIO log_l(LogOrigin("AWProjectFT2","makeCoordinateMachine[R&D]"));
     554           0 :     Double time = getCurrentTimeStamp(vb);
     555             :     
     556           0 :     MEpoch epoch(Quantity(time,Second),MEpoch::TAI);
     557             :     //  epoch = MEpoch(Quantity(time,Second),MEpoch::TAI);
     558             :     //
     559             :     // ...now make an object to hold the observatory position info...
     560             :     //
     561           0 :     MPosition pos;
     562           0 :     String ObsName=(vb.subtableColumns()).observation().telescopeName()(vb.arrayId()(0));
     563             :     
     564           0 :     if (!MeasTable::Observatory(pos,ObsName))
     565           0 :       log_l << "Observatory position for "+ ObsName + " not found"
     566           0 :             << LogIO::EXCEPTION;
     567             :     //
     568             :     // ...now make a Frame object out of the observatory position and
     569             :     // time objects...
     570             :     //
     571           0 :     MeasFrame frame(epoch,pos);
     572             :     //
     573             :     // ...finally make the convert machine.
     574             :     //
     575           0 :     MDirection::Convert mac(MDirection::Ref(From,frame),
     576           0 :                             MDirection::Ref(To,frame));
     577             :     
     578           0 :     MEpoch::Convert toLAST = MEpoch::Convert(MEpoch::Ref(MEpoch::TAI,frame),
     579           0 :                                              MEpoch::Ref(MEpoch::LAST,frame));
     580           0 :     last = toLAST(epoch);
     581             :     
     582           0 :     return mac;
     583           0 :   }
     584             :   //
     585             :   //---------------------------------------------------------------
     586             :   //
     587           0 :   int AWProjectFT::findPointingOffsets(const VisBuffer2& vb, 
     588             :                                         Array<Float> &l_off,
     589             :                                         Array<Float> &m_off,
     590             :                                         Bool Evaluate)
     591             :   {
     592             :     //    LogIO log_l(LogOrigin("AWProjectFT2", "findPointingOffsets[R&D]"));
     593           0 :     Int NAnt = 0;
     594           0 :     MEpoch LAST;
     595           0 :     Double thisTime = getCurrentTimeStamp(vb);
     596             :     //    Array<Float> pointingOffsets = epJ->nearest(thisTime);
     597           0 :     if (epJ_p.null()) return 0;
     598           0 :     Array<Float> pointingOffsets; epJ_p->nearest(thisTime,pointingOffsets);
     599           0 :     NAnt=pointingOffsets.shape()(2);
     600           0 :     l_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     601           0 :     m_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     602             :     // Can't figure out how to do the damn slicing of [Pol,NChan,NAnt,1] array
     603             :     // into [Pol,NChan,NAnt] array
     604             :     //
     605           0 :     IPosition tndx(3,0,0,0), sndx(4,0,0,0,0);
     606           0 :     for(tndx(2)=0;tndx(2)<NAnt; tndx(2)++,sndx(2)++)
     607             :       {
     608           0 :         sndx(0)=0; l_off(tndx) = pointingOffsets(sndx);
     609           0 :         sndx(0)=2; m_off(tndx) = pointingOffsets(sndx);
     610             :       }
     611           0 :     return NAnt;
     612             :     if (!Evaluate) return NAnt;
     613             :     
     614             :     //
     615             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     616             :     // (HA,Dec).
     617             :     //
     618             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     619             :                                                        MDirection::AZEL,
     620             :                                                        LAST);
     621             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     622             :                                                         MDirection::HADEC,
     623             :                                                         LAST);
     624             :     //
     625             :     // ...and now hope that it all works and works correctly!!!
     626             :     //
     627             :     Quantity dAz(0,Radian),dEl(0,Radian);
     628             :     //
     629             :     // An array of shape [2,1,1]!
     630             :     //
     631             :     Array<Double> phaseDir = vb.subtableColumns().field().phaseDir().getColumn();
     632             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     633             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     634             :     //  
     635             :     // Compute reference (HA,Dec)
     636             :     //
     637             :     Double LST   = LAST.get(Day).getValue();
     638             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     639             :     LST -= floor(LST); // Extract the fractional day
     640             :     LST *= 2*C::pi;// Convert to Raidan
     641             :     
     642             :     Double HA0;
     643             :     HA0 = LST - RA0;
     644             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     645             :     //
     646             :     // Convert reference (HA,Dec) to reference (Az,El)
     647             :     //
     648             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     649             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     650             :     
     651             :     MDirection tmpHADec = toHADec(AzEl0);
     652             :     
     653             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     654             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     655             :     
     656             :     //
     657             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     658             :     //
     659             :     
     660             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     661             :       {
     662             :         //
     663             :         // From (Az,El) -> (HA,Dec)
     664             :         //
     665             :         // Add (Az,El) offsets to the reference (Az,El)
     666             :         //
     667             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     668             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     669             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     670             :         //
     671             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     672             :         //
     673             :         MDirection HADec = toHADec(AzEl);
     674             :         Double HA,Dec,RA, dRA;
     675             :         HA  = HADec.getAngle(Radian).getValue()(0);
     676             :         Dec = HADec.getAngle(Radian).getValue()(1);
     677             :         RA  = LST - HA;
     678             :         dRA = RA - RA0;
     679             :         //
     680             :         // Convert offsetted (RA,Dec) -> (l,m)
     681             :         //
     682             :         l_off(n)  = sin(dRA)*cos(Dec);
     683             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     684             :       }
     685             :     
     686             :     return NAnt+1;
     687           0 :   }
     688             :   //
     689             :   //---------------------------------------------------------------
     690             :   //
     691           0 :   int AWProjectFT::findPointingOffsets(const VisBuffer2& vb, 
     692             :                                          Cube<Float>& pointingOffsets,
     693             :                                         Array<Float> &l_off,
     694             :                                         Array<Float> &m_off,
     695             :                                         Bool Evaluate)
     696             :   {
     697             :     //    LogIO log_l(LogOrigin("AWProjectFT2", "findPointingOffsets[R&D]"));
     698           0 :     Int NAnt = 0;
     699             :     //Float tmp;
     700             :     // TBD: adapt the following to VisCal mechanism:
     701           0 :     MEpoch LAST;
     702             :     
     703           0 :     NAnt=pointingOffsets.shape()(2);
     704           0 :     l_off.resize(IPosition(3,2,1,NAnt));
     705           0 :     m_off.resize(IPosition(3,2,1,NAnt));
     706           0 :     IPosition ndx(3,0,0,0),ndx1(3,0,0,0);
     707           0 :     for(ndx(2)=0;ndx(2)<NAnt;ndx(2)++)
     708             :       {
     709           0 :         ndx1=ndx;
     710           0 :         ndx(0)=0;ndx1(0)=0;     //tmp=l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_0,Ant_i
     711           0 :         ndx(0)=1;ndx1(0)=1;     //tmp=l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_1,Ant_i
     712           0 :         ndx(0)=0;ndx1(0)=2;     //tmp=m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_0,Ant_i
     713           0 :         ndx(0)=1;ndx1(0)=3;     //tmp=m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_1,Ant_i
     714             :       }
     715             : 
     716           0 :     return NAnt;
     717             :     if (!Evaluate) return NAnt;
     718             :     
     719             :     //
     720             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     721             :     // (HA,Dec).
     722             :     //
     723             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     724             :                                                        MDirection::AZEL,
     725             :                                                        LAST);
     726             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     727             :                                                         MDirection::HADEC,
     728             :                                                         LAST);
     729             :     //
     730             :     // ...and now hope that it all works and works correctly!!!
     731             :     //
     732             :     Quantity dAz(0,Radian),dEl(0,Radian);
     733             :     //
     734             :     // An array of shape [2,1,1]!
     735             :     //
     736             :     Array<Double> phaseDir = vb.subtableColumns().field().phaseDir().getColumn();
     737             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     738             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     739             :     //  
     740             :     // Compute reference (HA,Dec)
     741             :     //
     742             :     Double LST   = LAST.get(Day).getValue();
     743             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     744             :     LST -= floor(LST); // Extract the fractional day
     745             :     LST *= 2*C::pi;// Convert to Raidan
     746             :     
     747             :     Double HA0;
     748             :     HA0 = LST - RA0;
     749             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     750             :     //
     751             :     // Convert reference (HA,Dec) to reference (Az,El)
     752             :     //
     753             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     754             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     755             :     
     756             :     MDirection tmpHADec = toHADec(AzEl0);
     757             :     
     758             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     759             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     760             :     
     761             :     //
     762             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     763             :     //
     764             :     
     765             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     766             :       {
     767             :         //
     768             :         // From (Az,El) -> (HA,Dec)
     769             :         //
     770             :         // Add (Az,El) offsets to the reference (Az,El)
     771             :         //
     772             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     773             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     774             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     775             :         //
     776             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     777             :         //
     778             :         MDirection HADec = toHADec(AzEl);
     779             :         Double HA,Dec,RA, dRA;
     780             :         HA  = HADec.getAngle(Radian).getValue()(0);
     781             :         Dec = HADec.getAngle(Radian).getValue()(1);
     782             :         RA  = LST - HA;
     783             :         dRA = RA - RA0;
     784             :         //
     785             :         // Convert offsetted (RA,Dec) -> (l,m)
     786             :         //
     787             :         l_off(n)  = sin(dRA)*cos(Dec);
     788             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     789             :       }
     790             :     
     791             :     return NAnt+1;
     792           0 :   }
     793             :   //
     794             :   //---------------------------------------------------------------
     795             :   // The method below is for making the sensitivty image directly from
     796             :   // image-plane models of the PB.  This is efficiently done via
     797             :   // ConvolutionFunction classes, at least for the ray traced models.
     798             :   //
     799             :   // For Wide-band AWP, this is computed in a wide-band sense by
     800             :   // accumulating WT*CF and FT'ing the resulting complex grid.  This
     801             :   // is relatively more expensive but is a one-time cost.  This method
     802             :   // (defined in C++ as the name plus the function signature) is
     803             :   // therefore overloaded in AWProjectWBFT which, in case the
     804             :   // sensitivity pattern (.pb image) is not found, only issues a
     805             :   // message informing that the first gridding cycle will do this
     806             :   // accumulation and therefore will be slower than the subsequent
     807             :   // ones.  The steps necessary to compute the WB sensitivity pattern are:
     808             :   //
     809             :   //     1. Accumulate CFs (done via AWProjectWBFT::resampleCFToGrid())
     810             :   //     2. FT the grid (done via AWProjectWBFT::ftWeightImage()).
     811             :   //        This gives PBs in the feed pol basis.
     812             :   //     3. Compute the Stokes PBs from feed basis
     813             :   //
     814             :   // The accumulation is done via the
     815             :   // AWProjectWBFT::resampleCFToGrid() method (which, for accumulating
     816             :   // the CFs, is the equivalent of ::resampledDataToGrid()).  FT and
     817             :   // averaging across feed-pol planes is done in the following method:
     818             :   //
     819             :   // AWProjectWBFT::makeWBSensitivityImage(Lattice<T>&,
     820             :   //                                       ImageInterface<Float>&,
     821             :   //                                       const Matrix<Float>&,
     822             :   //                                       const Bool&)
     823             :   //
     824             :   // (which uses the AWProjectWBFT::ftWeightImage() method for FFT).
     825             :   // This method is expected to be a NoOp if avgPBReady_p state
     826             :   // variable is True.  Since these operations can be done only at the
     827             :   // _end_ of the (first) gridding cycle, they are naturally triggered
     828             :   // in the ImageInterface<Complex>& AWProjectWBFT::getImage() method,
     829             :   // which is also overloaded to first call
     830             :   // AWProjectWBFT::makeWBSensitivityImage() (which makes the PB and
     831             :   // points the class variables avgPB_p to it).  And then call
     832             :   // AWProjectFT::getImage() (which normalizes the sky images).
     833             :   //
     834           0 :   void AWProjectFT::makeSensitivityImage(const VisBuffer2& vb, 
     835             :                                          const ImageInterface<Complex>& imageTemplate,
     836             :                                          ImageInterface<Float>& sensitivityImage)
     837             :   {
     838           0 :     if (convFuncCtor_p->makeAverageResponse(vb, imageTemplate, sensitivityImage))
     839           0 :       cfCache_p->flush(sensitivityImage,sensitivityPatternQualifierStr_p); 
     840           0 :   }
     841             :   //
     842             :   //---------------------------------------------------------------
     843             :   //
     844           0 :   void AWProjectFT::makeCFPolMap(const VisBuffer2& vb, const Vector<Int>& locCfStokes,
     845             :                                  Vector<Int>& polM)
     846             :   {
     847           0 :     Vector<Int> msStokes = vb.correlationTypes();
     848           0 :     Int nPol = msStokes.nelements();
     849           0 :     polM.resize(polMap.shape());
     850           0 :     polM = -1;
     851             : 
     852           0 :     for(Int i=0;i<nPol;i++)
     853           0 :       for(uInt j=0;j<locCfStokes.nelements();j++)
     854           0 :         if (locCfStokes(j) == msStokes(i))
     855           0 :             {polM(i) = j;break;}
     856           0 :   }
     857             :   //
     858             :   //---------------------------------------------------------------
     859             :   //
     860             :   // Given a polMap (mapping of which Visibility polarization is
     861             :   // gridded onto which grid plane), make a map of the conjugate
     862             :   // planes of the grid E.g, for Stokes-I and -V imaging, the two
     863             :   // planes of the uv-grid are [LL,RR].  For input VisBuffer2
     864             :   // visibilites in order [RR,RL,LR,LL], polMap = [1,-1,-1,0].  The
     865             :   // conjugate map will be [0,-1,-1,1].
     866             :   //
     867           0 :   void AWProjectFT::makeConjPolMap(const VisBuffer2& vb, 
     868             :                                      const Vector<Int> cfPolMap, 
     869             :                                      Vector<Int>& conjPolMap)
     870             :   {
     871           0 :     if (conjPolMap.nelements() > 0) return;
     872             : 
     873           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "makConjPolMap[R&D]"));
     874             : 
     875             :     //
     876             :     // All the Natak (Drama) below with slicers etc. is to extract the
     877             :     // Poln. info. for the first IF only (not much "information
     878             :     // hiding" for the code to slice arrays in a general fashion).
     879             :     //
     880             :     // Extract the shape of the array to be sliced.
     881             :     //
     882             :     //    Array<Int> stokesForAllIFs = vb.subtableColumns().polarization().corrType().getColumn();
     883             :     log_l << "############....temp code!!!!!!!!!! "
     884           0 :           << SynthesisUtils::mapSpwIDToPolID(vb, vb.spectralWindows()[0])
     885           0 :           << LogIO::DEBUG1;
     886           0 :     Vector<Int> polIDs=SynthesisUtils::mapSpwIDToPolID(vb,vb.spectralWindows()[0]);
     887           0 :     if (polIDs.nelements()==0)
     888           0 :       log_l << "Internal Error: Selected SPW did not map to any pol!" << LogIO::EXCEPTION;
     889             :     //
     890             :     // Use the first selected Spw to determine the pol. mapping in the
     891             :     // VB.  This implies that the code assumes that all selected SPWs
     892             :     // have the same pol. setup.
     893             :     //
     894           0 :     Int polID=polIDs(0);
     895           0 :     Array<Int> stokesForAllIFs = (vb.subtableColumns()).polarization().corrType().get(polID);
     896           0 :     IPosition stokesShape(stokesForAllIFs.shape());
     897           0 :     IPosition firstIFStart(stokesShape),firstIFLength(stokesShape);
     898             :     //
     899             :     // Set up the start and length IPositions to extract only the
     900             :     // first column of the array.  The following is required since the
     901             :     // array could have only one column as well.
     902             :     //
     903           0 :     firstIFStart(0)=0;firstIFLength(0)=stokesShape(0);
     904           0 :     for(uInt i=1;i<stokesShape.nelements();i++) {firstIFStart(i)=0;firstIFLength(i)=1;}
     905             :     //
     906             :     // Construct the slicer and produce the slice.  .nonDegenerate
     907             :     // required to ensure the result of slice is a pure vector.
     908             :     //
     909           0 :     Vector<Int> visStokes = stokesForAllIFs(Slicer(firstIFStart,firstIFLength)).nonDegenerate();
     910             : 
     911           0 :     conjPolMap = cfPolMap;
     912             :     
     913           0 :     Int i,j,N = cfPolMap.nelements();
     914           0 :     for(i=0;i<N;i++)
     915           0 :       if (cfPolMap[i] > -1)
     916             :         {
     917           0 :         if      (visStokes[i] == Stokes::RR) 
     918             :           {
     919           0 :             conjPolMap[i]=-1;
     920           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LL) break; 
     921           0 :             conjPolMap[i]=cfPolMap[j];
     922             :           }
     923           0 :         else if (visStokes[i] == Stokes::LL) 
     924             :           {
     925           0 :             conjPolMap[i]=-1;
     926           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RR) break; 
     927           0 :             conjPolMap[i]=cfPolMap[j];
     928             :           }
     929           0 :         else if (visStokes[i] == Stokes::LR) 
     930             :           {
     931           0 :             conjPolMap[i]=-1;
     932           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RL) break; 
     933           0 :             conjPolMap[i]=cfPolMap[j];
     934             :           }
     935           0 :         else if (visStokes[i] == Stokes::RL) 
     936             :           {
     937           0 :             conjPolMap[i]=-1;
     938           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LR) break; 
     939           0 :             conjPolMap[i]=cfPolMap[j];
     940             :           }
     941             :         }
     942           0 :   }
     943             :   //
     944             :   //---------------------------------------------------------------
     945             :   // Convert the CFs in the supplied CFStore to
     946             :   // A(nu)<Convolution>A(nu_*)
     947             :   //
     948           0 :   void AWProjectFT::makeWBCFWt(CFStore2& cfs, const Double imRefFreq)
     949             :   {
     950           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "makeWBCFWt[R&D]"));
     951           0 :     log_l << "Converting WTCFs to wide-band versions" << LogIO::POST;
     952             : 
     953           0 :     Vector<Int> ant1List, ant2List;
     954           0 :     Vector<Quantity> paList;
     955           0 :     ant1List = cfs.getAnt1List();
     956           0 :     ant2List = cfs.getAnt2List();
     957           0 :     paList   = cfs.getPAList();
     958             : 
     959           0 :     if (paNdxProcessed_p.nelements() == 0) {paNdxProcessed_p.resize(1); paNdxProcessed_p[0]=false;}
     960           0 :     CountedPtr<CFBuffer> cfb_l, cfb_clone;
     961           0 :     Quantity dPA(360.0,"deg");
     962           0 :     for (uInt pa=0;pa<paList.nelements();pa++)
     963           0 :       for (uint a1=0;a1<ant1List.nelements(); a1++)
     964           0 :         for (uint a2=0;a2<ant2List.nelements(); a2++)
     965             :           {
     966           0 :             if (paNdxProcessed_p.nelements() < pa) {paNdxProcessed_p.resize(pa+1,true); paNdxProcessed_p[pa]=false;}
     967           0 :             if (!paNdxProcessed_p[pa])
     968             :               {
     969           0 :                 paNdxProcessed_p[pa]=true;
     970           0 :                 Vector<Double> wVals, fVals; PolMapType mVals, mNdx, conjMVals, conjMNdx;
     971             :                 Double fIncr, wIncr;
     972           0 :                 cfb_l = cfs.getCFBuffer(paList[pa], dPA, ant1List(a1), ant2List(a2));
     973           0 :                 cfb_l->getCoordList(fVals,wVals,mNdx, mVals, conjMNdx, conjMVals, fIncr, wIncr);
     974             :                 
     975           0 :                 cfb_clone=cfb_l->clone();
     976           0 :                 cfb_clone->getCoordList(fVals,wVals,mNdx, mVals, conjMNdx, conjMVals, fIncr, wIncr);
     977             : 
     978           0 :                 CountedPtr<Array<Complex> > cfc_l, conjCFC_l, result_l;
     979             :                 //
     980             :                 // Damn!  Convolver does not work for complex convolution!
     981             :                 //              Convolver<Complex> convolver;
     982             : 
     983           0 :                 for (Int nw=0;nw<(Int)wVals.nelements(); nw++)
     984           0 :                   for (Int nf=0;nf<(Int)fVals.nelements(); nf++)
     985           0 :                     for (Int ipol=0;ipol<(Int)conjMVals.nelements();ipol++)
     986           0 :                       for (Int mRow=0;mRow<(Int)conjMVals[ipol].nelements(); mRow++)
     987             :                         {
     988             :                           Double f, cf;
     989           0 :                           f=fVals[nf];
     990           0 :                           cf=sqrt(2*imRefFreq*imRefFreq - f*f);
     991           0 :                           Int conjNF = cfb_l->nearestFreqNdx(cf);
     992             : 
     993           0 :                           result_l  = cfb_l->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow])->getStorage();
     994           0 :                           cfc_l     = cfb_clone->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow])->getStorage();
     995           0 :                           conjCFC_l = cfb_clone->getCFCellPtr(conjNF,nw,conjMNdx[ipol][mRow])->getStorage();
     996             : 
     997           0 :                           SynthesisUtils::libreConvolver(*result_l,*conjCFC_l);
     998             :                         }
     999           0 :               }
    1000             :           }
    1001           0 :   }
    1002             :   //
    1003             :   // Locate a convlution function.  It will be either in the cache
    1004             :   // (mem. or disk cache) or will be computed and cached for possible
    1005             :   // later use.
    1006             :   //
    1007           0 :   void AWProjectFT::findConvFunction(const ImageInterface<Complex>& image,
    1008             :                                      const VisBuffer2& vb)
    1009             :   {
    1010           0 :     if (!paChangeDetector.changed(vb,0)) return;
    1011           0 :     Int cfSource=CFDefs::NOTCACHED;
    1012           0 :     CoordinateSystem ftcoords;
    1013             :     // Think of a generic call to get the key-values.  And a
    1014             :     // overloadable method (or an externally supplied one?) to convert
    1015             :     // the values to key-ids.  That will ensure that AWProjectFT
    1016             :     // remains the A-Projection algorithm implementation configurable
    1017             :     // by the behaviour of the supplied objects.
    1018           0 :     Float pa=getVBPA(vb);
    1019             :     //UUU// ok();
    1020           0 :     visResampler_p->setMaps(chanMap, polMap); //UUU Added here.
    1021           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    1022             : 
    1023           0 :     lastPAUsedForWtImg = currentCFPA = pa;
    1024             : 
    1025             :     //Vector<Vector<Double> > pointingOffset(convFuncCtor_p->findPointingOffset(image,vb, doPointing));
    1026             : 
    1027             :     // PO::setOverSampling needs to be called here since
    1028             :     // convFuncCtor_p gets that value from a combination of (1)
    1029             :     // ATerm_OVERSAMPLING env. variable, (2) ATERM.OVERSAMPLING in
    1030             :     // ~/.casa and (3) from existing CFCache.  This setting in the AWP
    1031             :     // constructor will only get the default value from ATerm.h
    1032           0 :     convSampling=convFuncCtor_p->getOversampling();
    1033           0 :     po_p->setOverSampling(convFuncCtor_p->getOversampling());
    1034             :     // PO::fetchPointingOffset() only updates the internal cache in PO
    1035             :     // class.  PO::pullPointingOffset() is required to extract in the
    1036             :     // calling class.
    1037           0 :     po_p->fetchPointingOffset(image,vb, doPointing);
    1038             : 
    1039           0 :     Float dPA = paChangeDetector.getParAngleTolerance().getValue("rad");
    1040           0 :     Quantity dPAQuant = Quantity(paChangeDetector.getParAngleTolerance());
    1041             : 
    1042           0 :     vb2CFBMap_p->setDoPointing(doPointing);
    1043           0 :     cfSource = vb2CFBMap_p->makeVBRow2CFBMap(*cfs2_p,
    1044             :                                                 vb,
    1045             :                                                 dPAQuant,
    1046           0 :                                                 chanMap,polMap,po_p);
    1047             : 
    1048           0 :     if (cfSource == CFDefs::NOTCACHED)
    1049             :       {
    1050           0 :         PolMapType polMat, polIndexMat, conjPolMat, conjPolIndexMat;
    1051           0 :         Vector<Int> visPolMap(vb.correlationTypes());
    1052           0 :         polMat = pop_p->makePolMat(visPolMap,polMap);
    1053           0 :         polIndexMat = pop_p->makePol2CFMat(visPolMap,polMap);
    1054             : 
    1055           0 :         conjPolMat = pop_p->makeConjPolMat(visPolMap,polMap);
    1056           0 :         conjPolIndexMat = pop_p->makeConjPol2CFMat(visPolMap,polMap);
    1057             : 
    1058           0 :         convFuncCtor_p->setPolMap(polMap);
    1059           0 :         convFuncCtor_p->setSpwSelection(spwChanSelFlag_p);
    1060           0 :         convFuncCtor_p->setSpwFreqSelection(spwFreqSel_p);
    1061             : 
    1062             :         // USEFUL DEBUG MESSAGE
    1063             :         //cerr << "Freq. selection: " << expandedSpwFreqSel_p << endl << expandedSpwConjFreqSel_p << endl;
    1064           0 :         Bool pleaseDoAlsoFillTheCF=!dryRun();
    1065           0 :         convFuncCtor_p->makeConvFunction(image,vb,wConvSize, 
    1066           0 :                                          pop_p, pa, dPA, uvScale, uvOffset,spwFreqSel_p,
    1067             :                                          *cfs2_p, *cfwts2_p, pleaseDoAlsoFillTheCF);
    1068           0 :       }
    1069             :     //
    1070             :     // If one-time-operations in the CFCache not yet done, set the
    1071             :     // pol. index maps in the CFCache.
    1072             :     //
    1073           0 :     if (!cfCache_p->OTODone())
    1074             :       {
    1075             :         //Vector<Int> visPolMap(vb.corrType());
    1076           0 :         Vector<Int> visPolMap(vb.correlationTypes());
    1077             : 
    1078           0 :         PolMapType polMat, conjPolMat;
    1079           0 :         polMat = pop_p->makePolMat(visPolMap,polMap);
    1080           0 :         conjPolMat = pop_p->makeConjPolMat(visPolMap,polMap);
    1081             : 
    1082           0 :         PolMapType pNdx, cpNdx;
    1083           0 :         pNdx = pop_p->makePol2CFMat(visPolMap,polMap);
    1084           0 :         cpNdx = pop_p->makeConjPol2CFMat(visPolMap,polMap);
    1085             :     
    1086           0 :         cfCache_p->initPolMaps(pNdx,cpNdx);
    1087             : 
    1088           0 :         cfs2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1089           0 :         cfwts2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1090           0 :       }
    1091             :     //
    1092             :     // Load the average PB (sensitivity pattern) from the cache.  If
    1093             :     // not found in the cache, make one and cache it.
    1094             :     //
    1095           0 :         std::tuple<int, double>cubeinfo(1,-1.0);
    1096             :         double freqofBegChan;
    1097           0 :         spectralCoord_p.toWorld(freqofBegChan, 0.0);
    1098             :         
    1099           0 :         cubeinfo=std::make_tuple(image.shape()(3),freqofBegChan);
    1100             : 
    1101           0 :         if(!avgPBReady_p)
    1102           0 :           avgPBReady_p = (cfCache_p->loadAvgPB(avgPB_p,sensitivityPatternQualifierStr_p, cubeinfo) != CFDefs::NOTCACHED);
    1103             :     
    1104           0 :     if(avgPBReady_p){
    1105           0 :         LatticeExprNode le( max( *avgPB_p ) );
    1106           0 :         Float avgPB_max=le.getFloat();
    1107             :         
    1108           0 :         if(avgPB_max <= 0.0) avgPBReady_p = false;
    1109           0 :     }
    1110             :     
    1111           0 :     if(!avgPBReady_p) makeSensitivityImage(vb,image,*avgPB_p);
    1112             : 
    1113             :         
    1114             :     
    1115           0 :     verifyShapes(avgPB_p->shape(), image.shape());
    1116             : 
    1117           0 :     if (paChangeDetector.changed(vb,0)) paChangeDetector.update(vb,0);
    1118             :     //
    1119             :     // Write some useful info. to the logger.
    1120             :     //
    1121           0 :     if (cfSource != CFDefs::MEMCACHE)
    1122             :       {
    1123             :         // If dry run, write the uvgrid as an image for later use in
    1124             :         // filling the empty CFCache.  Only the co-ordinate system of
    1125             :         // the uvgrid is required later.
    1126           0 :         if (dryRun())
    1127             :           {
    1128           0 :             PagedImage<Complex> thisGrid(image.shape(),image.coordinates(), 
    1129           0 :                                          cfCache_p->getCacheDir()+"/uvgrid.im");
    1130           0 :           }
    1131             :         // Save only the CF Cube for the current value of PA (not the
    1132             :         // entire CFStore -- CFs for PA values encountered earlier
    1133             :         // than current value have already need made persistent).
    1134           0 :         cfs2_p->makePersistent(cfCache_p->getCacheDir().c_str(),"","",    Quantity(pa,"rad"),dPAQuant,0,0);
    1135           0 :         cfwts2_p->makePersistent(cfCache_p->getCacheDir().c_str(),"","WT",Quantity(pa,"rad"),dPAQuant,0,0);
    1136           0 :         Double memUsed=cfs2_p->memUsage();
    1137           0 :         String unit(" KB");
    1138           0 :         memUsed = (Int)(memUsed/1024.0+0.5);
    1139           0 :         if (memUsed > 1024) {memUsed /=1024; unit=" MB";}
    1140             : 
    1141           0 :         LogIO log_l(LogOrigin("AWProjectFT2", "findConvFunction[R&D]"));
    1142             :         log_l << "Convolution function memory footprint:" 
    1143             :               << (Int)(memUsed) << unit << " out of a maximum of "
    1144           0 :               << HostInfo::memoryTotal(true)/1024 << " MB" << LogIO::POST;
    1145             :         
    1146             :         //
    1147             :         // Initialize any internal maps that may be used later for
    1148             :         // efficient access.
    1149             :         //
    1150           0 :         cfs2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1151           0 :         cfwts2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1152           0 :       }
    1153           0 :   }
    1154             :   //
    1155             :   //------------------------------------------------------------------------------
    1156             :   // Vectorized initializeToVis.  See design related comments in the
    1157             :   // .h file.
    1158             :   //
    1159             :   //
    1160             :   // The functional goals here are:
    1161             :   //
    1162             :   //  1. If doPBCorrection==true (i.e. the input sky-image is flat-sky
    1163             :   //  image), divide the image by the PB
    1164             :   //
    1165             :   //  2. Convert from Stokes to Feed (correlation) frame
    1166             :   //
    1167             :   //  3. FFT the image to produce gridded vis.
    1168             :   //
    1169             :   //  4. And since the same image buffer is used to accumulate the
    1170             :   //  model, multiply the sky-image back with PB
    1171             :   //
    1172             :   // The call to non-vectorized version of initializeToVis() which is
    1173             :   // pure virtual and hence the local version is called, is only to do
    1174             :   // the FFT.  FFT is *NOT* in place.
    1175             :   //
    1176             :   // These operations effecitvely maintains the model image as PB*Sky
    1177             :   // and supplies flat-sky model for prediction.  This can probably be
    1178             :   // achieve with fewer operations and same memory buffers....but that
    1179             :   // for later (SB)
    1180           0 :   void AWProjectFT::initializeToVis(Block<CountedPtr<ImageInterface<Complex> > > & compImageVec,
    1181             :                                     PtrBlock<SubImage<Float> *> & modelImageVec, 
    1182             :                                     PtrBlock<SubImage<Float> *>& weightImageVec, 
    1183             :                                     PtrBlock<SubImage<Float> *>& /*fluxScaleVec*/, 
    1184             :                                     Block<Matrix<Float> >& weightsVec,
    1185             :                                     const VisBuffer2& vb)
    1186             :   {
    1187           0 :     LogIO log_p(LogOrigin("AWProjectFT2","initToVis[V][R&D]"));
    1188             :     //
    1189             :     // Setting the image below is crucial since init() and
    1190             :     // initMaps(vb) below expect this to be set.
    1191             :     //
    1192           0 :     image=&(*compImageVec[0]);
    1193             : 
    1194             :     log_p << "Total flux in model image (before avgPB normalization): " 
    1195           0 :           << sum((*(modelImageVec[0])).get()) 
    1196           0 :           << LogIO::POST;
    1197           0 :     if(doPBCorrection) 
    1198             :       {
    1199             :         // Make the sensitivity Image if applicable
    1200           0 :         init();
    1201           0 :         initMaps(vb);
    1202           0 :         findConvFunction(*(compImageVec[0]), vb); // Pure virtual -- call local version
    1203             : 
    1204           0 :         if (isDryRun) return;
    1205             : 
    1206             :         // Get the sensitivity Image
    1207           0 :         Matrix<Float> tempWts;
    1208           0 :         tempWts.resize();
    1209           0 :         getWeightImage(*(weightImageVec[0]), tempWts);  // Pure virtual -- call local version
    1210             : 
    1211             :         // Normalize the model image by the sensitivity image only.
    1212             :         // No local implementation -- call FTMachine version
    1213             : 
    1214             :         // Divide by avgPB ///// PBWeight
    1215             :         //
    1216             : 
    1217             :         // Divide by sqrt(avgPB) ////// PBSQWeight
    1218             :         //
    1219           0 :          normalizeImage( *(modelImageVec[0]) , weightsVec[0],  *(weightImageVec[0]), 
    1220           0 :                         false, (Float)pbLimit_p, (Int)4);
    1221           0 :       }
    1222             :     log_p << "Total flux in model image (after avgPB normalization): " 
    1223           0 :           << sum((*(modelImageVec[0])).get()) << LogIO::POST;
    1224             :     
    1225             :     // Convert from Stokes planes to Correlation planes
    1226             :     // No local implementation -- call FTMachine version
    1227           0 :     stokesToCorrelation(*(modelImageVec[0]), *(compImageVec[0]));
    1228             : 
    1229             :     // Call initializeToVis
    1230           0 :     initializeToVis(*(compImageVec[0]), vb); // Pure virtual
    1231             :     
    1232             :     // Multiply the flat-sky model by the PB.
    1233             :     // No local implementation -- call FTMachine version
    1234           0 :     if(doPBCorrection)
    1235             :       // Multiply by avgPB ///////  PBWeight
    1236             :       //normalizeImage( *(modelImageVec[0]) , weightsVec[0], *(weightImageVec[0]) , false, (Float)pbLimit_p, (Int)3);
    1237             :       
    1238             :       // Multiply by sqrt(avgPB) ///// PBSQWeight
    1239           0 :       normalizeImage( *(modelImageVec[0]) , weightsVec[0], *(weightImageVec[0]) , false, (Float)pbLimit_p, (Int)5);
    1240           0 :   }
    1241             :   //
    1242             :   //------------------------------------------------------------------------------
    1243             :   //
    1244           0 :   void AWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    1245             :                                     const VisBuffer2& vb)
    1246             :   {
    1247           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "initializeToVis[R&D]"));
    1248           0 :     image=&iimage;
    1249             :     
    1250           0 :     ok();
    1251             :     
    1252           0 :     init();
    1253           0 :     makingPSF = false;
    1254           0 :     initMaps(vb);
    1255             :     
    1256           0 :     findConvFunction(*image, vb);
    1257           0 :     if (isDryRun) return;
    1258             :     //  
    1259             :     // Initialize the maps for polarization and channel. These maps
    1260             :     // translate visibility indices into image indices
    1261             :     //
    1262             : 
    1263           0 :     nx    = image->shape()(0);
    1264           0 :     ny    = image->shape()(1);
    1265           0 :     npol  = image->shape()(2);
    1266           0 :     nchan = image->shape()(3);
    1267             :     
    1268             :     //
    1269             :     // If we are memory-based then read the image in and create an
    1270             :     // ArrayLattice otherwise just use the PagedImage
    1271             :     //
    1272             : 
    1273           0 :     isTiled=false;
    1274             : 
    1275             :       {
    1276           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    1277           0 :         griddedData.resize(gridShape);
    1278           0 :         griddedData=Complex(0.0);
    1279             :         
    1280           0 :         IPosition stride(4, 1);
    1281           0 :         IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    1282           0 :                       (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    1283           0 :         IPosition trc(blc+image->shape()-stride);
    1284             :         
    1285           0 :         IPosition start(4, 0);
    1286           0 :         griddedData(blc, trc) = image->getSlice(start, image->shape());
    1287             :         
    1288           0 :         lattice=new ArrayLattice<Complex>(griddedData);
    1289           0 :       }
    1290             : 
    1291             :     //AlwaysAssert(lattice, AipsError);
    1292             :     
    1293           0 :     log_l << LogIO::DEBUGGING << "Starting FFT of image" << LogIO::POST;
    1294             :     
    1295           0 :     Vector<Float> sincConv(nx);
    1296           0 :     Float centerX=nx/2;
    1297           0 :     for (Int ix=0;ix<nx;ix++) 
    1298             :       {
    1299           0 :         Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    1300           0 :         if(ix==centerX) sincConv(ix)=1.0;
    1301           0 :         else            sincConv(ix)=sin(x)/x;
    1302           0 :         sincConv(ix) = 1.0;
    1303             :       }
    1304             :     
    1305           0 :     if(cfCache_p->avgPBReady()) //SB
    1306             :     {
    1307             :       //      normalizeAvgPB();
    1308             :       
    1309           0 :       IPosition cursorShape(4, nx, 1, 1, 1);
    1310           0 :       IPosition axisPath(4, 0, 1, 2, 3);
    1311           0 :       LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1312           0 :       LatticeIterator<Complex> lix(*lattice, lsx);
    1313             :           
    1314           0 :       verifyShapes(avgPB_p->shape(), image->shape());
    1315           0 :       Array<Float> avgBuf; avgPB_p->get(avgBuf);
    1316             :       // If the total-power sensitivity pattern peak is too low, warn
    1317             :       // the user.  This usually is indicative of a rat somewhere in
    1318             :       // the pipes upstream...
    1319           0 :       if ((sensitivityPatternQualifier_p==0) && (max(avgBuf) < 1e-04))
    1320             :         log_l << "Normalization by PB requested but either PB was not"
    1321             :               <<" found in the cache or is ill-formed. Peak = "
    1322           0 :               << max(avgBuf)// << " " << sensitivityPatternQualifier_p
    1323           0 :               << LogIO::WARN << LogIO::POST;
    1324             :           
    1325             : 
    1326           0 :       LatticeStepper lpb(avgPB_p->shape(),cursorShape,axisPath);
    1327           0 :       LatticeIterator<Float> lipb(*avgPB_p, lpb);
    1328             : 
    1329           0 :       Vector<Complex> griddedVis;
    1330             :       //
    1331             :       // Grid correct in anticipation of the convolution by the
    1332             :       // convFunc.  Each polarization plane is corrected by the
    1333             :       // appropraite primary beam.
    1334             :       //
    1335           0 :       for(lix.reset(),lipb.reset();!lix.atEnd();lix++,lipb++) 
    1336             :         {
    1337           0 :           Int iy=lix.position()(1);
    1338           0 :           griddedVis = lix.rwVectorCursor();
    1339             :           
    1340           0 :           Vector<Float> PBCorrection(lipb.rwVectorCursor().shape());
    1341           0 :           PBCorrection = lipb.rwVectorCursor();
    1342           0 :           for(int ix=0;ix<nx;ix++) 
    1343             :             {
    1344           0 :               if (doPBCorrection)
    1345             :                 {
    1346           0 :                   PBCorrection(ix) = pbFunc(PBCorrection(ix),pbLimit_p)*(sincConv(ix)*sincConv(iy));
    1347           0 :                   lix.rwVectorCursor()(ix) /= (PBCorrection(ix));
    1348             :                 }
    1349             :               else 
    1350           0 :                 lix.rwVectorCursor()(ix) /= (1.0/(sincConv(ix)*sincConv(iy)));
    1351             :             }
    1352           0 :         }
    1353           0 :     }
    1354             :     //
    1355             :     // Now do the FFT2D in place
    1356             :     //
    1357             : 
    1358           0 :     LatticeFFT::cfft2d(*lattice);
    1359           0 :     log_l << LogIO::DEBUGGING << "Finished FFT" << LogIO::POST;
    1360           0 :   }
    1361             :   //
    1362             :   //------------------------------------------------------------------------------
    1363             :   //
    1364           0 :   void AWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    1365             :                                      const VisBuffer2& vb,
    1366             :                                      Array<Complex>& griddedVis,
    1367             :                                      Vector<Double>& uvscale)
    1368             :   {
    1369           0 :     initializeToVis(iimage, vb);
    1370           0 :     griddedVis.assign(griddedData); //using the copy for storage
    1371           0 :     uvscale.assign(uvScale);
    1372             :     
    1373           0 :   }
    1374             :   //
    1375             :   //---------------------------------------------------------------
    1376             :   //
    1377           0 :   void AWProjectFT::finalizeToVis()
    1378             :   {
    1379           0 :     visResampler_p->runTimeDG_p=0.0;
    1380           0 :     logIO()<< LogIO::NORMAL2 << "Time degrid " << timedegrid_p << LogIO::POST;
    1381           0 :     timedegrid_p=0.0;
    1382             : 
    1383           0 :   if(!lattice.null()) lattice=0;
    1384           0 :   griddedData.resize();
    1385             :   
    1386           0 :     if(isTiled) 
    1387             :       {
    1388           0 :         AlwaysAssert(imageCache, AipsError);
    1389           0 :         AlwaysAssert(image, AipsError);
    1390           0 :         ostringstream o;
    1391           0 :         imageCache->flush();
    1392           0 :         imageCache->showCacheStatistics(o);
    1393             : 
    1394           0 :         LogIO log_l(LogOrigin("AWProjectFT2", "finalizeToVis[R&D]"));
    1395           0 :         log_l << o.str() << LogIO::POST;
    1396           0 :       }
    1397           0 :     if(pointingToImage) delete pointingToImage;
    1398           0 :     pointingToImage=0;
    1399           0 :   }
    1400             :   //
    1401             :   //---------------------------------------------------------------
    1402             :   //
    1403             :   // Initialize the FFT to the Sky. Here we have to setup and
    1404             :   // initialize the grid.
    1405             :   //
    1406           0 :   void AWProjectFT::initializeToSky(ImageInterface<Complex>& iimage,
    1407             :                                      Matrix<Float>& weight,
    1408             :                                      const VisBuffer2& vb)
    1409             :   {
    1410           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "initializeToSky[R&D]"));
    1411             :     
    1412             :     // image always points to the image
    1413           0 :     image=&iimage;
    1414             :     
    1415           0 :     init();
    1416           0 :     initMaps(vb);
    1417           0 :     log_l << "Computed maps using FTMachine::initMaps. " << "polMap = " << polMap << LogIO::POST;
    1418           0 :     visResampler_p->setMaps(chanMap, polMap);
    1419           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    1420             :     
    1421             :     // Initialize the maps for polarization and channel. These maps
    1422             :     // translate visibility indices into image indices
    1423           0 :     nx    = image->shape()(0);
    1424           0 :     ny    = image->shape()(1);
    1425           0 :     npol  = image->shape()(2);
    1426           0 :     nchan = image->shape()(3);
    1427             :     
    1428           0 :     sumWeight=0.0;
    1429           0 :     sumCFWeight = 0.0;
    1430           0 :     weight.resize(sumWeight.shape());
    1431           0 :     weight=0.0;
    1432             : 
    1433             :     //
    1434             :     // Construct the HPG.  This is now donw in AWVRHPG.  Not the right
    1435             :     // place, I think, but good enough for testing. (21Dec2020).
    1436             :     //
    1437             :     // const std::array<unsigned, 4> gridSize{(uInt)nx,(uInt)ny,(uInt)npol,(uInt)nchan};
    1438             :     // const std::array<float, 2> gridScale{(float)uvScale(0), (float)uvScale(1)};
    1439             :     // unsigned max_added_tasks=1; // This allocates 2 CUDA streams in AWVRHPG.
    1440             :     // visResampler_p->initGridder(max_added_tasks,gridSize,gridScale);
    1441             : 
    1442             : 
    1443             :     //
    1444             :     // Initialize for in memory or to disk gridding. lattice will
    1445             :     // point to the appropriate Lattice, either the ArrayLattice for
    1446             :     // in memory gridding or to the image for to disk gridding.
    1447             :     //
    1448           0 :     if(isTiled) 
    1449             :       {
    1450           0 :         imageCache->flush();
    1451           0 :         image->set(Complex(0.0));
    1452           0 :         lattice=CountedPtr<Lattice<Complex> > (image, false);
    1453             :       }
    1454             :     else 
    1455             :       {
    1456           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    1457           0 :         if(!useDoubleGrid_p){
    1458           0 :         griddedData.resize(gridShape);
    1459           0 :         griddedData=Complex(0.0); 
    1460             :         }
    1461             :         else      {
    1462           0 :           griddedData2.resize(gridShape);
    1463           0 :           griddedData2=DComplex(0.0);
    1464             :         }
    1465           0 :       }
    1466             : 
    1467             :     //cerr << "initializeToSky for grid" << endl;
    1468           0 :     if(useDoubleGrid_p) 
    1469           0 :       visResampler_p->initializeToSky(griddedData2, sumWeight);
    1470             :     else
    1471           0 :       visResampler_p->initializeToSky(griddedData, sumWeight);
    1472           0 :   }
    1473             :   //
    1474             :   //---------------------------------------------------------------
    1475             :   //
    1476           0 :   void AWProjectFT::finalizeToSky()
    1477             :   {
    1478             : 
    1479           0 :     logIO() <<   LogIO::NORMAL2 << "time to massage data " << timemass_p << LogIO::POST;
    1480           0 :     logIO() <<  LogIO::NORMAL2 << "time gridding " << timegrid_p << LogIO::POST;
    1481           0 :    timemass_p=0.0;
    1482           0 :    timegrid_p=0.0;
    1483             :     
    1484             :     //
    1485             :     // Now we flush the cache and report statistics For memory based,
    1486             :     // we don't write anything out yet.
    1487             :     //
    1488             :     //    LogIO log_l(LogOrigin("AWProjectFT2", "finalizeToSky[R&D]"));
    1489             : 
    1490           0 :     if(isTiled) 
    1491             :       {
    1492           0 :         AlwaysAssert(image, AipsError);
    1493           0 :         AlwaysAssert(imageCache, AipsError);
    1494           0 :         imageCache->flush();
    1495           0 :         ostringstream o;
    1496           0 :         imageCache->showCacheStatistics(o);
    1497           0 :       }
    1498           0 :     if(pointingToImage) delete pointingToImage;
    1499           0 :     pointingToImage=0;
    1500             : 
    1501           0 :     paChangeDetector.reset();
    1502           0 :     cfCache_p->flush();
    1503           0 :     if(useDoubleGrid_p) 
    1504           0 :       visResampler_p->finalizeToSky(griddedData2, sumWeight);
    1505             :     else
    1506           0 :       visResampler_p->finalizeToSky(griddedData, sumWeight);
    1507           0 :   }
    1508             :   //
    1509             :   //---------------------------------------------------------------
    1510             :   //
    1511           0 :   Array<Complex>* AWProjectFT::getDataPointer(const IPosition& centerLoc2D,
    1512             :                                                Bool readonly) 
    1513             :   {
    1514             :     Array<Complex>* result;
    1515             :     // Is tiled: get tiles and set up offsets
    1516           0 :     centerLoc(0)=centerLoc2D(0);
    1517           0 :     centerLoc(1)=centerLoc2D(1);
    1518           0 :     result=&imageCache->tile(offsetLoc, centerLoc, readonly);
    1519           0 :     gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    1520           0 :     return result;
    1521             :   }
    1522             :   
    1523             :   // The following file has the runFORTRAN* stuff. Moving it to a
    1524             :   // separate file to reduce clutter and ultimately delete it.
    1525             : #include "AWProjectFT.FORTRANSTUFF"
    1526             :   //
    1527             :   //---------------------------------------------------------------
    1528             :   //
    1529           0 :     void AWProjectFT::put(const VisBuffer2& vb, Int /*row*/, Bool dopsf,
    1530             :                         FTMachine::Type type)
    1531             :   {
    1532             :     // Take care of translation of Bools to Integer
    1533           0 :     makingPSF=dopsf;
    1534           0 :     if(dopsf)
    1535           0 :       ftmType_p=refim::FTMachine::PSF;
    1536           0 :     Timer tim;
    1537           0 :     tim.mark();
    1538             :     
    1539             :     try
    1540             :       {
    1541           0 :         findConvFunction(*image, vb);
    1542             :       }
    1543           0 :     catch(AipsError& x)
    1544             :       {
    1545           0 :         LogIO log_l(LogOrigin("AWProjectFT2", "put[R&D]"));
    1546           0 :         log_l << x.getMesg() << LogIO::WARN;
    1547           0 :         return;
    1548           0 :       }
    1549           0 :     if (isDryRun) return;
    1550             : 
    1551           0 :     Nant_p     = vb.subtableColumns().antenna().nrow();
    1552             : 
    1553           0 :     Matrix<Float> imagingweight;
    1554           0 :     getImagingWeight(imagingweight, vb);
    1555             : 
    1556           0 :     Cube<Complex> data;
    1557             :     //Fortran gridder need the flag as ints 
    1558           0 :     Cube<Int> flags;
    1559           0 :     Matrix<Float> elWeight;
    1560             : 
    1561           0 :     interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
    1562             : 
    1563             :     //    
    1564             :     // Get the uvws in a form that Fortran can use and do that
    1565             :     // necessary phase rotation. On a Pentium Pro 200 MHz when null,
    1566             :     // this step takes about 50us per uvw point. This is just barely
    1567             :     // noticeable for Stokes I continuum and irrelevant for other
    1568             :     // cases.
    1569             :     //
    1570           0 :     Matrix<Double> uvw(negateUV(vb));
    1571             :     
    1572           0 :     Vector<Double> dphase(vb.nRows());
    1573           0 :     dphase=0.0;
    1574           0 :     doUVWRotation_p=true;
    1575           0 :     girarUVW(uvw, dphase, vb);
    1576           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    1577             :     
    1578             :     //Here we redo the match or use previous match
    1579             :     
    1580             :     //Channel matching for the actual spectral window of buffer
    1581             : 
    1582           0 :     matchChannel(vb);
    1583           0 :     VBStore vbs;
    1584           0 :     Vector<Int> gridShape = griddedData2.shape().asVector();
    1585           0 :     setupVBStore(vbs,vb, elWeight,data,uvw,flags, dphase,dopsf,gridShape);
    1586           0 :     timemass_p +=tim.real();
    1587           0 :     tim.mark();
    1588             :     
    1589           0 :     if (useDoubleGrid_p)
    1590             :       {
    1591           0 :         resampleDataToGrid(griddedData2, vbs, vb, dopsf);//, *imagingweight, *data, uvw,flags,dphase,dopsf);
    1592             :       }
    1593             :     else
    1594             :       {
    1595           0 :         resampleDataToGrid(griddedData, vbs, vb, dopsf);//, *imagingweight, *data, uvw,flags,dphase,dopsf);
    1596             :       }
    1597           0 :     timegrid_p+=tim.real();
    1598           0 :   }
    1599             : 
    1600           0 :   std::shared_ptr<std::complex<double>> AWProjectFT::getGridPtr(size_t& size) const
    1601             :   {
    1602           0 :     return visResampler_p->getGridPtr(size);
    1603             :   }
    1604             : 
    1605           0 :   std::shared_ptr<double> AWProjectFT::getSumWeightsPtr(size_t& size) const
    1606             :   {
    1607           0 :     return visResampler_p->getSumWeightsPtr(size);
    1608             :   }
    1609             : 
    1610             :   //
    1611             :   //-------------------------------------------------------------------------
    1612             :   // Gridding
    1613           0 :   void AWProjectFT::resampleDataToGrid(Array<Complex>& griddedData_l, VBStore& vbs, 
    1614             :                                        const VisBuffer2& /*vb*/, Bool& dopsf)
    1615             :   {
    1616           0 :     visResampler_p->DataToGrid(griddedData_l, vbs, sumWeight, dopsf); 
    1617           0 :   }
    1618             :   //
    1619             :   //-------------------------------------------------------------------------
    1620             :   // Gridding
    1621           0 :   void AWProjectFT::resampleDataToGrid(Array<DComplex>& griddedData_l, VBStore& vbs, 
    1622             :                                        const VisBuffer2& /*vb*/, Bool& dopsf)
    1623             :   {
    1624           0 :     visResampler_p->DataToGrid(griddedData_l, vbs, sumWeight, dopsf); 
    1625           0 :   }
    1626             :   //
    1627             :   //---------------------------------------------------------------
    1628             :   //
    1629           0 :   void AWProjectFT::get(VisBuffer2& vb, Int /*row*/)
    1630             :   {
    1631           0 :     findConvFunction(*image, vb);
    1632           0 :     Timer tim;
    1633           0 :     tim.mark();
    1634           0 :     Nant_p     = vb.subtableColumns().antenna().nrow();
    1635             :     // Get the uvws in a form that Fortran can use
    1636           0 :     Matrix<Double> uvw(negateUV(vb));
    1637             : 
    1638           0 :     Vector<Double> dphase(vb.nRows());
    1639           0 :     dphase=0.0;
    1640           0 :     doUVWRotation_p=true;
    1641             :     //rotateUVW(uvw, dphase, vb);
    1642             : 
    1643           0 :     girarUVW(uvw, dphase, vb);
    1644           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    1645             :     
    1646           0 :     matchChannel(vb);
    1647             :     //No point in reading data if its not matching in frequency
    1648           0 :     if(max(chanMap)==-1) return;
    1649             :     
    1650           0 :     Cube<Complex> data;
    1651           0 :     Cube<Int> flags;
    1652           0 :     getInterpolateArrays(vb, data, flags);
    1653             : 
    1654           0 :     VBStore vbs;
    1655           0 :     Bool tmpDoPSF=false;
    1656             : 
    1657           0 :     setupVBStore(vbs,vb, vb.imagingWeight(),data,uvw,flags, dphase,tmpDoPSF,griddedData.shape().asVector());
    1658           0 :     resampleGridToData(vbs, griddedData, vb);//, uvw, flags, dphase);
    1659           0 :     interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
    1660           0 :     timedegrid_p+=tim.real();
    1661           0 :   }
    1662             :   //
    1663             :   //-------------------------------------------------------------------------
    1664             :   // De-gridding
    1665           0 :   void AWProjectFT::resampleGridToData(VBStore& vbs, Array<Complex>& griddedData_l,
    1666             :                                        const VisBuffer2& /*vb*/)
    1667             :   {
    1668           0 :     visResampler_p->GridToData(vbs, griddedData_l);
    1669           0 :   }
    1670             :   //
    1671             :   //---------------------------------------------------------------
    1672             :   //
    1673             :   // Finalize the FFT to the Sky. Here we actually do the FFT and
    1674             :   // return the resulting image
    1675           0 :   ImageInterface<Complex>& AWProjectFT::getImage(Matrix<Float>& weights,
    1676             :                                                   Bool fftNormalization) 
    1677             :   {
    1678           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "getImage[R&D]"));
    1679             : 
    1680           0 :     AlwaysAssert(image, AipsError);
    1681             : 
    1682           0 :     weights.resize(sumWeight.shape());
    1683           0 :     convertArray(weights, sumWeight);
    1684             :     //  
    1685             :     // If the weights are all zero then we cannot normalize otherwise
    1686             :     // we don't care.
    1687             :     //
    1688           0 :     if(max(weights)==0.0) 
    1689             :       log_l // UUU //<< LogIO::SEVERE
    1690           0 :             << "No useful data in " << name() << ".  Weights all zero"
    1691           0 :             << LogIO::POST;
    1692             :     else
    1693             :       {
    1694           0 :         log_l << "Sum of weights: " << weights << " " << max(griddedData2) << " " << min(griddedData2) << LogIO::POST;
    1695             :         //cerr << "Sum of weights: " << setprecision(20) << weights << endl;
    1696             :       }
    1697             :     // UUU else
    1698             :       {
    1699             :         log_l << LogIO::DEBUGGING
    1700           0 :                 << "Starting FFT and scaling of image" << LogIO::POST;
    1701             :         //    
    1702             :         // x and y transforms (lattice has the gridded vis.  Make the
    1703             :         // dirty images)
    1704             :         //
    1705           0 :         if (useDoubleGrid_p)
    1706             :           {
    1707           0 :             ArrayLattice<DComplex> darrayLattice(griddedData2);
    1708           0 :             LatticeFFT::cfft2d(darrayLattice,false);
    1709           0 :             griddedData.resize(griddedData2.shape());
    1710           0 :             convertArray(griddedData, griddedData2);
    1711           0 :             SynthesisUtilMethods::getResource("mem peak in getImage");
    1712             :         
    1713             :             //Don't need the double-prec grid anymore...
    1714           0 :             griddedData2.resize();
    1715           0 :             lattice=new ArrayLattice<Complex>(griddedData);
    1716           0 :           }
    1717             :         else
    1718             :           {
    1719           0 :             lattice=new ArrayLattice<Complex>(griddedData);
    1720           0 :             LatticeFFT::cfft2d(*lattice,false);
    1721             :           }
    1722           0 :         const IPosition latticeShape = lattice->shape();
    1723             : 
    1724           0 :         int samp=getAWConvFunc()->getOversampling();
    1725             :         //cerr << "SAMP " << samp << endl;
    1726             :         //Do sampling size correction    
    1727           0 :         Vector<Float> sincConvX(nx);
    1728           0 :         for (Int ix=0;ix<nx;ix++) {
    1729           0 :           Float x=C::pi*Float(ix-nx/2)/(Float(nx)*Float(convSampling));
    1730           0 :           if(ix==nx/2) {
    1731           0 :             sincConvX(ix)=1.0;
    1732             :           }
    1733             :           else {
    1734           0 :             sincConvX(ix)=sin(x)/x;
    1735             :           }
    1736             :         }
    1737           0 :         Vector<Float> sincConvY(ny);
    1738           0 :         for (Int ix=0;ix<ny;ix++) {
    1739           0 :           Float x=C::pi*Float(ix-ny/2)/(Float(ny)*Float(convSampling));
    1740           0 :           if(ix==ny/2) {
    1741           0 :             sincConvY(ix)=1.0;
    1742             :           }
    1743             :           else {
    1744           0 :             sincConvY(ix)=sin(x)/x;
    1745             :           }
    1746             :         }
    1747             :     
    1748             : 
    1749             :         //cerr << convSampling << " max min of sincs " << max(sincConvX) << "    " << min(sincConvX) << max(sincConvY) << "     " << min(sincConvY) << endl;
    1750             :         //
    1751             :         // Now normalize the dirty image.
    1752             :         //
    1753             :         // Since *lattice is not copied to *image till the end of this
    1754             :         // method, normalizeImage also needs to work with Lattices
    1755             :         // (rather than ImageInterface).
    1756             :         //
    1757             :         // nx ny normalization from GridFT...
    1758             :         {
    1759           0 :           Int inx = lattice->shape()(0);
    1760           0 :           Int iny = lattice->shape()(1);
    1761           0 :           Vector<Complex> correction(inx);
    1762           0 :           correction=Complex(1.0, 0.0);
    1763             :           // Do the Grid-correction
    1764           0 :           IPosition cursorShape(4, inx, 1, 1, 1);
    1765           0 :           IPosition axisPath(4, 0, 1, 2, 3);
    1766           0 :           LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1767           0 :           LatticeIterator<Complex> lix(*lattice, lsx);
    1768           0 :           for(lix.reset();!lix.atEnd();lix++) 
    1769             :             {
    1770           0 :               Int pol=lix.position()(2);
    1771           0 :               Int chan=lix.position()(3);
    1772             :               {
    1773             : 
    1774           0 :                 Int iy=lix.position()(1);
    1775           0 :                 for (Int ix=0;ix<nx;ix++) {
    1776           0 :                   correction(ix)=1.0/(sincConvX(ix)*sincConvY(iy));
    1777             :                  }
    1778             :                 //cerr << iy << " min max corr " << min(abs(correction)) << "    " << max(abs(correction)) << endl;
    1779           0 :                 lix.rwVectorCursor()*=correction;
    1780           0 :                 if(fftNormalization) 
    1781             :                   {
    1782           0 :                     if(weights(pol,chan)!=0.0)
    1783             :                       {
    1784           0 :                         Complex rnorm(Float(inx)*Float(iny)/( weights(pol,chan) ));
    1785           0 :                         lix.rwCursor()*=rnorm;
    1786             :                       }
    1787             :                     else
    1788           0 :                       lix.woCursor()=0.0;
    1789             :                   }
    1790             :                 else 
    1791             :                   {
    1792           0 :                     Complex rnorm(Float(inx)*Float(iny));
    1793           0 :                     lix.rwCursor()*=rnorm;
    1794             :                   }
    1795             :               }
    1796             :             }
    1797           0 :         }
    1798           0 :         if(!isTiled) 
    1799             :           {
    1800             :             //
    1801             :             // Check the section from the image BEFORE converting to a lattice 
    1802             :             //
    1803           0 :             LatticeLocker lock1 (*(image), FileLocker::Write);
    1804           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    1805           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    1806           0 :             IPosition stride(4, 1);
    1807           0 :             IPosition trc(blc+image->shape()-stride);
    1808             :             //
    1809             :             // Do the copy
    1810             :             //
    1811           0 :             image->put(griddedData(blc, trc));
    1812             :             
    1813             : 
    1814           0 :             if(!lattice.null()) lattice=0;
    1815           0 :             griddedData.resize(IPosition(1,0));
    1816           0 :           }
    1817           0 :       }
    1818             : 
    1819           0 :     return *image;
    1820           0 :   }
    1821             :   //
    1822             :   //---------------------------------------------------------------
    1823             :   //
    1824             :   // Get weight image
    1825           0 :   void AWProjectFT::getWeightImage(ImageInterface<Float>& weightImage,
    1826             :                                    Matrix<Float>& weights) 
    1827             :   {
    1828           0 :     weights.resize(sumWeight.shape());
    1829           0 :     convertArray(weights,sumWeight);
    1830             :     
    1831           0 :     const IPosition latticeShape = weightImage.shape();
    1832           0 :     const IPosition avgpbShape = avgPB_p->shape();
    1833             :     //cout << "AWP::getWeightImage : weightimage shape : " << latticeShape << "  and avgpb shape : " << avgpbShape << " nelems " << avgpbShape.nelements()<< "  " << sumWeight << endl;
    1834           0 :      if(avgpbShape.nelements()==0 || ( avgpbShape != latticeShape) )
    1835           0 :       avgPB_p->resize(weightImage.shape());
    1836             :     
    1837           0 :     Int nx=latticeShape(0);
    1838           0 :     Int ny=latticeShape(1);
    1839             : 
    1840           0 :     int samp=getAWConvFunc()->getOversampling();
    1841             :     //Do sampling size correction    
    1842           0 :     Vector<Float> sincConvX(nx);
    1843           0 :     for (Int ix=0;ix<nx;ix++) {
    1844           0 :       Float x=C::pi*Float(ix-nx/2)/(Float(nx)*Float(convSampling));
    1845           0 :       if(ix==nx/2) {
    1846           0 :         sincConvX(ix)=1.0;
    1847             :       }
    1848             :       else {
    1849           0 :         sincConvX(ix)=sin(x)/x;
    1850             :       }
    1851             :     }
    1852           0 :     Vector<Float> sincConvY(ny);
    1853           0 :     for (Int ix=0;ix<ny;ix++) {
    1854           0 :       Float x=C::pi*Float(ix-ny/2)/(Float(ny)*Float(convSampling));
    1855           0 :       if(ix==ny/2) {
    1856           0 :         sincConvY(ix)=1.0;
    1857             :       }
    1858             :       else {
    1859           0 :         sincConvY(ix)=sin(x)/x;
    1860             :       }
    1861             :     }
    1862             :     
    1863             : 
    1864             :        
    1865             : 
    1866             :     {
    1867           0 :       IPosition cursorShape(4, nx, ny, latticeShape(2), latticeShape(3));
    1868           0 :       IPosition axisPath(4, 0, 1, 2, 3);
    1869           0 :       LatticeStepper lsx(latticeShape, cursorShape, axisPath);
    1870           0 :       LatticeIterator<Float> lix(weightImage, lsx);
    1871           0 :       LatticeIterator<Float> liy(*avgPB_p,lsx);
    1872           0 :       for(lix.reset();!lix.atEnd();lix++) 
    1873             :         {
    1874           0 :           lix.rwCursor()=liy.cursor();
    1875             :         }
    1876           0 :     }
    1877             :     {//sampling size correction
    1878           0 :       Vector<Float> correction(nx);
    1879           0 :       correction=1.0;
    1880             :       // Do the Grid-correction
    1881           0 :       IPosition cursorShape(4, nx, 1, 1, 1);
    1882           0 :       IPosition axisPath(4, 0, 1, 2, 3);
    1883           0 :       LatticeStepper lsx(weightImage.shape(), cursorShape, axisPath);
    1884           0 :       LatticeIterator<Float> lix(weightImage, lsx);
    1885           0 :       for(lix.reset();!lix.atEnd();lix++) 
    1886             :         {
    1887             :                
    1888           0 :           Int iy=lix.position()(1);
    1889           0 :           for (Int ix=0;ix<nx;ix++) {
    1890           0 :             correction(ix)=1.0/(sincConvX(ix)*sincConvY(iy));
    1891             :           }
    1892           0 :           lix.rwVectorCursor()*=correction;
    1893             :         }
    1894           0 :         }
    1895           0 :   }
    1896             :   //---------------------------------------------------------------
    1897           0 :     void AWProjectFT::setWeightImage(ImageInterface<Float>& weightImage){
    1898             :       //cerr <<"@@@loading weightimage" << endl;
    1899           0 :       IPosition latticeShape = weightImage.shape();
    1900           0 :       CoordinateSystem cs=weightImage.coordinates();
    1901           0 :       avgPB_p=new TempImage<Float>(latticeShape, cs);
    1902           0 :       avgPB_p->copyData(weightImage);
    1903           0 :       avgPBReady_p=True;
    1904             : 
    1905           0 :     }
    1906             :     
    1907             :   //---------------------------------------------------------------
    1908             :   //
    1909           0 :   Bool AWProjectFT::toRecord(RecordInterface& outRec, Bool withImage) 
    1910             :   {
    1911             :     // Save the current AWProjectFT object to an output state record
    1912           0 :     Bool retval = true;
    1913           0 :     String error;
    1914             :     //save the base class variables
    1915           0 :     if(!FTMachine::toRecord(error, outRec, withImage, ""))
    1916           0 :       return false;
    1917           0 :     Double cacheVal=(Double) cachesize;
    1918           0 :     outRec.define("cache", cacheVal);
    1919           0 :     outRec.define("tile", tilesize);
    1920             :     
    1921           0 :     Vector<Double> phaseValue(2);
    1922           0 :     String phaseUnit;
    1923           0 :     phaseValue=mTangent_p.getAngle().getValue();
    1924           0 :     phaseUnit= mTangent_p.getAngle().getUnit();
    1925           0 :     outRec.define("phasevalue", phaseValue);
    1926           0 :     outRec.define("phaseunit", phaseUnit);
    1927             :     
    1928           0 :     Vector<Double> dirValue(3);
    1929           0 :     String dirUnit;
    1930           0 :     dirValue=mLocation_p.get("m").getValue();
    1931           0 :     dirUnit=mLocation_p.get("m").getUnit();
    1932           0 :     outRec.define("dirvalue", dirValue);
    1933           0 :     outRec.define("dirunit", dirUnit);
    1934             :     
    1935           0 :     outRec.define("padding", padding_p);
    1936           0 :     outRec.define("maxdataval", maxAbsData);
    1937             :     
    1938           0 :     Vector<Int> center_loc(4), offset_loc(4);
    1939           0 :     for (Int k=0; k<4 ; k++)
    1940             :       {
    1941           0 :         center_loc(k)=centerLoc(k);
    1942           0 :         offset_loc(k)=offsetLoc(k);
    1943             :       }
    1944           0 :     outRec.define("centerloc", center_loc);
    1945           0 :     outRec.define("offsetloc", offset_loc);
    1946           0 :     outRec.define("sumofweights", sumWeight);
    1947           0 :     outRec.define("sumofcfweights", sumCFWeight);
    1948           0 :     if(withImage && image)
    1949             :       { 
    1950           0 :         ImageInterface<Complex>& tempimage(*image);
    1951           0 :         Record imageContainer;
    1952           0 :         String error;
    1953           0 :         retval = (retval || tempimage.toRecord(error, imageContainer));
    1954           0 :         outRec.defineRecord("image", imageContainer);
    1955           0 :       }
    1956           0 :     return retval;
    1957           0 :   }
    1958             :   //
    1959             :   //---------------------------------------------------------------
    1960             :   //
    1961           0 :   Bool AWProjectFT::fromRecord(const RecordInterface& inRec)
    1962             :   {
    1963           0 :     Bool retval = true;
    1964           0 :     String error;
    1965           0 :     if(!FTMachine::fromRecord(error, inRec))
    1966           0 :       return false;
    1967           0 :     imageCache=0; lattice=0; 
    1968             :     Double cacheVal;
    1969           0 :     inRec.get("cache", cacheVal);
    1970           0 :     cachesize=(Long) cacheVal;
    1971           0 :     inRec.get("tile", tilesize);
    1972             :     
    1973           0 :     Vector<Double> phaseValue(2);
    1974           0 :     inRec.get("phasevalue",phaseValue);
    1975           0 :     String phaseUnit;
    1976           0 :     inRec.get("phaseunit",phaseUnit);
    1977           0 :     Quantity val1(phaseValue(0), phaseUnit);
    1978           0 :     Quantity val2(phaseValue(1), phaseUnit); 
    1979           0 :     MDirection phasecenter(val1, val2);
    1980             :     
    1981           0 :     mTangent_p=phasecenter;
    1982             :     // This should be passed down too but the tangent plane is 
    1983             :     // expected to be specified in all meaningful cases.
    1984           0 :     tangentSpecified_p=true;  
    1985           0 :     Vector<Double> dirValue(3);
    1986           0 :     String dirUnit;
    1987           0 :     inRec.get("dirvalue", dirValue);
    1988           0 :     inRec.get("dirunit", dirUnit);
    1989           0 :     MVPosition dummyMVPos(dirValue(0), dirValue(1), dirValue(2));
    1990           0 :     MPosition mLocation(dummyMVPos, MPosition::ITRF);
    1991           0 :     mLocation_p=mLocation;
    1992             :     
    1993           0 :     inRec.get("padding", padding_p);
    1994           0 :     inRec.get("maxdataval", maxAbsData);
    1995             :     
    1996           0 :     Vector<Int> center_loc(4), offset_loc(4);
    1997           0 :     inRec.get("centerloc", center_loc);
    1998           0 :     inRec.get("offsetloc", offset_loc);
    1999           0 :     uInt ndim4 = 4;
    2000           0 :     centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2), 
    2001           0 :                         center_loc(3));
    2002           0 :     offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2), 
    2003           0 :                         offset_loc(3));
    2004           0 :     inRec.get("sumofweights", sumWeight);
    2005           0 :     inRec.get("sumofcfweights", sumCFWeight);
    2006           0 :     if(inRec.nfields() > 12 )
    2007             :       {
    2008           0 :         Record imageAsRec=inRec.asRecord("image");
    2009           0 :         if(!image) image= new TempImage<Complex>(); 
    2010             :         
    2011           0 :         String error;
    2012           0 :         retval = (retval || image->fromRecord(error, imageAsRec));    
    2013             :         
    2014             :         // Might be changing the shape of sumWeight
    2015           0 :         init(); 
    2016             :         
    2017           0 :         if(isTiled) 
    2018           0 :           lattice=CountedPtr<Lattice<Complex> > (image, false);
    2019             :         else 
    2020             :           {
    2021             :             //
    2022             :             // Make the grid the correct shape and turn it into an
    2023             :             // array lattice Check the section from the image BEFORE
    2024             :             // converting to a lattice
    2025             :             //
    2026           0 :             IPosition gridShape(4, nx, ny, npol, nchan);
    2027           0 :             griddedData.resize(gridShape);
    2028           0 :             griddedData=Complex(0.0);
    2029           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    2030           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    2031           0 :             IPosition start(4, 0);
    2032           0 :             IPosition stride(4, 1);
    2033           0 :             IPosition trc(blc+image->shape()-stride);
    2034           0 :             griddedData(blc, trc) = image->getSlice(start, image->shape());
    2035             :             
    2036           0 :             lattice=new ArrayLattice<Complex>(griddedData);
    2037           0 :           }
    2038             :         
    2039           0 :         AlwaysAssert(image, AipsError);
    2040           0 :       };
    2041           0 :     return retval;
    2042           0 :   }
    2043             :   //
    2044             :   //---------------------------------------------------------------
    2045             :   //
    2046           0 :   void AWProjectFT::ok() 
    2047             :   {
    2048           0 :     AlwaysAssert(image, AipsError);
    2049           0 :   }
    2050             :   //
    2051             :   //-------------------------------------------------------------------------
    2052             :   //  
    2053           0 :   void AWProjectFT::setPAIncrement(const Quantity& computePAIncrement,
    2054             :                                    const Quantity& rotateOTFPAIncrement)
    2055             :   {
    2056           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "setPAIncrement[R&D]"));
    2057             : 
    2058           0 :     rotateOTFPAIncr_p = rotateOTFPAIncrement.getValue("rad");
    2059           0 :     computePAIncr_p = computePAIncrement.getValue("rad");
    2060           0 :     convFuncCtor_p->setRotateCF(computePAIncr_p, rotateOTFPAIncr_p);
    2061             : 
    2062           0 :     paChangeDetector.setTolerance(computePAIncrement);
    2063           0 :     visResampler_p->setPATolerance(computePAIncrement.getValue("rad"));
    2064             :     log_l << LogIO::NORMAL <<"Setting PA increment to " 
    2065           0 :           << computePAIncrement.getValue("deg") << " deg" << endl;
    2066           0 :     cfCache_p->setPAChangeDetector(paChangeDetector);
    2067           0 :   }
    2068             :   //
    2069             :   //-------------------------------------------------------------------------
    2070             :   //  
    2071           0 :   Bool AWProjectFT::verifyShapes(IPosition pbShape, IPosition skyShape)
    2072             :   {
    2073           0 :     LogIO log_l(LogOrigin("AWProjectFT2", "verifyShapes[R&D]"));
    2074             : 
    2075           0 :     if ((pbShape(0) != skyShape(0)) && // X-axis
    2076           0 :         (pbShape(1) != skyShape(1)) && // Y-axis
    2077           0 :         (pbShape(2) != skyShape(2)))   // Poln-axis
    2078             :       {
    2079             :         log_l << "Sky and/or polarization shape of the avgPB and the sky model do not match."
    2080           0 :               << LogIO::EXCEPTION;
    2081           0 :         return false;
    2082             :       }
    2083           0 :     return true;
    2084             :     
    2085           0 :   }
    2086             :   //
    2087             :   //-------------------------------------------------------------------------
    2088             :   //  
    2089           0 :   void AWProjectFT::setupVBStore(VBStore& vbs,
    2090             :                                  const VisBuffer2& vb, 
    2091             :                                  const Matrix<Float>& imagingweight,
    2092             :                                  const Cube<Complex>& visData,
    2093             :                                  const Matrix<Double>& uvw,
    2094             :                                  const Cube<Int>& flagCube,
    2095             :                                  const Vector<Double>& dphase,
    2096             :                                  const Bool& dopsf,
    2097             :                                  const Vector<Int>& /*gridShape*/)
    2098             :   {
    2099           0 :     vbs.vb_p = &vb;
    2100           0 :     vbs.wbAWP_p=wbAWP_p;
    2101           0 :     vbs.ftmType_p=ftmType_p;
    2102           0 :     vbs.nWPlanes_p = nWPlanes_p;
    2103           0 :     makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2104           0 :     makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2105             : 
    2106           0 :     visResampler_p->setParams(uvScale,uvOffset,dphase);
    2107           0 :     visResampler_p->setMaps(chanMap, polMap);
    2108           0 :     visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2109           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2110             :     //
    2111             :     // Set up VBStore object to point to the relavent info. of the VB.
    2112             :     //
    2113           0 :     vbs.imRefFreq_p = imRefFreq_p;
    2114           0 :     vbs.nRow_p = vb.nRows();
    2115           0 :     vbs.beginRow_p = 0;
    2116           0 :     vbs.endRow_p = vbs.nRow_p;
    2117           0 :     vbs.spwID_p = vb.spectralWindows()(0);
    2118           0 :     vbs.nDataPol_p  = flagCube.shape()[0];
    2119           0 :     vbs.nDataChan_p = flagCube.shape()[1];
    2120             : 
    2121           0 :     vbs.antenna1_p.reference(vb.antenna1());
    2122           0 :     vbs.antenna2_p.reference(vb.antenna2());
    2123           0 :     vbs.paQuant_p = Quantity(getPA(vb),"rad");
    2124             : 
    2125           0 :     vbs.corrType_p.reference(vb.correlationTypes());
    2126             : 
    2127           0 :     vbs.uvw_p=uvw;
    2128           0 :     vbs.imagingWeight_p.reference(imagingweight);
    2129           0 :     vbs.visCube_p.reference(visData);
    2130             : 
    2131           0 :     vbs.freq_p.reference(vb.getFrequencies(0));
    2132             : 
    2133           0 :     vbs.rowFlag_p.reference(vb.flagRow());
    2134           0 :     if(!usezero_p) 
    2135           0 :       for (Int rownr=0; rownr<vbs.nRow_p; rownr++) 
    2136           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) vbs.rowFlag_p(rownr)=true;
    2137             : 
    2138           0 :     vbs.flagCube_p.resize(flagCube.shape());  vbs.flagCube_p = false; vbs.flagCube_p(flagCube!=0) = true;
    2139             :       
    2140           0 :     vbs.conjBeams_p=conjBeams_p;
    2141             : 
    2142             :     //timer_p.mark();
    2143             : 
    2144           0 :     po_p->fetchPointingOffset(*image, vb, doPointing);
    2145             :     
    2146           0 :     if (makingPSF || (vbs.ftmType_p==casa::refim::FTMachine::WEIGHT)){
    2147           0 :       cfwts2_p->invokeGC(vbs.spwID_p);
    2148           0 :       vb2CFBMap_p->setDoPointing(doPointing);
    2149           0 :       vb2CFBMap_p->makeVBRow2CFBMap(*cfwts2_p,
    2150             :                                       vb,
    2151           0 :                                       paChangeDetector.getParAngleTolerance(),
    2152           0 :                                       chanMap,polMap,po_p);
    2153             :     }
    2154             :     else
    2155             :       {
    2156             :        // If the Wt. CFs are still in the memory, clear them.  They
    2157             :         // won't be required again (though with the silly check below,
    2158             :         // if the in-memory Wt. CFs are less than 1KB, they will be
    2159             :         // left in memory).
    2160           0 :         if (cfwts2_p->memUsage() > 1000)
    2161             :           {
    2162           0 :             cfwts2_p->clear();
    2163             :           }
    2164             : 
    2165           0 :         cfs2_p->invokeGC(vbs.spwID_p);
    2166           0 :         vb2CFBMap_p->setDoPointing(doPointing);
    2167           0 :         vb2CFBMap_p->makeVBRow2CFBMap(*cfs2_p, vb,
    2168           0 :                                        paChangeDetector.getParAngleTolerance(),
    2169           0 :                                        chanMap,polMap,po_p);
    2170             :       }
    2171             : 
    2172             :     // 
    2173             :     // Trigger the computation of phase gradiant corresponding to the
    2174             :     // field offset (from the VB) w.r.t. the image phase center.
    2175             :     //
    2176             :     //
    2177             :     // For AzElApertures, this rotates the CFs.
    2178             :     //
    2179           0 :     convFuncCtor_p->prepareConvFunction(vb,*vb2CFBMap_p);
    2180             :     
    2181           0 :     vbs.accumCFs_p=((vbs.uvw_p.nelements() == 0) && dopsf);
    2182           0 :     visResampler_p->setVB2CFMap(vb2CFBMap_p);
    2183             :     
    2184             :     // The following code is required only for GPU or multi-threaded
    2185             :     //gridder.  Currently does not work without the rest of the
    2186             :     //GPU/multi-threaded infrastructure (though, I (SB) thought this
    2187             :     //was designed to be benign for normal gridding).
    2188             :     //
    2189           0 :     visResampler_p->initializeDataBuffers(vbs);
    2190           0 :   }
    2191             :   //
    2192             :   //---------------------------------------------------------------
    2193             :   //
    2194           0 :   void AWProjectFT::get(VisBuffer2& vb, Cube<Complex>& modelVis, 
    2195             :                          Array<Complex>& griddedVis, Vector<Double>& scale,
    2196             :                          Int row)
    2197             :   {
    2198             : 
    2199             :     (void)scale; //Suppress the warning
    2200             : 
    2201           0 :     Int nX=griddedVis.shape()(0);
    2202           0 :     Int nY=griddedVis.shape()(1);
    2203           0 :     Vector<Double> offset(2);
    2204           0 :     offset(0)=Double(nX)/2.0;
    2205           0 :     offset(1)=Double(nY)/2.0;
    2206             :     // If row is -1 then we pass through all rows
    2207             :     Int startRow, endRow, nRow;
    2208           0 :     if (row==-1) 
    2209             :       {
    2210           0 :         nRow=vb.nRows();
    2211           0 :         startRow=0;
    2212           0 :         endRow=nRow-1;
    2213           0 :         modelVis.set(Complex(0.0,0.0));
    2214             :       } 
    2215             :     else 
    2216             :       {
    2217           0 :         nRow=1;
    2218           0 :         startRow=row;
    2219           0 :         endRow=row;
    2220             :       }
    2221             :     
    2222           0 :     Int NAnt=0;
    2223             :     
    2224           0 :     if (doPointing) 
    2225           0 :       NAnt = findPointingOffsets(vb,l_offsets, m_offsets,true);
    2226             :     
    2227             :     
    2228             :     //  
    2229             :     // Get the uvws in a form that Fortran can use
    2230             :     //
    2231           0 :     Matrix<Double> uvw(negateUV(vb));
    2232           0 :     Vector<Double> dphase(vb.nRows());
    2233           0 :     dphase=0.0;
    2234           0 :     doUVWRotation_p=true;
    2235             :     //rotateUVW(uvw, dphase, vb);
    2236           0 :     girarUVW(uvw, dphase, vb); 
    2237           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2238             :     
    2239             :     // This is the convention for dphase
    2240             :     //dphase*=-1.0;
    2241             :     
    2242           0 :     Cube<Int> flags(vb.flagCube().shape());
    2243           0 :     flags=0;
    2244           0 :     flags(vb.flagCube())=true;
    2245             :     
    2246             :     
    2247           0 :     matchChannel(vb);
    2248           0 :     Vector<Int> rowFlags(vb.nRows());
    2249           0 :     rowFlags=0;
    2250           0 :     rowFlags(vb.flagRow())=true;
    2251           0 :     if(!usezero_p) 
    2252           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2253           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2254             :     
    2255           0 :     visResampler_p->setParams(uvScale,uvOffset,dphase);
    2256           0 :     visResampler_p->setMaps(chanMap, polMap);
    2257           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2258             : 
    2259           0 :     IPosition s(modelVis.shape());
    2260           0 :     Int Conj=0,doGrad=0,ScanNo=0;
    2261           0 :     Double area=1.0;
    2262           0 :     Int tmpPAI=1;
    2263           0 :     Cube<Complex> visCubeModel(vb.visCubeModel());
    2264           0 :     runFortranGet(uvw,dphase,visCubeModel,s,Conj,flags,rowFlags,row,
    2265           0 :                   offset,&griddedVis,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2266           0 :                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    2267           0 :     vb.setVisCubeModel(visCubeModel);
    2268           0 :   }
    2269             :   //
    2270             :   //----------------------------------------------------------------------
    2271             :   //
    2272           0 :   void AWProjectFT::initVisBuffer(VisBuffer2& vb, Type whichVBColumn)
    2273             :   {
    2274           0 :     if (whichVBColumn      == FTMachine::MODEL)    vb.setVisCubeModel(Complex(0.0,0.0));
    2275           0 :     else if (whichVBColumn == FTMachine::OBSERVED) vb.setVisCube(Complex(0.0,0.0));
    2276           0 :   }
    2277             :   //
    2278             :   //----------------------------------------------------------------------
    2279             :   //
    2280           0 :     void AWProjectFT::initVisBuffer(VisBuffer2&, // vb
    2281             :                                     Type, // whichVBColumn
    2282             :                                     Int // row
    2283             :                                     )
    2284             :   {
    2285           0 :     cerr << "AWProjectFT::initVisBuffer(VisBuffer2& vb, Type whichVBColumn, Int row) disabled" << endl;
    2286           0 :   }
    2287             : 
    2288           0 :     void AWProjectFT::ComputeResiduals(VisBuffer2&vb, Bool useCorrected)
    2289             :     {
    2290           0 :       VBStore vbs;
    2291             : 
    2292           0 :       vbs.nRow_p = vb.nRows();
    2293           0 :       vbs.beginRow_p = 0;
    2294           0 :       vbs.endRow_p = vbs.nRow_p;
    2295             : 
    2296           0 :       vbs.modelCube_p.reference(vb.visCubeModel());
    2297           0 :       if (useCorrected) vbs.correctedCube_p.reference(vb.visCubeCorrected());
    2298           0 :       else vbs.visCube_p.reference(vb.visCube());
    2299           0 :       vbs.useCorrected_p = useCorrected;
    2300           0 :       visResampler_p->ComputeResiduals(vbs);
    2301           0 :     }
    2302             : 
    2303             :     //
    2304             :     //---------------------------------------------------------------
    2305             :     //---------------------------------------------------------------
    2306             :     //---------------------------------------------------------------
    2307             :     //---------------------------------------------------------------
    2308             :     // THIS IS FOR NON-PRODUCTION WORK.  HERE SINCE IT DOES LINK TO POINTING SELFCAL CODE
    2309             :     //
    2310             :     // Predict the coherences as well as their derivatives w.r.t. the
    2311             :     // pointing offsets.
    2312             :     //
    2313           0 :     void AWProjectFT::nget(VisBuffer2& vb,
    2314             :                            // These offsets should be appropriate for the VB
    2315             :                            Array<Float>& l_off, Array<Float>& m_off,
    2316             :                            Cube<Complex>& Mout,
    2317             :                            Cube<Complex>& dMout1,
    2318             :                            Cube<Complex>& dMout2,
    2319             :                            Int Conj, Int doGrad)
    2320             :     {
    2321           0 :       LogIO log_l(LogOrigin("AWProjectFT2", "nget[R&D]"));
    2322             :       Int startRow, endRow, nRow;
    2323           0 :       nRow=vb.nRows();
    2324           0 :       startRow=0;
    2325           0 :       endRow=nRow-1;
    2326             : 
    2327           0 :       Mout = dMout1 = dMout2 = Complex(0,0);
    2328             : 
    2329           0 :       findConvFunction(*image, vb);
    2330           0 :       Int NAnt=0;
    2331           0 :       Nant_p     = vb.subtableColumns().antenna().nrow();
    2332           0 :       if (doPointing)   
    2333           0 :         NAnt = findPointingOffsets(vb,l_offsets,m_offsets,false);
    2334             : 
    2335           0 :       l_offsets=l_off;
    2336           0 :       m_offsets=m_off;
    2337           0 :       Matrix<Double> uvw(negateUV(vb));
    2338             :     
    2339           0 :       Vector<Double> dphase(vb.nRows());
    2340           0 :       dphase=0.0;
    2341           0 :       doUVWRotation_p=true;
    2342             :       //rotateUVW(uvw, dphase, vb);
    2343           0 :       girarUVW(uvw, dphase, vb);
    2344           0 :       refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2345             :       // This is the convention for dphase
    2346             :       //    dphase*=-1.0;
    2347             : 
    2348           0 :       Cube<Int> flags(vb.flagCube().shape());
    2349           0 :       flags=0;
    2350           0 :       flags(vb.flagCube())=true;
    2351             :     
    2352           0 :       Vector<Int> rowFlags(vb.nRows());
    2353           0 :       rowFlags=0;
    2354           0 :       rowFlags(vb.flagRow())=true;
    2355           0 :       if(!usezero_p) 
    2356           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2357           0 :           if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2358             :     
    2359           0 :       IPosition s,gradS;
    2360           0 :       Cube<Complex> visdata,gradVisAzData,gradVisElData;
    2361             :       //
    2362             :       // visdata now references the Mout data structure rather than to the internal VB storeage.
    2363             :       //
    2364           0 :       visdata.reference(Mout);
    2365             : 
    2366           0 :       if (doGrad)
    2367             :         {
    2368             :           // The following should reference some slice of dMout?
    2369           0 :           gradVisAzData.reference(dMout1);
    2370           0 :           gradVisElData.reference(dMout2);
    2371             :         }
    2372           0 :       visResampler_p->setParams(uvScale,uvOffset,dphase);
    2373           0 :       visResampler_p->setMaps(chanMap, polMap);
    2374           0 :       visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2375             : 
    2376           0 :       makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2377           0 :       makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2378           0 :       visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2379             :       //
    2380             :       // Begin the actual de-gridding.
    2381             :       //
    2382           0 :       if(isTiled) 
    2383             :         {
    2384           0 :           log_l << "The sky model is tiled" << LogIO::NORMAL << LogIO::POST;
    2385           0 :           Double invLambdaC=vb.getFrequencies(0)(0)/C::c;
    2386           0 :           Vector<Double> uvLambda(2);
    2387           0 :           Vector<Int> centerLoc2D(2);
    2388           0 :           centerLoc2D=0;
    2389             :         
    2390             :           // Loop over all rows
    2391           0 :           for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2392             :             {
    2393             :             
    2394             :               // Calculate uvw for this row at the center frequency
    2395           0 :               uvLambda(0)=uvw(0, rownr)*invLambdaC;
    2396           0 :               uvLambda(1)=uvw(1, rownr)*invLambdaC;
    2397           0 :               centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    2398             :             
    2399             :               // Is this point on the grid?
    2400           0 :               if(gridder->onGrid(centerLoc2D)) 
    2401             :                 {
    2402             :                 
    2403             :                   // Get the tile
    2404           0 :                   Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    2405           0 :                   gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    2406           0 :                   Int aNx=dataPtr->shape()(0);
    2407           0 :                   Int aNy=dataPtr->shape()(1);
    2408             :                 
    2409             :                   // Now use FORTRAN to do the gridding. Remember to 
    2410             :                   // ensure that the shape and offsets of the tile are 
    2411             :                   // accounted for.
    2412             :                 
    2413           0 :                   Vector<Double> actualOffset(3);
    2414           0 :                   for (Int i=0;i<2;i++) 
    2415           0 :                     actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    2416             :                 
    2417           0 :                   actualOffset(2)=uvOffset(2);
    2418           0 :                   IPosition s(vb.visCubeModel().shape());
    2419             :                 
    2420           0 :                   Int ScanNo=0, tmpPAI;
    2421           0 :                   Double area=1.0;
    2422           0 :                   tmpPAI = 1;
    2423           0 :                   runFortranGetGrad(uvw,dphase,visdata,s,
    2424             :                                     gradVisAzData,gradVisElData,
    2425             :                                     Conj,flags,rowFlags,rownr,
    2426           0 :                                     actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    2427           0 :                                     l_offsets,m_offsets,area,doGrad,tmpPAI);
    2428           0 :                 }
    2429             :             }
    2430           0 :         }
    2431             :       else 
    2432             :         {
    2433           0 :           IPosition s(vb.visCubeModel().shape());
    2434           0 :           Int ScanNo=0, tmpPAI, trow=-1;
    2435           0 :           Double area=1.0;
    2436           0 :           tmpPAI = 1;
    2437           0 :           runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    2438             :                             gradVisAzData, gradVisElData,
    2439             :                             Conj,flags,rowFlags,trow,
    2440           0 :                             uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2441           0 :                             l_offsets,m_offsets,area,doGrad,tmpPAI);
    2442           0 :         }
    2443             :     
    2444           0 :     }
    2445           0 :     void AWProjectFT::get(VisBuffer2& vb,       
    2446             :                           VisBuffer2& gradVBAz,
    2447             :                           VisBuffer2& gradVBEl,
    2448             :                           Cube<Float>& pointingOffsets,
    2449             :                           Int row,  // default row=-1 
    2450             :                           Type whichVBColumn, // default whichVBColumn = FTMachine::MODEL
    2451             :                           Type whichGradVBColumn,// default whichGradVBColumn = FTMachine::MODEL
    2452             :                           Int Conj, Int doGrad) // default Conj=0, doGrad=1
    2453             :     {
    2454             :       // If row is -1 then we pass through all rows
    2455             :       Int startRow, endRow, nRow;
    2456           0 :       if (row==-1) 
    2457             :         {
    2458           0 :           nRow=vb.nRows();
    2459           0 :           startRow=0;
    2460           0 :           endRow=nRow-1;
    2461           0 :           initVisBuffer(vb,whichVBColumn);
    2462           0 :           if (doGrad)
    2463             :             {
    2464           0 :               initVisBuffer(gradVBAz, whichGradVBColumn);
    2465           0 :               initVisBuffer(gradVBEl, whichGradVBColumn);
    2466             :             }
    2467             :         }
    2468             :       else 
    2469             :         {
    2470           0 :           nRow=1;
    2471           0 :           startRow=row;
    2472           0 :           endRow=row;
    2473           0 :           initVisBuffer(vb,whichVBColumn,row);
    2474           0 :           if (doGrad)
    2475             :             {
    2476           0 :               initVisBuffer(gradVBAz, whichGradVBColumn,row);
    2477           0 :               initVisBuffer(gradVBEl, whichGradVBColumn,row);
    2478             :             }
    2479             :         }
    2480             :     
    2481           0 :       findConvFunction(*image, vb);
    2482             : 
    2483           0 :       Nant_p     = vb.subtableColumns().antenna().nrow();
    2484           0 :       Int NAnt=0;
    2485           0 :       if (doPointing)   
    2486           0 :         NAnt = findPointingOffsets(vb,pointingOffsets,l_offsets,m_offsets,false);
    2487             : 
    2488           0 :       Matrix<Double> uvw(negateUV(vb));
    2489             :     
    2490           0 :       Vector<Double> dphase(vb.nRows());
    2491           0 :       dphase=0.0;
    2492           0 :       doUVWRotation_p=true;
    2493             :       // rotateUVW(uvw, dphase, vb);
    2494           0 :       girarUVW(uvw, dphase, vb);
    2495           0 :       refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2496             :     
    2497             :       // This is the convention for dphase
    2498             :       //dphase*=-1.0;
    2499             :     
    2500             :     
    2501           0 :       Cube<Int> flags(vb.flagCube().shape());
    2502           0 :       flags=0;
    2503           0 :       flags(vb.flagCube())=true;
    2504             :       //    
    2505             :       //Check if ms has changed then cache new spw and chan selection
    2506             :       //
    2507             :       // if(vb.newMS()) matchAllSpwChans(vb);
    2508             :     
    2509             :       //Here we redo the match or use previous match
    2510             :       //
    2511             :       //Channel matching for the actual spectral window of buffer
    2512             :       //
    2513             :       // if(doConversion_p[vb.spectralWindow()])
    2514             :       //   matchChannel(vb.spectralWindow(), vb);
    2515             :       // else
    2516             :       //   {
    2517             :       //        chanMap.resize();
    2518             :       //        chanMap=multiChanMap_p[vb.spectralWindow()];
    2519             :       //   }
    2520             :     
    2521           0 :       matchChannel(vb);
    2522           0 :       Vector<Int> rowFlags(vb.nRows());
    2523           0 :       rowFlags=0;
    2524           0 :       rowFlags(vb.flagRow())=true;
    2525           0 :       if(!usezero_p) 
    2526           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2527           0 :           if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2528             :         
    2529           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2530           0 :         if (vb.antenna1()(rownr) != vb.antenna2()(rownr)) 
    2531           0 :           rowFlags(rownr) = (vb.flagRow()(rownr)==true);
    2532             :     
    2533           0 :       IPosition s,gradS;
    2534           0 :       Cube<Complex> visdata,gradVisAzData,gradVisElData;
    2535           0 :       if (whichVBColumn == FTMachine::MODEL) 
    2536             :         {
    2537           0 :           s = vb.visCubeModel().shape();
    2538           0 :           visdata.reference(vb.visCubeModel());
    2539             :         }
    2540           0 :       else if (whichVBColumn == FTMachine::OBSERVED)  
    2541             :         {
    2542           0 :           s = vb.visCube().shape();
    2543           0 :           visdata.reference(vb.visCube());
    2544             :         }
    2545             :     
    2546           0 :       if (doGrad)
    2547             :         {
    2548           0 :           if (whichGradVBColumn == FTMachine::MODEL) 
    2549             :             {
    2550             :               //            gradS = gradVBAz.modelVisCube().shape();
    2551           0 :               gradVisAzData.reference(gradVBAz.visCubeModel());
    2552           0 :               gradVisElData.reference(gradVBEl.visCubeModel());
    2553             :             }
    2554           0 :           else if (whichGradVBColumn == FTMachine::OBSERVED)  
    2555             :             {
    2556             :               //            gradS = gradVBAz.visCube().shape();
    2557           0 :               gradVisAzData.reference(gradVBAz.visCube());
    2558           0 :               gradVisElData.reference(gradVBEl.visCube());
    2559             :             }
    2560             :         }
    2561           0 :       visResampler_p->setParams(uvScale,uvOffset,dphase);
    2562           0 :       visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2563           0 :       visResampler_p->setMaps(chanMap, polMap);
    2564             :       //  Vector<Int> ConjCFMap, CFMap;
    2565           0 :       makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2566           0 :       makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2567           0 :       visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2568             :     
    2569           0 :       if(isTiled) 
    2570             :         {
    2571           0 :           Double invLambdaC=vb.getFrequencies(0)(0)/C::c;
    2572           0 :           Vector<Double> uvLambda(2);
    2573           0 :           Vector<Int> centerLoc2D(2);
    2574           0 :           centerLoc2D=0;
    2575             :         
    2576             :           // Loop over all rows
    2577           0 :           for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2578             :             {
    2579             :             
    2580             :               // Calculate uvw for this row at the center frequency
    2581           0 :               uvLambda(0)=uvw(0, rownr)*invLambdaC;
    2582           0 :               uvLambda(1)=uvw(1, rownr)*invLambdaC;
    2583           0 :               centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    2584             :             
    2585             :               // Is this point on the grid?
    2586           0 :               if(gridder->onGrid(centerLoc2D)) 
    2587             :                 {
    2588             :                 
    2589             :                   // Get the tile
    2590           0 :                   Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    2591           0 :                   gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    2592           0 :                   Int aNx=dataPtr->shape()(0);
    2593           0 :                   Int aNy=dataPtr->shape()(1);
    2594             :                 
    2595             :                   // Now use FORTRAN to do the gridding. Remember to 
    2596             :                   // ensure that the shape and offsets of the tile are 
    2597             :                   // accounted for.
    2598             :                 
    2599           0 :                   Vector<Double> actualOffset(3);
    2600           0 :                   for (Int i=0;i<2;i++) 
    2601           0 :                     actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    2602             :                 
    2603           0 :                   actualOffset(2)=uvOffset(2);
    2604           0 :                   IPosition s(vb.visCubeModel().shape());
    2605             :                 
    2606           0 :                   Int ScanNo=0, tmpPAI;
    2607           0 :                   Double area=1.0;
    2608           0 :                   tmpPAI = 1;
    2609           0 :                   runFortranGetGrad(uvw,dphase,visdata,s,
    2610             :                                     gradVisAzData,gradVisElData,
    2611             :                                     Conj,flags,rowFlags,rownr,
    2612           0 :                                     actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    2613           0 :                                     l_offsets,m_offsets,area,doGrad,tmpPAI);
    2614           0 :                 }
    2615             :             }
    2616           0 :         }
    2617             :       else 
    2618             :         {
    2619             :         
    2620           0 :           IPosition s(vb.visCubeModel().shape());
    2621           0 :           Int ScanNo=0, tmpPAI;
    2622           0 :           Double area=1.0;
    2623             : 
    2624           0 :           tmpPAI = 1;
    2625             : 
    2626           0 :           runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    2627             :                             gradVisAzData, gradVisElData,
    2628             :                             Conj,flags,rowFlags,row,
    2629           0 :                             uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2630           0 :                             l_offsets,m_offsets,area,doGrad,tmpPAI);
    2631           0 :         }
    2632           0 :     }
    2633             :     //---------------------------------------------------------------
    2634             :     //---------------------------------------------------------------
    2635             :     //---------------------------------------------------------------
    2636             :     //---------------------------------------------------------------
    2637             :     // THIS IS FOR NON-PRODUCTION WORK.  HERE SINCE IT DOES LINK TO POINTING SELFCAL CODE
    2638             :     
    2639             : } //# NAMESPACE CASA - END
    2640             : };

Generated by: LCOV version 1.16