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

Generated by: LCOV version 1.16