LCOV - code coverage report
Current view: top level - synthesis/TransformMachines - AWProjectFT.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 0 1261 0.0 %
Date: 2023-11-02 14:27:30 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: aips2-request@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/TransformMachines/AWProjectFT.h>
      44             : #include <synthesis/TransformMachines/AWConvFunc.h>
      45             : #include <synthesis/TransformMachines/CFStore2.h>
      46             : #include <synthesis/MeasurementComponents/ExpCache.h>
      47             : #include <synthesis/MeasurementComponents/CExp.h>
      48             : #include <synthesis/TransformMachines/AWVisResampler.h>
      49             : #include <synthesis/TransformMachines/VBStore.h>
      50             : 
      51             : #include <casacore/scimath/Mathematics/FFTServer.h>
      52             : #include <casacore/scimath/Mathematics/MathFunc.h>
      53             : #include <casacore/measures/Measures/MeasTable.h>
      54             : #include <iostream>
      55             : #include <casacore/casa/OS/Timer.h>
      56             : 
      57             : #include <synthesis/TransformMachines/ATerm.h>
      58             : #include <synthesis/TransformMachines/NoOpATerm.h>
      59             : #include <synthesis/TransformMachines/AWConvFunc.h>
      60             : #include <synthesis/TransformMachines/EVLAAperture.h>
      61             : #include <synthesis/TransformMachines/AWConvFuncEPJones.h>
      62             : 
      63             : //#define CONVSIZE (1024*2)
      64             : // #define OVERSAMPLING 2
      65             : #define USETABLES 0           // If equal to 1, use tabulated exp() and
      66             :                               // complex exp() functions.
      67             : #define MAXPOINTINGERROR 250.0 // Max. pointing error in arcsec used to
      68             : // determine the resolution of the
      69             : // tabulated exp() function.
      70             : #define DORES true
      71             : 
      72             : 
      73             : using namespace casacore;
      74             : namespace casa { //# NAMESPACE CASA - BEGIN
      75             :   
      76             : #define NEED_UNDERSCORES
      77             :   extern "C" 
      78             :   {
      79             :     //
      80             :     // The Gridding Convolution Function (GCF) used by the underlying
      81             :     // gridder written in FORTRAN.
      82             :     //
      83             :     // The arguments must all be pointers and the value of the GCF at
      84             :     // the given (u,v) point is returned in the weight variable.  Making
      85             :     // this a function which returns a complex value (namely the weight)
      86             :     // has problems when called in FORTRAN - I (SB) don't understand
      87             :     // why.
      88             :     //
      89             : #if defined(NEED_UNDERSCORES)
      90             : #define nwcppeij nwcppeij_
      91             : #endif
      92             :     //
      93             :     //---------------------------------------------------------------
      94             :     //
      95             :     IlluminationConvFunc awEij;
      96           0 :     void awcppeij(Double *griduvw, Double *area,
      97             :                  Double *raoff1, Double *decoff1,
      98             :                  Double *raoff2, Double *decoff2, 
      99             :                  Int *doGrad,
     100             :                  Complex *weight,
     101             :                  Complex *dweight1,
     102             :                  Complex *dweight2,
     103             :                  Double *currentCFPA)
     104             :     {
     105           0 :       Complex w,d1,d2;
     106           0 :       awEij.getValue(griduvw, raoff1, raoff2, decoff1, decoff2,
     107             :                     area,doGrad,w,d1,d2,*currentCFPA);
     108           0 :       *weight   = w;
     109           0 :       *dweight1 = d1;
     110           0 :       *dweight2 = d2;
     111           0 :     }
     112             :   }
     113             : 
     114           0 :   ATerm* AWProjectFT::createTelescopeATerm(const String& telescopeName, const Bool& isATermOn)
     115             :   {
     116           0 :     LogIO os(LogOrigin("AWProjectFT", "createTelescopeATerm",WHERE));
     117             :     
     118           0 :     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 :         os << "Telescope name ('"+
     127           0 :           telescopeName+"') in the MS not recognized to create the telescope specific ATerm" 
     128           0 :            << LogIO::WARN;
     129             :       }
     130             :     
     131           0 :     return NULL;
     132             :   }
     133             : 
     134           0 :   CountedPtr<ConvolutionFunction> AWProjectFT::makeCFObject(const String& telescopeName,
     135             :                                                             const Bool aTermOn,
     136             :                                                             const Bool psTermOn,
     137             :                                                             const Bool wTermOn,
     138             :                                                             const Bool mTermOn,
     139             :                                                             const Bool wbAWP,
     140             :                                                             const Bool conjBeams)
     141             :   {
     142           0 :       LogIO log_l(LogOrigin("AWProjectFT", "makeCFObject"));
     143           0 :       if ((psTermOn==false) && (aTermOn==false))
     144           0 :         log_l << "Both, psterm and aterm cannot be False.  Please set one or both to True." << LogIO::EXCEPTION;
     145             : 
     146           0 :     CountedPtr<ATerm> apertureFunction = AWProjectFT::createTelescopeATerm(telescopeName, aTermOn);
     147           0 :     CountedPtr<PSTerm> psTerm = new PSTerm();
     148           0 :     CountedPtr<WTerm> wTerm = new WTerm();
     149             :     
     150             :     //
     151             :     // Selectively switch off CFTerms.
     152             :     //
     153           0 :     if (aTermOn == false) {apertureFunction->setOpCode(CFTerms::NOOP);}
     154           0 :     if (psTermOn == false) psTerm->setOpCode(CFTerms::NOOP);
     155           0 :     if (wTermOn == False) wTerm->setOpCode(CFTerms::NOOP);
     156             :     //
     157             :     // Construct the CF object with appropriate CFTerms.
     158             :     //
     159           0 :     CountedPtr<ConvolutionFunction> awConvFunc;
     160             :     //    awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm, !wbAWP);
     161             :     //if ((ftmName=="mawprojectft") || (mTermOn))
     162           0 :     if (mTermOn)
     163           0 :       awConvFunc = new AWConvFuncEPJones(apertureFunction,psTerm,wTerm,wbAWP,conjBeams);
     164             :     else
     165           0 :       awConvFunc = new AWConvFunc(apertureFunction,psTerm,wTerm,wbAWP, conjBeams);
     166           0 :     return awConvFunc;
     167             :   }
     168             :   //
     169             :   //---------------------------------------------------------------
     170             :   //
     171           0 :   AWProjectFT::AWProjectFT()
     172             :     : FTMachine(), padding_p(1.0), nWPlanes_p(1),
     173             :       imageCache(0), cachesize(0), tilesize(16),
     174             :       gridder(0), isTiled(false), arrayLattice( ), lattice( ), 
     175             :       maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
     176             :       pointingToImage(0), usezero_p(false),
     177             :       // convFunc_p(), convWeights_p(),
     178             :       epJ_p(),
     179             :       doPBCorrection(true), conjBeams_p(true),/*cfCache_p(cfcache),*/ paChangeDetector(),
     180             :       rotateOTFPAIncr_p(0.1),
     181             :       Second("s"),Radian("rad"),Day("d"), pbNormalized_p(false), paNdxProcessed_p(),
     182             :       visResampler_p(), sensitivityPatternQualifier_p(-1),sensitivityPatternQualifierStr_p(""),
     183             :       rotatedConvFunc_p(),//cfs2_p(), cfwts2_p(), 
     184           0 :       runTime1_p(0.0), previousSPWID_p(-1)
     185             :   {
     186             :     //    convSize=0;
     187           0 :     tangentSpecified_p=false;
     188           0 :     lastIndex_p=0;
     189           0 :     paChangeDetector.reset();
     190           0 :     pbLimit_p=5e-2;
     191             :     //
     192             :     // Get various parameters from the visibilities.  
     193             :     //
     194           0 :     doPointing=1; 
     195             : 
     196           0 :     maxConvSupport=-1;  
     197             :     //
     198             :     // Set up the Conv. Func. disk cache manager object.
     199             :     //
     200             :     // if (!cfCache_p.null()) delete &cfCache_p;
     201             :     // cfCache_p=cfcache;
     202           0 :     convSampling=OVERSAMPLING;
     203             :     //convSize=CONVSIZE;
     204           0 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     205           0 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     206           0 :     if (cachesize > hostRAM) cachesize=hostRAM;
     207           0 :     sigma=1.0;
     208           0 :     canComputeResiduals_p=DORES;
     209             :     // cfs2_p = &cfCache_p->memCache2_p[0];//new CFStore2;
     210             :     // cfwts2_p =  &cfCache_p->memCacheWt2_p[0];//new CFStore2;
     211           0 :     pop_p->init();
     212           0 :     CFBuffer::initCFBStruct(cfbst_pub);
     213             :     //    rotatedConvFunc_p.data=new Array<Complex>();    
     214           0 :   }
     215             :   //
     216             :   //---------------------------------------------------------------
     217             :   //
     218           0 :   AWProjectFT::AWProjectFT(Int nWPlanes, Long icachesize, 
     219             :                            CountedPtr<CFCache>& cfcache,
     220             :                            CountedPtr<ConvolutionFunction>& cf,
     221             :                            CountedPtr<VisibilityResamplerBase>& visResampler,
     222             :                            Bool applyPointingOffset,
     223             :                            Bool doPBCorr,
     224             :                            Int itilesize, 
     225             :                            Float pbLimit,
     226             :                            Bool usezero,
     227             :                            Bool conjBeams,
     228             :                            Bool doublePrecGrid,
     229           0 :                            PolOuterProduct::MuellerType muellerType)
     230             :     : FTMachine(cfcache,cf), padding_p(1.0), nWPlanes_p(nWPlanes),
     231             :       imageCache(0), cachesize(icachesize), tilesize(itilesize),
     232             :       gridder(0), isTiled(false), arrayLattice( ), lattice( ), 
     233             :       maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
     234             :       pointingToImage(0), usezero_p(usezero),
     235             :       // convFunc_p(), convWeights_p(),
     236             :       epJ_p(),
     237             :       doPBCorrection(doPBCorr), conjBeams_p(conjBeams), 
     238             :       /*cfCache_p(cfcache),*/ paChangeDetector(),
     239             :       rotateOTFPAIncr_p(0.1),
     240             :       Second("s"),Radian("rad"),Day("d"), pbNormalized_p(false),
     241             :       visResampler_p(visResampler), sensitivityPatternQualifier_p(-1),sensitivityPatternQualifierStr_p(""),
     242           0 :       rotatedConvFunc_p(), runTime1_p(0.0), previousSPWID_p(-1)
     243             :   {
     244             :     //convSize=0;
     245           0 :     tangentSpecified_p=false;
     246           0 :     lastIndex_p=0;
     247           0 :     paChangeDetector.reset();
     248           0 :     pbLimit_p=pbLimit;
     249             :     //
     250             :     // Get various parameters from the visibilities.  
     251             :     //
     252           0 :     if (applyPointingOffset) doPointing=1; else doPointing=0;
     253             : 
     254           0 :     maxConvSupport=-1;  
     255             :     //
     256             :     // Set up the Conv. Func. disk cache manager object.
     257             :     //
     258             :     // if (!cfCache_p.null()) delete &cfCache_p;
     259             :     // cfCache_p=cfcache;
     260           0 :     convSampling=OVERSAMPLING;
     261             :     //convSize=CONVSIZE;
     262           0 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     263           0 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     264           0 :     if (cachesize > hostRAM) cachesize=hostRAM;
     265           0 :     sigma=1.0;
     266           0 :     canComputeResiduals_p=DORES;
     267           0 :     if (!cfCache_p.null())
     268             :       {
     269           0 :         cfs2_p = CountedPtr<CFStore2>(&(cfCache_p->memCache2_p)[0],false);//new CFStore2;
     270           0 :         cfwts2_p =  CountedPtr<CFStore2>(&cfCache_p->memCacheWt2_p[0],false);//new CFStore2;
     271             :       }
     272           0 :     pop_p->init();
     273           0 :     useDoubleGrid_p=doublePrecGrid;
     274           0 :     useDoubleGrid_p=doublePrecGrid;
     275           0 :     CFBuffer::initCFBStruct(cfbst_pub);
     276           0 :     muellerType_p = muellerType;
     277           0 :   }
     278             :   //
     279             :   //---------------------------------------------------------------
     280             :   //
     281           0 :   AWProjectFT::AWProjectFT(const RecordInterface& stateRec)
     282           0 :     : FTMachine(),Second("s"),Radian("rad"),Day("d"),visResampler_p()//, cfs2_p(), cfwts2_p()
     283             :   {
     284           0 :     LogIO log_l(LogOrigin("AWProjectFT", "AWProjectFT[R&D]"));
     285             :     //
     286             :     // Construct from the input state record
     287             :     //
     288           0 :     String error;
     289             :     
     290           0 :     if (!fromRecord(stateRec)) {
     291           0 :       log_l << "Failed to create " << name() << " object." << LogIO::EXCEPTION;
     292             :     };
     293           0 :     maxConvSupport=-1;
     294           0 :     convSampling=OVERSAMPLING;
     295           0 :     visResampler_p->init(useDoubleGrid_p);
     296             :     //convSize=CONVSIZE;
     297           0 :     canComputeResiduals_p=DORES;
     298           0 :     if (!cfCache_p.null())
     299             :       {
     300           0 :         cfs2_p = CountedPtr<CFStore2>(&cfCache_p->memCache2_p[0],false);//new CFStore2;
     301           0 :         cfwts2_p =  CountedPtr<CFStore2>(&cfCache_p->memCacheWt2_p[0],false);//new CFStore2;
     302             :       }
     303           0 :     pop_p->init();
     304           0 :   }
     305             :   //
     306             :   //----------------------------------------------------------------------
     307             :   //
     308           0 :   AWProjectFT::AWProjectFT(const AWProjectFT& other):FTMachine()
     309             :   {
     310           0 :     operator=(other);
     311           0 :   }
     312             :   //
     313             :   //---------------------------------------------------------------
     314             :   //
     315             :   // This is nasty, we should use CountedPointers here.
     316           0 :   AWProjectFT::~AWProjectFT() 
     317             :   {
     318           0 :       if(imageCache) delete imageCache; imageCache=0;
     319           0 :       if(gridder) delete gridder; gridder=0;
     320           0 :   }
     321             :   //
     322             :   //---------------------------------------------------------------
     323             :   //
     324           0 :   AWProjectFT& AWProjectFT::operator=(const AWProjectFT& other)
     325             :   {
     326           0 :     if(this!=&other) 
     327             :       {
     328             :         //Do the base parameters
     329           0 :         FTMachine::operator=(other);
     330             : 
     331             :         
     332           0 :         padding_p=other.padding_p;
     333             :         
     334           0 :         nWPlanes_p=other.nWPlanes_p;
     335           0 :         imageCache=other.imageCache;
     336           0 :         cachesize=other.cachesize;
     337           0 :         tilesize=other.tilesize;
     338           0 :         cfRefFreq_p = other.cfRefFreq_p;
     339           0 :         if(other.gridder==0) gridder=0;
     340             :         else
     341             :           {
     342           0 :             uvScale.resize();
     343           0 :             uvOffset.resize();
     344           0 :             uvScale=other.uvScale;
     345           0 :             uvOffset=other.uvOffset;
     346           0 :             gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     347           0 :                                                            uvScale, uvOffset,
     348           0 :                                                            "SF");
     349             :           }
     350             : 
     351           0 :         isTiled=other.isTiled;
     352           0 :         lattice=0;
     353           0 :         arrayLattice=0;
     354             : 
     355           0 :         maxAbsData=other.maxAbsData;
     356           0 :         centerLoc=other.centerLoc;
     357           0 :         offsetLoc=other.offsetLoc;
     358           0 :         pointingToImage=other.pointingToImage;
     359           0 :         usezero_p=other.usezero_p;
     360             : 
     361             :         
     362           0 :         padding_p=other.padding_p;
     363           0 :         nWPlanes_p=other.nWPlanes_p;
     364           0 :         imageCache=other.imageCache;
     365           0 :         cachesize=other.cachesize;
     366           0 :         tilesize=other.tilesize;
     367           0 :         isTiled=other.isTiled;
     368           0 :         maxAbsData=other.maxAbsData;
     369           0 :         centerLoc=other.centerLoc;
     370           0 :         offsetLoc=other.offsetLoc;
     371           0 :         pointingToImage=other.pointingToImage;
     372           0 :         usezero_p=other.usezero_p;
     373           0 :         doPBCorrection = other.doPBCorrection;
     374           0 :         maxConvSupport= other.maxConvSupport;
     375             : 
     376           0 :         epJ_p=other.epJ_p;
     377             :         //convSize=other.convSize;
     378           0 :         lastIndex_p=other.lastIndex_p;
     379           0 :         paChangeDetector=other.paChangeDetector;
     380           0 :         pbLimit_p=other.pbLimit_p;
     381             :         //
     382             :         // Get various parameters from the visibilities.  
     383             :         //
     384           0 :         doPointing=other.doPointing;
     385             : 
     386           0 :         maxConvSupport=other.maxConvSupport;
     387             :         //
     388             :         // Set up the Conv. Func. disk cache manager object.
     389             :         //
     390           0 :         cfCache_p=other.cfCache_p;
     391           0 :         convSampling=other.convSampling;
     392             :         //convSize=other.convSize;
     393           0 :         cachesize=other.cachesize;
     394             :     
     395           0 :         currentCFPA=other.currentCFPA;
     396           0 :         lastPAUsedForWtImg = other.lastPAUsedForWtImg;
     397           0 :         avgPB_p = other.avgPB_p;
     398           0 :         avgPBSq_p = other.avgPBSq_p;
     399           0 :         convFuncCtor_p = other.convFuncCtor_p;
     400           0 :         pbNormalized_p = other.pbNormalized_p;
     401           0 :         sensitivityPatternQualifier_p = other.sensitivityPatternQualifier_p;
     402           0 :         sensitivityPatternQualifierStr_p = other.sensitivityPatternQualifierStr_p;
     403           0 :         visResampler_p=other.visResampler_p; // Copy the counted pointer
     404             :         //      visResampler_p=other.visResampler_p->clone();
     405             :         //      *visResampler_p = *other.visResampler_p; // Call the appropriate operator=()
     406             : 
     407           0 :         rotatedConvFunc_p = other.rotatedConvFunc_p;
     408           0 :         cfs2_p = other.cfs2_p;
     409           0 :         cfwts2_p = other.cfwts2_p;
     410           0 :         paNdxProcessed_p = other.paNdxProcessed_p;
     411           0 :         imRefFreq_p = other.imRefFreq_p;
     412           0 :         conjBeams_p = other.conjBeams_p;
     413           0 :         rotateOTFPAIncr_p=other.rotateOTFPAIncr_p;
     414           0 :         computePAIncr_p=other.computePAIncr_p;
     415           0 :         runTime1_p = other.runTime1_p;
     416           0 :         muellerType_p = other.muellerType_p;
     417           0 :         previousSPWID_p = other.previousSPWID_p;
     418             :       };
     419           0 :     return *this;
     420             :   };
     421             :   //
     422             :   //----------------------------------------------------------------------
     423             :   //
     424           0 :   void AWProjectFT::init() 
     425             :   {
     426           0 :     LogIO log_l(LogOrigin("AWProjectFT", "init[R&D]"));
     427             : 
     428           0 :     nx    = image->shape()(0);
     429           0 :     ny    = image->shape()(1);
     430           0 :     npol  = image->shape()(2);
     431           0 :     nchan = image->shape()(3);
     432             :     
     433           0 :     if(image->shape().product()>cachesize) 
     434           0 :       isTiled=true;
     435             :     else 
     436           0 :       isTiled=false;
     437             :     
     438           0 :     sumWeight.resize(npol, nchan);
     439           0 :     sumCFWeight.resize(npol, nchan);
     440             :     
     441           0 :     wConvSize=max(1, nWPlanes_p);
     442             :     
     443           0 :     CoordinateSystem cs=image->coordinates();
     444           0 :     uvScale.resize(3);
     445           0 :     uvScale=0.0;
     446           0 :     uvScale(0)=Float(nx)*cs.increment()(0); 
     447           0 :     uvScale(1)=Float(ny)*cs.increment()(1); 
     448           0 :     uvScale(2)=Float(wConvSize)*abs(cs.increment()(0));
     449             :     
     450           0 :     Int index= cs.findCoordinate(Coordinate::SPECTRAL);
     451           0 :     SpectralCoordinate spCS = cs.spectralCoordinate(index);
     452           0 :     imRefFreq_p = spCS.referenceValue()(0);
     453             :     
     454           0 :     uvOffset.resize(3);
     455           0 :     uvOffset(0)=nx/2;
     456           0 :     uvOffset(1)=ny/2;
     457           0 :     uvOffset(2)=0;
     458             :     
     459           0 :     if(gridder) delete gridder; gridder=0;
     460           0 :     gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     461           0 :                                                    uvScale, uvOffset,
     462           0 :                                                    "SF");
     463             :     
     464             :     // Set up image cache needed for gridding. 
     465           0 :     if(imageCache) delete imageCache;   imageCache=0;
     466             :     
     467             :     // The tile size should be large enough that the
     468             :     // extended convolution function can fit easily
     469           0 :     if(isTiled) 
     470             :       {
     471           0 :         Float tileOverlap=0.5;
     472           0 :         tilesize=min(256,tilesize);
     473           0 :         IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
     474           0 :         Vector<Float> tileOverlapVec(4);
     475           0 :         tileOverlapVec=0.0;
     476           0 :         tileOverlapVec(0)=tileOverlap;
     477           0 :         tileOverlapVec(1)=tileOverlap;
     478             :         if (sizeof(long) < 4)  // 32-bit machine
     479             :           {
     480             :             Int tmpCacheVal=static_cast<Int>(cachesize);
     481             :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     482             :                                                    tileOverlapVec,
     483             :                                                    (tileOverlap>0.0));
     484             :           }
     485             :         else  // 64-bit machine
     486             :           {
     487           0 :             Long tmpCacheVal=cachesize;
     488           0 :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     489             :                                                    tileOverlapVec,
     490           0 :                                                    (tileOverlap>0.0));
     491             :           }
     492             :       }
     493             :     
     494             : #if(USETABLES)
     495             :     Double StepSize;
     496             :     Int N=500000;
     497             :     StepSize = abs((((2*nx)/uvScale(0))/(sigma) + 
     498             :                     MAXPOINTINGERROR*1.745329E-02*(sigma)/3600.0))/N;
     499             :     if (!awEij.isReady())
     500             :       {
     501             :         log_l << "Making lookup table for exp function with a resolution of " 
     502             :               << StepSize << " radians.  "
     503             :               << "Memory used: " << sizeof(Float)*N/(1024.0*1024.0)<< " MB." 
     504             :               << LogIO::NORMAL 
     505             :               <<LogIO::POST;
     506             :         
     507             :         awEij.setSigma(sigma);
     508             :         awEij.initExpTable(N,StepSize);
     509             :         //    ExpTab.build(N,StepSize);
     510             :         
     511             :         log_l << "Making lookup table for complex exp function with a resolution of " 
     512             :               << 2*M_PI/N << " radians.  "
     513             :               << "Memory used: " << 2*sizeof(Float)*N/(1024.0*1024.0) << " MB." 
     514             :               << LogIO::NORMAL
     515             :               << LogIO::POST;
     516             :         awEij.initCExpTable(N);
     517             :         //    CExpTab.build(N);
     518             :       }
     519             : #endif
     520             :     //    vpSJ->reset();
     521           0 :     paChangeDetector.reset();
     522           0 :     makingPSF = false;
     523             :     
     524             :     //cerr << "Current runTime = " << runTime << endl;
     525           0 :   }
     526             :   //
     527             :   //---------------------------------------------------------------
     528             :   //
     529           0 :   MDirection::Convert AWProjectFT::makeCoordinateMachine(const VisBuffer& vb,
     530             :                                                          const MDirection::Types& From,
     531             :                                                          const MDirection::Types& To,
     532             :                                                          MEpoch& last)
     533             :   {
     534           0 :     LogIO log_l(LogOrigin("AWProjectFT","makeCoordinateMachine[R&D]"));
     535           0 :     Double time = getCurrentTimeStamp(vb);
     536             :     
     537           0 :     MEpoch epoch(Quantity(time,Second),MEpoch::TAI);
     538             :     //  epoch = MEpoch(Quantity(time,Second),MEpoch::TAI);
     539             :     //
     540             :     // ...now make an object to hold the observatory position info...
     541             :     //
     542           0 :     MPosition pos;
     543           0 :     String ObsName=vb.msColumns().observation().telescopeName()(vb.arrayId());
     544             :     
     545           0 :     if (!MeasTable::Observatory(pos,ObsName))
     546           0 :       log_l << "Observatory position for "+ ObsName + " not found"
     547           0 :             << LogIO::EXCEPTION;
     548             :     //
     549             :     // ...now make a Frame object out of the observatory position and
     550             :     // time objects...
     551             :     //
     552           0 :     MeasFrame frame(epoch,pos);
     553             :     //
     554             :     // ...finally make the convert machine.
     555             :     //
     556           0 :     MDirection::Convert mac(MDirection::Ref(From,frame),
     557           0 :                             MDirection::Ref(To,frame));
     558             :     
     559           0 :     MEpoch::Convert toLAST = MEpoch::Convert(MEpoch::Ref(MEpoch::TAI,frame),
     560           0 :                                              MEpoch::Ref(MEpoch::LAST,frame));
     561           0 :     last = toLAST(epoch);
     562             :     
     563           0 :     return mac;
     564             :   }
     565             :   //
     566             :   //---------------------------------------------------------------
     567             :   //
     568           0 :   int AWProjectFT::findPointingOffsets(const VisBuffer& vb, 
     569             :                                         Array<Float> &l_off,
     570             :                                         Array<Float> &m_off,
     571             :                                         Bool Evaluate)
     572             :   {
     573           0 :     LogIO log_l(LogOrigin("AWProjectFT", "findPointingOffsets[R&D]"));
     574           0 :     Int NAnt = 0;
     575           0 :     MEpoch LAST;
     576           0 :     Double thisTime = getCurrentTimeStamp(vb);
     577             :     //    Array<Float> pointingOffsets = epJ->nearest(thisTime);
     578           0 :     if (epJ_p.null()) return 0;
     579           0 :     Array<Float> pointingOffsets; epJ_p->nearest(thisTime,pointingOffsets);
     580           0 :     NAnt=pointingOffsets.shape()(2);
     581           0 :     l_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     582           0 :     m_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     583             :     // Can't figure out how to do the damn slicing of [Pol,NChan,NAnt,1] array
     584             :     // into [Pol,NChan,NAnt] array
     585             :     //
     586             :     //    l_off = pointingOffsets(Slicer(IPosition(4,0,0,0,0),IPosition(4,1,1,NAnt+1,0)));
     587             :     //    m_off = pointingOffsets(Slicer(IPosition(4,1,0,0,0),IPosition(4,1,1,NAnt+1,0)));
     588           0 :     IPosition tndx(3,0,0,0), sndx(4,0,0,0,0);
     589           0 :     for(tndx(2)=0;tndx(2)<NAnt; tndx(2)++,sndx(2)++)
     590             :       //    for(Int j=0;j<NAnt;j++)
     591             :       {
     592             :         // l_off(IPosition(3,0,0,j)) = pointingOffsets(IPosition(4,0,0,j,0));
     593             :         // m_off(IPosition(3,0,0,j)) = pointingOffsets(IPosition(4,1,0,j,0));
     594             : 
     595           0 :         sndx(0)=0; l_off(tndx) = pointingOffsets(sndx);
     596           0 :         sndx(0)=2; m_off(tndx) = pointingOffsets(sndx);
     597             :       }
     598           0 :     return NAnt;
     599             :     if (!Evaluate) return NAnt;
     600             :     
     601             :     //  cout << "AzEl Offsets: " << pointingOffsets << endl;
     602             :     //
     603             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     604             :     // (HA,Dec).
     605             :     //
     606             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     607             :                                                        MDirection::AZEL,
     608             :                                                        LAST);
     609             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     610             :                                                         MDirection::HADEC,
     611             :                                                         LAST);
     612             :     //
     613             :     // ...and now hope that it all works and works correctly!!!
     614             :     //
     615             :     Quantity dAz(0,Radian),dEl(0,Radian);
     616             :     //
     617             :     // An array of shape [2,1,1]!
     618             :     //
     619             :     Array<Double> phaseDir = vb.msColumns().field().phaseDir().getColumn();
     620             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     621             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     622             :     //  
     623             :     // Compute reference (HA,Dec)
     624             :     //
     625             :     Double LST   = LAST.get(Day).getValue();
     626             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     627             :     LST -= floor(LST); // Extract the fractional day
     628             :     LST *= 2*C::pi;// Convert to Raidan
     629             :     
     630             :     Double HA0;
     631             :     HA0 = LST - RA0;
     632             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     633             :     //
     634             :     // Convert reference (HA,Dec) to reference (Az,El)
     635             :     //
     636             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     637             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     638             :     
     639             :     MDirection tmpHADec = toHADec(AzEl0);
     640             :     
     641             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     642             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     643             :     
     644             :     //
     645             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     646             :     //
     647             :     
     648             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     649             :       {
     650             :         //
     651             :         // From (Az,El) -> (HA,Dec)
     652             :         //
     653             :         // Add (Az,El) offsets to the reference (Az,El)
     654             :         //
     655             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     656             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     657             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     658             :         //
     659             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     660             :         //
     661             :         MDirection HADec = toHADec(AzEl);
     662             :         Double HA,Dec,RA, dRA;
     663             :         HA  = HADec.getAngle(Radian).getValue()(0);
     664             :         Dec = HADec.getAngle(Radian).getValue()(1);
     665             :         RA  = LST - HA;
     666             :         dRA = RA - RA0;
     667             :         //
     668             :         // Convert offsetted (RA,Dec) -> (l,m)
     669             :         //
     670             :         l_off(n)  = sin(dRA)*cos(Dec);
     671             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     672             :         //      cout << "FindOff: " << n(2) << " " << l_offsets(n) << " " << m_offsets(n) << endl;
     673             :         
     674             :         //       cout << l_off(n) << " " << m_off(n) << " "
     675             :         //         << " " << HA << " " << Dec
     676             :         //         << " " << LST << " " << RA0 << " " << Dec0 
     677             :         //         << " " << RA << " " << Dec
     678             :         //         << endl;
     679             :       }
     680             :     
     681             :     return NAnt+1;
     682             :   }
     683             :   //
     684             :   //---------------------------------------------------------------
     685             :   //
     686           0 :   int AWProjectFT::findPointingOffsets(const VisBuffer& vb, 
     687             :                                          Cube<Float>& pointingOffsets,
     688             :                                         Array<Float> &l_off,
     689             :                                         Array<Float> &m_off,
     690             :                                         Bool Evaluate)
     691             :   {
     692           0 :     LogIO log_l(LogOrigin("AWProjectFT", "findPointingOffsets[R&D]"));
     693           0 :     Int NAnt = 0;
     694             :     //Float tmp;
     695             :     // TBD: adapt the following to VisCal mechanism:
     696           0 :     MEpoch LAST;
     697             :     
     698           0 :     NAnt=pointingOffsets.shape()(2);
     699           0 :     l_off.resize(IPosition(3,2,1,NAnt));
     700           0 :     m_off.resize(IPosition(3,2,1,NAnt));
     701           0 :     IPosition ndx(3,0,0,0),ndx1(3,0,0,0);
     702           0 :     for(ndx(2)=0;ndx(2)<NAnt;ndx(2)++)
     703             :       {
     704           0 :         ndx1=ndx;
     705           0 :         ndx(0)=0;ndx1(0)=0;     //tmp=l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_0,Ant_i
     706           0 :         ndx(0)=1;ndx1(0)=1;     //tmp=l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_1,Ant_i
     707           0 :         ndx(0)=0;ndx1(0)=2;     //tmp=m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_0,Ant_i
     708           0 :         ndx(0)=1;ndx1(0)=3;     //tmp=m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_1,Ant_i
     709             :       }
     710             : 
     711             : //     l_off  = pointingOffsets(IPosition(3,0,0,0),IPosition(3,0,0,NAnt));
     712             : //     m_off = pointingOffsets(IPosition(3,1,0,0),IPosition(3,1,0,NAnt));
     713             :     /*
     714             :     IPosition shp(pointingOffsets.shape());
     715             :     IPosition shp1(l_off.shape()),shp2(m_off.shape());
     716             :     for(Int ii=0;ii<NAnt;ii++)
     717             :       {
     718             :         IPosition ndx(3,0,0,0);
     719             :         ndx(2)=ii;
     720             :         cout << "Pointing Offsets: " << ii << " " 
     721             :              << l_off(ndx)*57.295*60.0 << " " 
     722             :              << m_off(ndx)*57.295*60.0 << endl;
     723             :       }
     724             :     */
     725           0 :     return NAnt;
     726             :     if (!Evaluate) return NAnt;
     727             :     
     728             :     //
     729             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     730             :     // (HA,Dec).
     731             :     //
     732             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     733             :                                                        MDirection::AZEL,
     734             :                                                        LAST);
     735             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     736             :                                                         MDirection::HADEC,
     737             :                                                         LAST);
     738             :     //
     739             :     // ...and now hope that it all works and works correctly!!!
     740             :     //
     741             :     Quantity dAz(0,Radian),dEl(0,Radian);
     742             :     //
     743             :     // An array of shape [2,1,1]!
     744             :     //
     745             :     Array<Double> phaseDir = vb.msColumns().field().phaseDir().getColumn();
     746             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     747             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     748             :     //  
     749             :     // Compute reference (HA,Dec)
     750             :     //
     751             :     Double LST   = LAST.get(Day).getValue();
     752             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     753             :     LST -= floor(LST); // Extract the fractional day
     754             :     LST *= 2*C::pi;// Convert to Raidan
     755             :     
     756             :     Double HA0;
     757             :     HA0 = LST - RA0;
     758             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     759             :     //
     760             :     // Convert reference (HA,Dec) to reference (Az,El)
     761             :     //
     762             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     763             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     764             :     
     765             :     MDirection tmpHADec = toHADec(AzEl0);
     766             :     
     767             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     768             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     769             :     
     770             :     //
     771             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     772             :     //
     773             :     
     774             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     775             :       {
     776             :         //
     777             :         // From (Az,El) -> (HA,Dec)
     778             :         //
     779             :         // Add (Az,El) offsets to the reference (Az,El)
     780             :         //
     781             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     782             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     783             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     784             :         //
     785             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     786             :         //
     787             :         MDirection HADec = toHADec(AzEl);
     788             :         Double HA,Dec,RA, dRA;
     789             :         HA  = HADec.getAngle(Radian).getValue()(0);
     790             :         Dec = HADec.getAngle(Radian).getValue()(1);
     791             :         RA  = LST - HA;
     792             :         dRA = RA - RA0;
     793             :         //
     794             :         // Convert offsetted (RA,Dec) -> (l,m)
     795             :         //
     796             :         l_off(n)  = sin(dRA)*cos(Dec);
     797             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     798             :         //      cout << "FindOff: " << n(2) << " " << l_offsets(n) << " " << m_offsets(n) << endl;
     799             :         
     800             :         //       cout << l_off(n) << " " << m_off(n) << " "
     801             :         //         << " " << HA << " " << Dec
     802             :         //         << " " << LST << " " << RA0 << " " << Dec0 
     803             :         //         << " " << RA << " " << Dec
     804             :         //         << endl;
     805             :       }
     806             :     
     807             :     return NAnt+1;
     808             :   }
     809             :   //
     810             :   //---------------------------------------------------------------
     811             :   //
     812           0 :   void AWProjectFT::makeSensitivityImage(const VisBuffer& vb, 
     813             :                                          const ImageInterface<Complex>& imageTemplate,
     814             :                                          ImageInterface<Float>& sensitivityImage)
     815             :   {
     816           0 :     if (convFuncCtor_p->makeAverageResponse(vb, imageTemplate, sensitivityImage))
     817           0 :       cfCache_p->flush(sensitivityImage,sensitivityPatternQualifierStr_p); 
     818           0 :   }
     819             :   //
     820             :   //---------------------------------------------------------------
     821             :   //
     822           0 :   void AWProjectFT::normalizeAvgPB(ImageInterface<Complex>& inImage,
     823             :                                    ImageInterface<Float>& outImage)
     824             :   {
     825           0 :     LogIO log_l(LogOrigin("AWProjectFT", "normalizeAvgPB[R&D]"));
     826           0 :     if (pbNormalized_p) return;
     827           0 :     IPosition inShape(inImage.shape()),ndx(4,0,0,0,0);
     828           0 :     Vector<Complex> peak(inShape(2));
     829             :     
     830           0 :     outImage.resize(inShape);
     831           0 :     outImage.setCoordinateInfo(inImage.coordinates());
     832             : 
     833             :     Bool isRefIn;
     834           0 :     Array<Complex> inBuf;
     835           0 :     Array<Float> outBuf;
     836             : 
     837           0 :     isRefIn  = inImage.get(inBuf);
     838             :     //isRefOut = outImage.get(outBuf);
     839             :     log_l << "Normalizing the average PBs to unity"
     840           0 :           << LogIO::NORMAL << LogIO::POST;
     841             :     //
     842             :     // Normalize each plane of the inImage separately to unity.
     843             :     //
     844           0 :     Complex inMax = max(inBuf);
     845           0 :     if (abs(inMax)-1.0 > 1E-3)
     846             :       {
     847           0 :         for(ndx(3)=0;ndx(3)<inShape(3);ndx(3)++)
     848           0 :           for(ndx(2)=0;ndx(2)<inShape(2);ndx(2)++)
     849             :             {
     850           0 :               peak(ndx(2)) = 0;
     851           0 :               for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++)
     852           0 :                 for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++)
     853           0 :                   if (abs(inBuf(ndx)) > peak(ndx(2)))
     854           0 :                     peak(ndx(2)) = inBuf(ndx);
     855             :               
     856           0 :               for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++)
     857           0 :                 for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++)
     858             :                   //                  avgPBBuf(ndx) *= (pbPeaks(ndx(2))/peak(ndx(2)));
     859           0 :                   inBuf(ndx) /= peak(ndx(2));
     860             :             }
     861           0 :         if (isRefIn) inImage.put(inBuf);
     862             :       }
     863             : 
     864           0 :     ndx=0;
     865           0 :     for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++)
     866           0 :       for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++)
     867             :         {
     868           0 :           IPosition plane1(ndx);
     869           0 :           plane1=ndx;
     870           0 :           plane1(2)=1; // The other poln. plane
     871             :           //      avgPBBuf(ndx) = (avgPBBuf(ndx) + avgPBBuf(plane1))/2.0;
     872           0 :           outBuf(ndx) = sqrt(real(inBuf(ndx) * inBuf(plane1)));
     873             :         }
     874             :     //
     875             :     // Rather convoluted way of copying Pol. plane-0 to Pol. plane-1!!!
     876             :     //
     877           0 :     for(ndx(1)=0;ndx(1)<inShape(1);ndx(1)++)
     878           0 :       for(ndx(0)=0;ndx(0)<inShape(0);ndx(0)++)
     879             :         {
     880           0 :           IPosition plane1(ndx);
     881           0 :           plane1=ndx;
     882           0 :           plane1(2)=1; // The other poln. plane
     883           0 :           outBuf(plane1) = real(outBuf(ndx));
     884             :         }
     885             : 
     886           0 :     pbNormalized_p = true;
     887             :   }
     888             :   //
     889             :   //---------------------------------------------------------------
     890             :   //
     891           0 :   void AWProjectFT::normalizeAvgPB()
     892             :   {
     893           0 :     LogIO log_l(LogOrigin("AWProjectFT", "normalizeAvgPB[R&D]"));
     894           0 :     if (pbNormalized_p) return;
     895             :     Bool isRefF;
     896           0 :     Array<Float> avgPBBuf;
     897           0 :     isRefF=avgPB_p->get(avgPBBuf);
     898             :     //    Float pbMax = max(avgPBBuf);
     899             :       {
     900           0 :         pbPeaks.resize(avgPB_p->shape()(2),true);
     901             :         // if (makingPSF) pbPeaks = 1.0;
     902             :         // else pbPeaks /= (Float)noOfPASteps;
     903           0 :         pbPeaks = 1.0;
     904             :         log_l << "Normalizing the average PBs to " << 1.0
     905           0 :               << LogIO::NORMAL << LogIO::POST;
     906             :         
     907           0 :         IPosition avgPBShape(avgPB_p->shape()),ndx(4,0,0,0,0);
     908           0 :         Vector<Float> peak(avgPBShape(2));
     909             :         
     910             :         
     911           0 :         Float pbMax = max(avgPBBuf);
     912           0 :         if (fabs(pbMax-1.0) > 1E-3)
     913             :           {
     914             :             //      avgPBBuf = avgPBBuf/noOfPASteps;
     915           0 :             for(ndx(3)=0;ndx(3)<avgPBShape(3);ndx(3)++)
     916           0 :               for(ndx(2)=0;ndx(2)<avgPBShape(2);ndx(2)++)
     917             :                 {
     918           0 :                   peak(ndx(2)) = 0;
     919           0 :                   for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     920           0 :                     for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     921           0 :                       if (abs(avgPBBuf(ndx)) > peak(ndx(2)))
     922           0 :                         peak(ndx(2)) = avgPBBuf(ndx);
     923             :               
     924           0 :                   for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     925           0 :                     for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     926             :                       //                      avgPBBuf(ndx) *= (pbPeaks(ndx(2))/peak(ndx(2)));
     927           0 :                       avgPBBuf(ndx) /= peak(ndx(2));
     928             :                 }
     929           0 :             if (isRefF) avgPB_p->put(avgPBBuf);
     930             :           }
     931             : 
     932           0 :         ndx=0;
     933           0 :         for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     934           0 :           for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     935             :             {
     936           0 :               IPosition plane1(ndx);
     937           0 :               plane1=ndx;
     938           0 :               plane1(2)=1; // The other poln. plane
     939           0 :               avgPBBuf(ndx) = (avgPBBuf(ndx) + avgPBBuf(plane1))/2.0;
     940             :               //              avgPBBuf(ndx) = (avgPBBuf(ndx) * avgPBBuf(plane1));
     941             :             }
     942           0 :         for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     943           0 :           for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     944             :             {
     945           0 :               IPosition plane1(ndx);
     946           0 :               plane1=ndx;
     947           0 :               plane1(2)=1; // The other poln. plane
     948           0 :               avgPBBuf(plane1) = avgPBBuf(ndx);
     949             :             }
     950             :       }
     951           0 :       pbNormalized_p = true;
     952             :   }
     953             :   //
     954             :   //---------------------------------------------------------------
     955           0 :   void AWProjectFT::makeCFPolMap(const VisBuffer& vb, const Vector<Int>& locCfStokes,
     956             :                                  Vector<Int>& polM)
     957             :   {
     958           0 :     LogIO log_l(LogOrigin("AWProjectFT", "makeCFPolMap[R&D]"));
     959           0 :     Vector<Int> msStokes = vb.corrType();
     960           0 :     Int nPol = msStokes.nelements();
     961           0 :     polM.resize(polMap.shape());
     962           0 :     polM = -1;
     963             : 
     964           0 :     for(Int i=0;i<nPol;i++)
     965           0 :       for(uInt j=0;j<locCfStokes.nelements();j++)
     966           0 :         if (locCfStokes(j) == msStokes(i))
     967           0 :             {polM(i) = j;break;}
     968           0 :   }
     969             :   //
     970             :   //---------------------------------------------------------------
     971             :   //
     972             :   // Given a polMap (mapping of which Visibility polarization is
     973             :   // gridded onto which grid plane), make a map of the conjugate
     974             :   // planes of the grid E.g, for Stokes-I and -V imaging, the two
     975             :   // planes of the uv-grid are [LL,RR].  For input VisBuffer
     976             :   // visibilites in order [RR,RL,LR,LL], polMap = [1,-1,-1,0].  The
     977             :   // conjugate map will be [0,-1,-1,1].
     978             :   //
     979           0 :   void AWProjectFT::makeConjPolMap(const VisBuffer& vb, 
     980             :                                      const Vector<Int> cfPolMap, 
     981             :                                      Vector<Int>& conjPolMap)
     982             :   {
     983           0 :     if (conjPolMap.nelements() > 0) return;
     984             : 
     985           0 :     LogIO log_l(LogOrigin("AWProjectFT", "makConjPolMap[R&D]"));
     986             : 
     987             :     //
     988             :     // All the Natak (Drama) below with slicers etc. is to extract the
     989             :     // Poln. info. for the first IF only (not much "information
     990             :     // hiding" for the code to slice arrays in a general fashion).
     991             :     //
     992             :     // Extract the shape of the array to be sliced.
     993             :     //
     994             :     log_l << "############....temp code!!!!!!!!!! "
     995           0 :           << SynthesisUtils::mapSpwIDToPolID(vb,selectedSpw_p(0))
     996           0 :           << LogIO::DEBUG1;
     997           0 :     Vector<Int> polIDs=SynthesisUtils::mapSpwIDToPolID(vb,selectedSpw_p(0));
     998           0 :     if (polIDs.nelements()==0)
     999           0 :       log_l << "Internal Error: Selected SPW did not map to any pol!" << LogIO::EXCEPTION;
    1000             :     //
    1001             :     // Use the first selected Spw to determine the pol. mapping in the
    1002             :     // VB.  This implies that the code assumes that all selected SPWs
    1003             :     // have the same pol. setup.
    1004             :     //
    1005           0 :     Int polID=polIDs(0);
    1006           0 :     Array<Int> stokesForAllIFs = vb.msColumns().polarization().corrType().get(polID);
    1007           0 :     IPosition stokesShape(stokesForAllIFs.shape());
    1008           0 :     IPosition firstIFStart(stokesShape),firstIFLength(stokesShape);
    1009             :     //
    1010             :     // Set up the start and length IPositions to extract only the
    1011             :     // first column of the array.  The following is required since the
    1012             :     // array could have only one column as well.
    1013             :     //
    1014           0 :     firstIFStart(0)=0;firstIFLength(0)=stokesShape(0);
    1015           0 :     for(uInt i=1;i<stokesShape.nelements();i++) {firstIFStart(i)=0;firstIFLength(i)=1;}
    1016             :     //
    1017             :     // Construct the slicer and produce the slice.  .nonDegenerate
    1018             :     // required to ensure the result of slice is a pure vector.
    1019             :     //
    1020           0 :     Vector<Int> visStokes = stokesForAllIFs(Slicer(firstIFStart,firstIFLength)).nonDegenerate();
    1021             : 
    1022           0 :     conjPolMap = cfPolMap;
    1023             :     
    1024           0 :     Int i,j,N = cfPolMap.nelements();
    1025           0 :     for(i=0;i<N;i++)
    1026           0 :       if (cfPolMap[i] > -1)
    1027             :         {
    1028           0 :         if      (visStokes[i] == Stokes::RR) 
    1029             :           {
    1030           0 :             conjPolMap[i]=-1;
    1031           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LL) break; 
    1032           0 :             conjPolMap[i]=cfPolMap[j];
    1033             :           }
    1034           0 :         else if (visStokes[i] == Stokes::LL) 
    1035             :           {
    1036           0 :             conjPolMap[i]=-1;
    1037           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RR) break; 
    1038           0 :             conjPolMap[i]=cfPolMap[j];
    1039             :           }
    1040           0 :         else if (visStokes[i] == Stokes::LR) 
    1041             :           {
    1042           0 :             conjPolMap[i]=-1;
    1043           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RL) break; 
    1044           0 :             conjPolMap[i]=cfPolMap[j];
    1045             :           }
    1046           0 :         else if (visStokes[i] == Stokes::RL) 
    1047             :           {
    1048           0 :             conjPolMap[i]=-1;
    1049           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LR) break; 
    1050           0 :             conjPolMap[i]=cfPolMap[j];
    1051             :           }
    1052             :         }
    1053             :   }
    1054             :   //
    1055             :   //---------------------------------------------------------------
    1056             :   // Convert the CFs in the supplied CFStore to
    1057             :   // A(nu)<Convolution>A(nu_*)
    1058             :   //
    1059           0 :   void AWProjectFT::makeWBCFWt(CFStore2& cfs, const Double imRefFreq)
    1060             :   {
    1061           0 :     LogIO log_l(LogOrigin("AWProjectFT", "makeWBCFWt[R&D]"));
    1062           0 :     log_l << "Converting WTCFs to wide-band versions" << LogIO::POST;
    1063             : 
    1064           0 :     Vector<Int> ant1List, ant2List;
    1065           0 :     Vector<Quantity> paList;
    1066           0 :     ant1List = cfs.getAnt1List();
    1067           0 :     ant2List = cfs.getAnt2List();
    1068           0 :     paList   = cfs.getPAList();
    1069             : 
    1070           0 :     if (paNdxProcessed_p.nelements() == 0) {paNdxProcessed_p.resize(1); paNdxProcessed_p[0]=false;}
    1071           0 :     CountedPtr<CFBuffer> cfb_l, cfb_clone;
    1072           0 :     Quantity dPA(360.0,"deg");
    1073           0 :     for (uInt pa=0;pa<paList.nelements();pa++)
    1074           0 :       for (uint a1=0;a1<ant1List.nelements(); a1++)
    1075           0 :         for (uint a2=0;a2<ant2List.nelements(); a2++)
    1076             :           {
    1077           0 :             if (paNdxProcessed_p.nelements() < pa) {paNdxProcessed_p.resize(pa+1,true); paNdxProcessed_p[pa]=false;}
    1078           0 :             if (!paNdxProcessed_p[pa])
    1079             :               {
    1080           0 :                 paNdxProcessed_p[pa]=true;
    1081           0 :                 Vector<Double> wVals, fVals; PolMapType mVals, mNdx, conjMVals, conjMNdx;
    1082             :                 Double fIncr, wIncr;
    1083           0 :                 cfb_l = cfs.getCFBuffer(paList[pa], dPA, ant1List(a1), ant2List(a2));
    1084           0 :                 cfb_l->getCoordList(fVals,wVals,mNdx, mVals, conjMNdx, conjMVals, fIncr, wIncr);
    1085             :                 
    1086             :                 // cerr << paList << " " << endl
    1087             :                 //      << wVals << " " << endl
    1088             :                 //      << fVals << " " << endl
    1089             :                 //      << conjMVals << " " << endl;
    1090             :                 
    1091           0 :                 cfb_clone=cfb_l->clone();
    1092           0 :                 cfb_clone->getCoordList(fVals,wVals,mNdx, mVals, conjMNdx, conjMVals, fIncr, wIncr);
    1093             :                 // cerr << "Clone: " 
    1094             :                 //      << paList << " " << endl
    1095             :                 //      << wVals << " " << endl
    1096             :                 //      << fVals << " " << endl
    1097             :                 //      << conjMVals << " " << endl;
    1098             : 
    1099           0 :                 CountedPtr<Array<Complex> > cfc_l, conjCFC_l, result_l;
    1100             :                 //
    1101             :                 // Damn!  Convolver does not work for complex convolution!
    1102             :                 //              Convolver<Complex> convolver;
    1103             : 
    1104           0 :                 for (Int nw=0;nw<(Int)wVals.nelements(); nw++)
    1105           0 :                   for (Int nf=0;nf<(Int)fVals.nelements(); nf++)
    1106           0 :                     for (Int ipol=0;ipol<(Int)conjMVals.nelements();ipol++)
    1107           0 :                       for (Int mRow=0;mRow<(Int)conjMVals[ipol].nelements(); mRow++)
    1108             :                         {
    1109             :                           Double f, cf;
    1110           0 :                           f=fVals[nf];
    1111           0 :                           cf=sqrt(2*imRefFreq*imRefFreq - f*f);
    1112           0 :                           Int conjNF = cfb_l->nearestFreqNdx(cf);
    1113             :                           // cerr << "###PTRs: " 
    1114             :                           //      << &(*(cfb_l->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow]))) << " "
    1115             :                           //      << &(*(cfb_clone->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow]))) << " "
    1116             :                           //      << &(*(cfb_clone->getCFCellPtr(conjNF,nw,conjMNdx[ipol][mRow])))
    1117             :                           //      << endl;
    1118           0 :                           result_l  = cfb_l->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow])->getStorage();
    1119           0 :                           cfc_l     = cfb_clone->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow])->getStorage();
    1120           0 :                           conjCFC_l = cfb_clone->getCFCellPtr(conjNF,nw,conjMNdx[ipol][mRow])->getStorage();
    1121             : 
    1122             :                           // convolver.setPsf(*cfc_l);
    1123             :                           // convolver.linearConv(*result_l, *conjCFC_l);
    1124           0 :                           SynthesisUtils::libreConvolver(*result_l,*conjCFC_l);
    1125             : 
    1126             : 
    1127             :                           // {
    1128             :                           //   CountedPtr<CFCell> cfc_t, conjCFC_t;
    1129             :                           //   cfc_t = cfb_l->getCFCellPtr(nf,nw,conjMNdx[ipol][mRow]);
    1130             :                           //   conjCFC_t = cfb_l->getCFCellPtr(conjNF,nw,conjMNdx[ipol][mRow]);
    1131             :                           //   cout << "-------------------------------" << " " << f << " " << cf << " " 
    1132             :                           //     << nf << " " << nw << " " << conjMNdx[ipol][mRow] << " " 
    1133             :                           //     << conjNF << " " << nw << " " << conjMNdx[ipol][mRow] << " " 
    1134             :                           //     <<endl;
    1135             :                           //   cfc_t->show("CFC: ",cout);
    1136             :                           //   conjCFC_t->show("conjCFC: ",cout);
    1137             :                           //   cout << "-------------------------------" << endl;
    1138             :                           // }
    1139             :                         }
    1140             :               }
    1141             :           }
    1142           0 :   }
    1143             :   //
    1144             :   // Locate a convlution function.  It will be either in the cache
    1145             :   // (mem. or disk cache) or will be computed and cached for possible
    1146             :   // later use.
    1147             :   //
    1148           0 :   void AWProjectFT::findConvFunction(const ImageInterface<Complex>& image,
    1149             :                                      const VisBuffer& vb)
    1150             :   {
    1151           0 :     LogIO log_l(LogOrigin("AWProjectFT", "findConvFunction[R&D]"));
    1152           0 :     if (!paChangeDetector.changed(vb,0)) return;
    1153           0 :     Int cfSource=CFDefs::NOTCACHED;
    1154           0 :     CoordinateSystem ftcoords;
    1155             :     // Think of a generic call to get the key-values.  And a
    1156             :     // overloadable method (or an externally supplied one?) to convert
    1157             :     // the values to key-ids.  That will ensure that AWProjectFT
    1158             :     // remains the A-Projection algorithm implementation configurable
    1159             :     // by the behaviour of the supplied objects.
    1160           0 :     Float pa=getVBPA(vb);
    1161             :     //UUU// ok();
    1162           0 :     visResampler_p->setMaps(chanMap, polMap); //UUU Added here.
    1163           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    1164             : 
    1165           0 :     lastPAUsedForWtImg = currentCFPA = pa;
    1166             : 
    1167           0 :     Vector<Double> pointingOffset(convFuncCtor_p->findPointingOffset(image,vb));
    1168           0 :     Float dPA = paChangeDetector.getParAngleTolerance().getValue("rad");
    1169           0 :     Quantity dPAQuant = Quantity(paChangeDetector.getParAngleTolerance());
    1170           0 :     cfSource = visResampler_p->makeVBRow2CFMap(*cfs2_p,*convFuncCtor_p, vb,
    1171             :                                                dPAQuant,
    1172           0 :                                                chanMap,polMap,pointingOffset);
    1173             : 
    1174           0 :     if (cfSource == CFDefs::NOTCACHED)
    1175             :       {
    1176           0 :         PolMapType polMat, polIndexMat, conjPolMat, conjPolIndexMat;
    1177           0 :         Vector<Int> visPolMap(vb.corrType());
    1178           0 :         polMat = pop_p->makePolMat(visPolMap,polMap);
    1179           0 :         polIndexMat = pop_p->makePol2CFMat(visPolMap,polMap);
    1180             : 
    1181             :         // polMat = pop_p->makePolMat(visPolMap,polMap);
    1182             :         // polIndexMat = pop_p->makePol2CFMat(visPolMap,polMap);
    1183             : 
    1184           0 :         conjPolMat = pop_p->makeConjPolMat(visPolMap,polMap);
    1185           0 :         conjPolIndexMat = pop_p->makeConjPol2CFMat(visPolMap,polMap);
    1186             : 
    1187           0 :         convFuncCtor_p->setPolMap(polMap);
    1188           0 :         convFuncCtor_p->setSpwSelection(spwChanSelFlag_p);
    1189           0 :         convFuncCtor_p->setSpwFreqSelection(spwFreqSel_p);
    1190             : 
    1191             :         // USEFUL DEBUG MESSAGE
    1192             :         //cerr << "Freq. selection: " << expandedSpwFreqSel_p << endl << expandedSpwConjFreqSel_p << endl;
    1193             : 
    1194             : 
    1195             :         // isDryRun = true;
    1196           0 :         Bool pleaseDoAlsoFillTheCF=!dryRun();
    1197           0 :         convFuncCtor_p->makeConvFunction(image,vb,wConvSize, 
    1198           0 :                                          pop_p, pa, dPA, uvScale, uvOffset,spwFreqSel_p,
    1199           0 :                                          *cfs2_p, *cfwts2_p, pleaseDoAlsoFillTheCF);
    1200             :         //      log_l << "Converting WTCFs to wide-band versions" << LogIO::POST;
    1201             :         //      makeWBCFWt(*cfwts2_p, imRefFreq_p);
    1202             : 
    1203             :         // cfSource = visResampler_p->makeVBRow2CFMap(*cfs2_p,*convFuncCtor_p, vb,
    1204             :         //                                         paChangeDetector.getParAngleTolerance(),
    1205             :         //                                         chanMap,polMap);
    1206             :       }
    1207             :     //
    1208             :     // If one-time-operations in the CFCache not yet done, set the
    1209             :     // pol. index maps in the CFCache.
    1210             :     //
    1211           0 :     if (!cfCache_p->OTODone())
    1212             :       {
    1213           0 :         Vector<Int> visPolMap(vb.corrType());
    1214             : 
    1215           0 :         PolMapType polMat, conjPolMat;
    1216           0 :         polMat = pop_p->makePolMat(visPolMap,polMap);
    1217           0 :         conjPolMat = pop_p->makeConjPolMat(visPolMap,polMap);
    1218             : 
    1219           0 :         PolMapType pNdx, cpNdx;
    1220           0 :         pNdx = pop_p->makePol2CFMat(visPolMap,polMap);
    1221           0 :         cpNdx = pop_p->makeConjPol2CFMat(visPolMap,polMap);
    1222             :     
    1223           0 :         cfCache_p->initPolMaps(pNdx,cpNdx);
    1224             : 
    1225           0 :         cfs2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1226           0 :         cfwts2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1227             :       }
    1228             :     //
    1229             :     // Load the average PB (sensitivity pattern) from the cache.  If
    1230             :     // not found in the cache, make one and cache it.
    1231             :     //
    1232           0 :     if (cfCache_p->loadAvgPB(avgPB_p,sensitivityPatternQualifierStr_p) == CFDefs::NOTCACHED)
    1233           0 :         makeSensitivityImage(vb,image,*avgPB_p);
    1234             : 
    1235           0 :     verifyShapes(avgPB_p->shape(), image.shape());
    1236             : 
    1237           0 :     if (paChangeDetector.changed(vb,0)) paChangeDetector.update(vb,0);
    1238             :     //
    1239             :     // Write some useful info. to the logger.
    1240             :     //
    1241           0 :     if (cfSource != CFDefs::MEMCACHE)
    1242             :       {
    1243           0 :         if (dryRun())
    1244             :           {
    1245             :             // PagedImage<Complex> thisGrid(lattice->shape(),image.coordinates(), 
    1246             :             //                           cfCache_p->getCacheDir()+"/uvgrid.im");
    1247           0 :             PagedImage<Complex> thisGrid(image.shape(),image.coordinates(), 
    1248           0 :                                          cfCache_p->getCacheDir()+"/uvgrid.im");
    1249             :           }
    1250             : 
    1251             :         // cfs2_p->makePersistent(cfCache_p->getCacheDir().c_str());
    1252             :         // cfwts2_p->makePersistent(cfCache_p->getCacheDir().c_str(),"","WT");
    1253             : 
    1254             :         // Save only the CF Cube for the current value of PA (not the
    1255             :         // entire CFStore -- CFs for PA values encountered earlier
    1256             :         // than current value have already need made persistent).
    1257           0 :         cfs2_p->makePersistent(cfCache_p->getCacheDir().c_str(),"","",    Quantity(pa,"rad"),dPAQuant,0,0);
    1258           0 :         cfwts2_p->makePersistent(cfCache_p->getCacheDir().c_str(),"","WT",Quantity(pa,"rad"),dPAQuant,0,0);
    1259           0 :         Double memUsed=cfs2_p->memUsage();
    1260           0 :         String unit(" KB");
    1261           0 :         memUsed = (Int)(memUsed/1024.0+0.5);
    1262           0 :         if (memUsed > 1024) {memUsed /=1024; unit=" MB";}
    1263             :         log_l << "Convolution function memory footprint:" 
    1264             :               << (Int)(memUsed) << unit << " out of a maximum of "
    1265           0 :               << HostInfo::memoryTotal(true)/1024 << " MB" << LogIO::POST;
    1266             :         
    1267             :         //
    1268             :         // Initialize any internal maps that may be used later for
    1269             :         // efficient access.
    1270             :         //
    1271           0 :         cfs2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1272           0 :         cfwts2_p->initMaps(vb,spwFreqSel_p,imRefFreq_p);
    1273             :       }
    1274             : 
    1275             :     // cfs2_p->makePersistent("test.cf");
    1276             :     // cfwts2_p->makePersistent("test.wtcf");
    1277             :   }
    1278             :   //
    1279             :   //------------------------------------------------------------------------------
    1280             :   // Vectorized initializeToVis.  See design related comments in the
    1281             :   // .h file.
    1282             :   //
    1283             :   //
    1284             :   // The functional goals here are:
    1285             :   //
    1286             :   //  1. If doPBCorrection==true (i.e. the input sky-image is flat-sky
    1287             :   //  image), divide the image by the PB
    1288             :   //
    1289             :   //  2. Convert from Stokes to Feed (correlation) frame
    1290             :   //
    1291             :   //  3. FFT the image to produce gridded vis.
    1292             :   //
    1293             :   //  4. And since the same image buffer is used to accumulate the
    1294             :   //  model, multiply the sky-image back with PB
    1295             :   //
    1296             :   // The call to non-vectorized version of initializeToVis() which is
    1297             :   // pure virtual and hence the local version is called, is only to do
    1298             :   // the FFT.  FFT is *NOT* in place.
    1299             :   //
    1300             :   // These operations effecitvely maintains the model image as PB*Sky
    1301             :   // and supplies flat-sky model for prediction.  This can probably be
    1302             :   // achieve with fewer operations and same memory buffers....but that
    1303             :   // for later (SB)
    1304           0 :   void AWProjectFT::initializeToVis(Block<CountedPtr<ImageInterface<Complex> > > & compImageVec,
    1305             :                                     PtrBlock<SubImage<Float> *> & modelImageVec, 
    1306             :                                     PtrBlock<SubImage<Float> *>& weightImageVec, 
    1307             :                                     PtrBlock<SubImage<Float> *>& /*fluxScaleVec*/, 
    1308             :                                     Block<Matrix<Float> >& weightsVec,
    1309             :                                     const VisBuffer& vb)
    1310             :   {
    1311           0 :     LogIO log_p(LogOrigin("AWProjectFT","initToVis[V][R&D]"));
    1312             :     //
    1313             :     // Setting the image below is crucial since init() and
    1314             :     // initMaps(vb) below expect this to be set.
    1315             :     //
    1316           0 :     image=&(*compImageVec[0]);
    1317             : 
    1318             :     log_p << "Total flux in model image (before avgPB normalization): " 
    1319           0 :           << sum((*(modelImageVec[0])).get()) 
    1320             :           // << " predicing SPW = " <<vb.spectralWindow() 
    1321             :           // << " Pointing Offset = " << convFuncCtor_p->findPointingOffset(*(compImageVec[0]), vb)
    1322             :           // << " Qualifier String = " << sensitivityPatternQualifier_p 
    1323           0 :           << LogIO::POST;
    1324           0 :     if(doPBCorrection) 
    1325             :       {
    1326             :         // Make the sensitivity Image if applicable
    1327           0 :         init();
    1328           0 :         initMaps(vb);
    1329           0 :         findConvFunction(*(compImageVec[0]), vb); // Pure virtual -- call local version
    1330             : 
    1331           0 :         if (isDryRun) return;
    1332             : 
    1333             :         // Get the sensitivity Image
    1334           0 :         Matrix<Float> tempWts;
    1335           0 :         tempWts.resize();
    1336           0 :         getWeightImage(*(weightImageVec[0]), tempWts);  // Pure virtual -- call local version
    1337             : 
    1338             :         // Normalize the model image by the sensitivity image only.
    1339             :         // No local implementation -- call FTMachine version
    1340             : 
    1341             :         // Divide by avgPB ///// PBWeight
    1342             :         //
    1343             :         //normalizeImage( *(modelImageVec[0]) , weightsVec[0],  *(weightImageVec[0]), 
    1344             :         //              false, (Float)pbLimit_p, (Int)1);
    1345             : 
    1346             :         //
    1347             :         // Divide by sqrt(avgPB) ////// PBSQWeight
    1348             :         //
    1349           0 :          normalizeImage( *(modelImageVec[0]) , weightsVec[0],  *(weightImageVec[0]), 
    1350           0 :                         false, (Float)pbLimit_p, (Int)4);
    1351             :       }
    1352             :     log_p << "Total flux in model image (after avgPB normalization): " 
    1353           0 :           << sum((*(modelImageVec[0])).get()) << LogIO::POST;
    1354             :     
    1355             :     // Convert from Stokes planes to Correlation planes
    1356             :     // No local implementation -- call FTMachine version
    1357           0 :     stokesToCorrelation(*(modelImageVec[0]), *(compImageVec[0]));
    1358             : 
    1359             :     // Call initializeToVis
    1360           0 :     initializeToVis(*(compImageVec[0]), vb); // Pure virtual
    1361             :     
    1362             :     // Multiply the flat-sky model by the PB.
    1363             :     // No local implementation -- call FTMachine version
    1364           0 :     if(doPBCorrection)
    1365             :       // Multiply by avgPB ///////  PBWeight
    1366             :       //normalizeImage( *(modelImageVec[0]) , weightsVec[0], *(weightImageVec[0]) , false, (Float)pbLimit_p, (Int)3);
    1367             :       
    1368             :       // Multiply by sqrt(avgPB) ///// PBSQWeight
    1369           0 :       normalizeImage( *(modelImageVec[0]) , weightsVec[0], *(weightImageVec[0]) , false, (Float)pbLimit_p, (Int)5);
    1370             :   }
    1371             :   //
    1372             :   //------------------------------------------------------------------------------
    1373             :   //
    1374           0 :   void AWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    1375             :                                     const VisBuffer& vb)
    1376             :   {
    1377           0 :     LogIO log_l(LogOrigin("AWProjectFT", "initializeToVis[R&D]"));
    1378           0 :     image=&iimage;
    1379             :     
    1380           0 :     ok();
    1381             :     
    1382           0 :     init();
    1383           0 :     makingPSF = false;
    1384           0 :     initMaps(vb);
    1385             :     //visResampler_p->setMaps(chanMap, polMap);
    1386             :     
    1387           0 :     findConvFunction(*image, vb);
    1388           0 :     if (isDryRun) return;
    1389             :     //UUU    if (!cfCache_p->avgPBReady() && doPBCorrection)
    1390             :     //UUU  log_l << "Sensitivity pattern not found." << LogIO::EXCEPTION;
    1391             :     //UUU//    if (!cfCache_p->avgPBReady(sensitivityPatternQualifierStr_p) && doPBCorrection)
    1392             :     //UUU//  log_l << "Sensitivity pattern for term " << sensitivityPatternQualifierStr_p << " not found." << LogIO::EXCEPTION;
    1393             : 
    1394             :     //  
    1395             :     // Initialize the maps for polarization and channel. These maps
    1396             :     // translate visibility indices into image indices
    1397             :     //
    1398             : 
    1399           0 :     nx    = image->shape()(0);
    1400           0 :     ny    = image->shape()(1);
    1401           0 :     npol  = image->shape()(2);
    1402           0 :     nchan = image->shape()(3);
    1403             :     
    1404           0 :     if(image->shape().product()>cachesize) isTiled=true;
    1405           0 :     else isTiled=false;
    1406             :     //
    1407             :     // If we are memory-based then read the image in and create an
    1408             :     // ArrayLattice otherwise just use the PagedImage
    1409             :     //
    1410             : 
    1411           0 :     isTiled=false;
    1412             : 
    1413           0 :     if(isTiled){
    1414           0 :         lattice=CountedPtr<Lattice<Complex> > (image, false);
    1415             :     }
    1416             :     else 
    1417             :       {
    1418           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    1419           0 :         griddedData.resize(gridShape);
    1420           0 :         griddedData=Complex(0.0);
    1421             :         
    1422           0 :         IPosition stride(4, 1);
    1423           0 :         IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    1424           0 :                       (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    1425           0 :         IPosition trc(blc+image->shape()-stride);
    1426             :         
    1427           0 :         IPosition start(4, 0);
    1428           0 :         griddedData(blc, trc) = image->getSlice(start, image->shape());
    1429             :         
    1430           0 :         arrayLattice = new ArrayLattice<Complex>(griddedData);
    1431           0 :         lattice=arrayLattice;
    1432             :       }
    1433             : 
    1434             :     //AlwaysAssert(lattice, AipsError);
    1435             :     
    1436           0 :     log_l << LogIO::DEBUGGING << "Starting FFT of image" << LogIO::POST;
    1437             :     
    1438           0 :     Vector<Float> sincConv(nx);
    1439           0 :     Float centerX=nx/2;
    1440           0 :     for (Int ix=0;ix<nx;ix++) 
    1441             :       {
    1442           0 :         Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    1443           0 :         if(ix==centerX) sincConv(ix)=1.0;
    1444           0 :         else            sincConv(ix)=sin(x)/x;
    1445             :       }
    1446             :     
    1447             :     //    Vector<Complex> correction(nx);
    1448             :     //
    1449             :     // Do the Grid-correction
    1450             :     //
    1451             :     //    if(0) //UUU
    1452           0 :     if(cfCache_p->avgPBReady()) //SB
    1453             :     {
    1454             :       //      normalizeAvgPB();
    1455             :       
    1456           0 :       IPosition cursorShape(4, nx, 1, 1, 1);
    1457           0 :       IPosition axisPath(4, 0, 1, 2, 3);
    1458           0 :       LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1459           0 :       LatticeIterator<Complex> lix(*lattice, lsx);
    1460             :           
    1461           0 :       verifyShapes(avgPB_p->shape(), image->shape());
    1462           0 :       Array<Float> avgBuf; avgPB_p->get(avgBuf);
    1463             :       // If the total-power sensitivity pattern peak is too low, warn
    1464             :       // the user.  This usually is indicative of a rat somewhere in
    1465             :       // the pipes upstream...
    1466           0 :       if ((sensitivityPatternQualifier_p==0) && (max(avgBuf) < 1e-04))
    1467             :         log_l << "Normalization by PB requested but either PB was not"
    1468             :               <<" found in the cache or is ill-formed. Peak = "
    1469           0 :               << max(avgBuf)// << " " << sensitivityPatternQualifier_p
    1470           0 :               << LogIO::WARN << LogIO::POST;
    1471             :           
    1472             : 
    1473           0 :       LatticeStepper lpb(avgPB_p->shape(),cursorShape,axisPath);
    1474           0 :       LatticeIterator<Float> lipb(*avgPB_p, lpb);
    1475             : 
    1476           0 :       Vector<Complex> griddedVis;
    1477             :       //
    1478             :       // Grid correct in anticipation of the convolution by the
    1479             :       // convFunc.  Each polarization plane is corrected by the
    1480             :       // appropraite primary beam.
    1481             :       //
    1482           0 :       for(lix.reset(),lipb.reset();!lix.atEnd();lix++,lipb++) 
    1483             :         {
    1484           0 :           Int iy=lix.position()(1);
    1485             :           //      gridder->correctX1D(correction,iy);
    1486           0 :           griddedVis = lix.rwVectorCursor();
    1487             :           
    1488           0 :           Vector<Float> PBCorrection(lipb.rwVectorCursor().shape());
    1489           0 :           PBCorrection = lipb.rwVectorCursor();
    1490           0 :           for(int ix=0;ix<nx;ix++) 
    1491             :             {
    1492           0 :               if (doPBCorrection)
    1493             :                 {
    1494           0 :                   PBCorrection(ix) = pbFunc(PBCorrection(ix),pbLimit_p)*(sincConv(ix)*sincConv(iy));
    1495           0 :                   lix.rwVectorCursor()(ix) /= (PBCorrection(ix));
    1496             :                 }
    1497             :               else 
    1498           0 :                 lix.rwVectorCursor()(ix) /= (1.0/(sincConv(ix)*sincConv(iy)));
    1499             :             }
    1500             :         }
    1501             :     }
    1502             :     //
    1503             :     // Now do the FFT2D in place
    1504             :     //
    1505             : 
    1506             :     //    storeImg(String("img.before.mod"), *image);
    1507           0 :     LatticeFFT::cfft2d(*lattice);
    1508             :     //    storeImg(String("img.after.mod"), *image);
    1509             : 
    1510           0 :     log_l << LogIO::DEBUGGING << "Finished FFT" << LogIO::POST;
    1511             :   }
    1512             :   //
    1513             :   //---------------------------------------------------------------
    1514             :   //
    1515           0 :   void AWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    1516             :                                      const VisBuffer& vb,
    1517             :                                      Array<Complex>& griddedVis,
    1518             :                                      Vector<Double>& uvscale)
    1519             :   {
    1520           0 :     initializeToVis(iimage, vb);
    1521           0 :     griddedVis.assign(griddedData); //using the copy for storage
    1522           0 :     uvscale.assign(uvScale);
    1523           0 :   }
    1524             :   //
    1525             :   //---------------------------------------------------------------
    1526             :   //
    1527           0 :   void AWProjectFT::finalizeToVis()
    1528             :   {
    1529           0 :     LogIO log_l(LogOrigin("AWProjectFT", "finalizeToVis[R&D]"));
    1530             :     
    1531             :     //    cerr << "De-gridding run time = " << visResampler_p->runTimeDG_p << endl;
    1532           0 :     visResampler_p->runTimeDG_p=0.0;
    1533             : 
    1534           0 :   if(!arrayLattice.null()) arrayLattice=0;
    1535           0 :   if(!lattice.null()) lattice=0;
    1536           0 :   griddedData.resize();
    1537             : 
    1538           0 :     if(isTiled) 
    1539             :       {
    1540           0 :         AlwaysAssert(imageCache, AipsError);
    1541           0 :         AlwaysAssert(image, AipsError);
    1542           0 :         ostringstream o;
    1543           0 :         imageCache->flush();
    1544           0 :         imageCache->showCacheStatistics(o);
    1545           0 :         log_l << o.str() << LogIO::POST;
    1546             :       }
    1547           0 :     if(pointingToImage) delete pointingToImage; pointingToImage=0;
    1548           0 :   }
    1549             :   //
    1550             :   //---------------------------------------------------------------
    1551             :   //
    1552             :   // Initialize the FFT to the Sky. Here we have to setup and
    1553             :   // initialize the grid.
    1554             :   //
    1555           0 :   void AWProjectFT::initializeToSky(ImageInterface<Complex>& iimage,
    1556             :                                      Matrix<Float>& weight,
    1557             :                                      const VisBuffer& vb)
    1558             :   {
    1559           0 :     LogIO log_l(LogOrigin("AWProjectFT", "initializeToSky[R&D]"));
    1560             :     
    1561             :     // image always points to the image
    1562           0 :     image=&iimage;
    1563             :     
    1564           0 :     init();
    1565           0 :     initMaps(vb);
    1566           0 :     visResampler_p->setMaps(chanMap, polMap);
    1567           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    1568             :     
    1569             :     // Initialize the maps for polarization and channel. These maps
    1570             :     // translate visibility indices into image indices
    1571             :     
    1572           0 :     nx    = image->shape()(0);
    1573           0 :     ny    = image->shape()(1);
    1574           0 :     npol  = image->shape()(2);
    1575           0 :     nchan = image->shape()(3);
    1576             :     
    1577           0 :     if(image->shape().product()>cachesize) isTiled=true;
    1578           0 :     else                                   isTiled=false;
    1579             :     
    1580           0 :     sumWeight=0.0;
    1581           0 :     sumCFWeight = 0.0;
    1582           0 :     weight.resize(sumWeight.shape());
    1583           0 :     weight=0.0;
    1584             :     //
    1585             :     // Initialize for in memory or to disk gridding. lattice will
    1586             :     // point to the appropriate Lattice, either the ArrayLattice for
    1587             :     // in memory gridding or to the image for to disk gridding.
    1588             :     //
    1589           0 :     if(isTiled) 
    1590             :       {
    1591           0 :         imageCache->flush();
    1592           0 :         image->set(Complex(0.0));
    1593           0 :         lattice=CountedPtr<Lattice<Complex> > (image, false);
    1594             :       }
    1595             :     else 
    1596             :       {
    1597           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    1598           0 :         if(!useDoubleGrid_p){
    1599           0 :         griddedData.resize(gridShape);
    1600           0 :         griddedData=Complex(0.0); 
    1601             :         }
    1602             :         //      arrayLattice = new ArrayLattice<Complex>(griddedData);
    1603             :         //      lattice=arrayLattice;
    1604             :         else      {
    1605             :           //griddedData.resize();
    1606           0 :           griddedData2.resize(gridShape);
    1607           0 :           griddedData2=DComplex(0.0);
    1608             :         }
    1609             :       }
    1610             : 
    1611             :     //cerr << "initializeToSky for grid" << endl;
    1612           0 :     if(useDoubleGrid_p) 
    1613           0 :       visResampler_p->initializeToSky(griddedData2, sumWeight);
    1614             :     else
    1615           0 :       visResampler_p->initializeToSky(griddedData, sumWeight);
    1616           0 :   }
    1617             :   //
    1618             :   //---------------------------------------------------------------
    1619             :   //
    1620           0 :   void AWProjectFT::finalizeToSky()
    1621             :   {
    1622             :     //
    1623             :     // Now we flush the cache and report statistics For memory based,
    1624             :     // we don't write anything out yet.
    1625             :     //
    1626           0 :     LogIO log_l(LogOrigin("AWProjectFT", "finalizeToSky[R&D]"));
    1627             : 
    1628           0 :     if(isTiled) 
    1629             :       {
    1630           0 :         AlwaysAssert(image, AipsError);
    1631           0 :         AlwaysAssert(imageCache, AipsError);
    1632           0 :         imageCache->flush();
    1633           0 :         ostringstream o;
    1634           0 :         imageCache->showCacheStatistics(o);
    1635           0 :         log_l << o.str() << LogIO::POST;
    1636             :       }
    1637           0 :     if(pointingToImage) delete pointingToImage; pointingToImage=0;
    1638             : 
    1639           0 :     paChangeDetector.reset();
    1640           0 :     cfCache_p->flush();
    1641           0 :     if(useDoubleGrid_p) 
    1642           0 :       visResampler_p->finalizeToSky(griddedData2, sumWeight);
    1643             :     else
    1644           0 :       visResampler_p->finalizeToSky(griddedData, sumWeight);
    1645           0 :   }
    1646             :   //
    1647             :   //---------------------------------------------------------------
    1648             :   //
    1649           0 :   Array<Complex>* AWProjectFT::getDataPointer(const IPosition& centerLoc2D,
    1650             :                                                Bool readonly) 
    1651             :   {
    1652             :     Array<Complex>* result;
    1653             :     // Is tiled: get tiles and set up offsets
    1654           0 :     centerLoc(0)=centerLoc2D(0);
    1655           0 :     centerLoc(1)=centerLoc2D(1);
    1656           0 :     result=&imageCache->tile(offsetLoc, centerLoc, readonly);
    1657           0 :     gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    1658           0 :     return result;
    1659             :   }
    1660             :   
    1661             :   // The following file has the runFORTRAN* stuff. Moving it to a
    1662             :   // separate file to reduce clutter and ultimately delete it.
    1663             : #include "AWProjectFT.FORTRANSTUFF"
    1664             :   //
    1665             :   //---------------------------------------------------------------
    1666             :   //
    1667           0 :   void AWProjectFT::put(const VisBuffer& vb, Int row, Bool dopsf,
    1668             :                         FTMachine::Type type)
    1669             :   {
    1670           0 :     LogIO log_l(LogOrigin("AWProjectFT", "put[R&D]"));
    1671             :     // Take care of translation of Bools to Integer
    1672           0 :     makingPSF=dopsf;
    1673             :     
    1674             :     try
    1675             :       {
    1676           0 :         findConvFunction(*image, vb);
    1677             :       }
    1678           0 :     catch(AipsError& x)
    1679             :       {
    1680           0 :         log_l << x.getMesg() << LogIO::WARN;
    1681           0 :         return;
    1682             :       }
    1683           0 :     if (isDryRun) return;
    1684             : 
    1685           0 :     Nant_p     = vb.msColumns().antenna().nrow();
    1686             : 
    1687             :     const Matrix<Float> *imagingweight;
    1688           0 :     imagingweight=&(vb.imagingWeight());
    1689             : 
    1690           0 :     Cube<Complex> data;
    1691             :     //Fortran gridder need the flag as ints 
    1692           0 :     Cube<Int> flags;
    1693           0 :     Matrix<Float> elWeight;
    1694           0 :     interpolateFrequencyTogrid(vb, *imagingweight,data, flags, elWeight, type);
    1695             :     // NAnt no longer appears to be used
    1696             :     //Int NAnt;
    1697             :     //if (doPointing) NAnt = findPointingOffsets(vb,l_offsets,m_offsets,true);
    1698             :     //NAnt=NAnt;  // Dummy statement to supress complier warnings and will be used when pointing offsets are used.
    1699             :     //
    1700             :     // If row is -1 then we pass through all rows
    1701             :     //
    1702             :     Int startRow, endRow, nRow;
    1703           0 :     if (row==-1) 
    1704             :       {
    1705           0 :         nRow=vb.nRow();
    1706           0 :         startRow=0;
    1707           0 :         endRow=nRow-1;
    1708             :       } 
    1709             :     else 
    1710             :       {
    1711           0 :         nRow=1;
    1712           0 :         startRow=row;
    1713           0 :         endRow=row;
    1714             :       }
    1715             :     //    
    1716             :     // Get the uvws in a form that Fortran can use and do that
    1717             :     // necessary phase rotation. On a Pentium Pro 200 MHz when null,
    1718             :     // this step takes about 50us per uvw point. This is just barely
    1719             :     // noticeable for Stokes I continuum and irrelevant for other
    1720             :     // cases.
    1721             :     //
    1722           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    1723           0 :     uvw=0.0;
    1724           0 :     Vector<Double> dphase(vb.uvw().nelements());
    1725           0 :     dphase=0.0;
    1726             :     //NEGATING to correct for an image inversion problem
    1727           0 :     for (Int i=startRow;i<=endRow;i++) 
    1728             :       {
    1729           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    1730           0 :         uvw(2,i)=vb.uvw()(i)(2);
    1731             :       }
    1732             :     
    1733           0 :     doUVWRotation_p=true;
    1734             :     //rotateUVW(uvw, dphase, vb);
    1735           0 :     girarUVW(uvw, dphase, vb);
    1736           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    1737             :     
    1738             :     // // This is the convention for dphase
    1739             :     // dphase*=-1.0;
    1740             : 
    1741             :     //Check if ms has changed then cache new spw and chan selection
    1742           0 :     if(vb.newMS())
    1743           0 :       matchAllSpwChans(vb);  
    1744             :     
    1745             :     //Here we redo the match or use previous match
    1746             :     
    1747             :     //Channel matching for the actual spectral window of buffer
    1748           0 :     if(doConversion_p[vb.spectralWindow()])
    1749           0 :       matchChannel(vb.spectralWindow(), vb);
    1750             :     else
    1751             :       {
    1752           0 :         chanMap.resize();
    1753           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    1754             :       }
    1755             : 
    1756           0 :     VBStore vbs;
    1757           0 :     Vector<Int> gridShape = griddedData2.shape().asVector();
    1758           0 :     setupVBStore(vbs,vb, elWeight,data,uvw,flags, dphase,dopsf,gridShape);
    1759             : 
    1760           0 :     if (useDoubleGrid_p)
    1761             :       {
    1762           0 :         resampleDataToGrid(griddedData2, vbs, vb, dopsf);//, *imagingweight, *data, uvw,flags,dphase,dopsf);
    1763             :         //if (!dopsf) storeArrayAsImage(String("cgrid_awp_d.im"), image->coordinates(), griddedData2);
    1764             :       }
    1765             :     else
    1766             :       {
    1767           0 :         resampleDataToGrid(griddedData, vbs, vb, dopsf);//, *imagingweight, *data, uvw,flags,dphase,dopsf);
    1768             :         // String msg("WTH");
    1769             :         // isVBNaN(vb,msg);
    1770             :         //if (!dopsf) storeArrayAsImage(String("cgrid_awp_s.im"), image->coordinates(), griddedData);
    1771             :       }
    1772             :   }
    1773             :   //
    1774             :   //-------------------------------------------------------------------------
    1775             :   // Gridding
    1776           0 :   void AWProjectFT::resampleDataToGrid(Array<Complex>& griddedData_l, VBStore& vbs, 
    1777             :                                        const VisBuffer& /*vb*/, Bool& dopsf)
    1778             :   {
    1779           0 :     LogIO log_l(LogOrigin("AWProjectFT", "resampleDataToGrid[R&D]"));
    1780           0 :     visResampler_p->DataToGrid(griddedData_l, vbs, sumWeight, dopsf); 
    1781             :     //    cerr << "####SumWt(C): " << sumWeight << endl;
    1782           0 :   }
    1783             :   //
    1784             :   //-------------------------------------------------------------------------
    1785             :   // Gridding
    1786           0 :   void AWProjectFT::resampleDataToGrid(Array<DComplex>& griddedData_l, VBStore& vbs, 
    1787             :                                        const VisBuffer& /*vb*/, Bool& dopsf)
    1788             :   {
    1789           0 :     LogIO log_l(LogOrigin("AWProjectFT", "resampleDataToGridD[R&D]"));
    1790           0 :     visResampler_p->DataToGrid(griddedData_l, vbs, sumWeight, dopsf); 
    1791             :     //    cerr << "####SumWt(DC): " << sumWeight << endl;
    1792           0 :   }
    1793             :   //
    1794             :   //---------------------------------------------------------------
    1795             :   //
    1796           0 :   void AWProjectFT::get(VisBuffer& vb, Int row)
    1797             :   {
    1798           0 :     LogIO log_l(LogOrigin("AWProjectFT", "get[R&D]"));
    1799             :     // If row is -1 then we pass through all rows
    1800             : 
    1801             :     //------COMMON FROM HERE
    1802             :     Int startRow, endRow, nRow;
    1803           0 :     if (row==-1) 
    1804             :       {
    1805           0 :         nRow=vb.nRow();
    1806           0 :         startRow=0;
    1807           0 :         endRow=nRow-1;
    1808           0 :         vb.modelVisCube()=Complex(0.0,0.0);
    1809             :       }
    1810             :     else 
    1811             :       {
    1812           0 :         nRow=1;
    1813           0 :         startRow=row;
    1814           0 :         endRow=row;
    1815           0 :         vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
    1816             :       }
    1817             :     
    1818           0 :     findConvFunction(*image, vb);
    1819             :     
    1820           0 :     Nant_p     = vb.msColumns().antenna().nrow();
    1821             :     // NAnt set but not used
    1822             :     //Int NAnt=0;
    1823             :     //if (doPointing)   NAnt = findPointingOffsets(vb,l_offsets,m_offsets,true);
    1824             :     
    1825             :     // Get the uvws in a form that Fortran can use
    1826           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    1827           0 :     uvw=0.0;
    1828           0 :     Vector<Double> dphase(vb.uvw().nelements());
    1829           0 :     dphase=0.0;
    1830             :     //NEGATING to correct for an image inversion problem
    1831           0 :     for (Int i=startRow;i<=endRow;i++) 
    1832             :       {
    1833           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    1834           0 :         uvw(2,i)=vb.uvw()(i)(2);
    1835             :       }
    1836             : 
    1837           0 :     doUVWRotation_p=true;
    1838             :     //rotateUVW(uvw, dphase, vb);
    1839           0 :     girarUVW(uvw, dphase, vb);
    1840           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    1841             :     
    1842             :     // This is the convention for dphase
    1843             :     //    dphase*=-1.0;
    1844             :     
    1845             :     //Check if ms has changed then cache new spw and chan selection
    1846           0 :     if(vb.newMS())
    1847           0 :       matchAllSpwChans(vb);
    1848             :     
    1849             :     //Here we redo the match or use previous match
    1850             :     //
    1851             :     //Channel matching for the actual spectral window of buffer
    1852             :     //
    1853           0 :     if(doConversion_p[vb.spectralWindow()])
    1854           0 :       matchChannel(vb.spectralWindow(), vb);
    1855             :     else
    1856             :       {
    1857           0 :         chanMap.resize();
    1858           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    1859             :       }
    1860             :     //No point in reading data if its not matching in frequency
    1861           0 :     if(max(chanMap)==-1) return;
    1862             :     //-----COMMONG TILL HERE
    1863             :     
    1864             :     // Cube<Int> flags(vb.flagCube().shape());
    1865             :     // flags=0;
    1866             :     // flags(vb.flagCube())=true;
    1867             : 
    1868           0 :     Cube<Complex> data;
    1869           0 :     Cube<Int> flags;
    1870           0 :     getInterpolateArrays(vb, data, flags);
    1871             : 
    1872           0 :     VBStore vbs;
    1873             :     //    setupVBStore(vbs,vb, vb.imagingWeight(),vb.modelVisCube(),uvw,flags, dphase, dopsf);
    1874           0 :     Bool tmpDoPSF=false;
    1875             : 
    1876           0 :     setupVBStore(vbs,vb, vb.imagingWeight(),data,uvw,flags, dphase,tmpDoPSF,griddedData.shape().asVector());
    1877             : 
    1878             :       // visResampler_p->setParams(uvScale,uvOffset,dphase);
    1879             :       // visResampler_p->setMaps(chanMap, polMap);
    1880           0 :     resampleGridToData(vbs, griddedData, vb);//, uvw, flags, dphase);
    1881             : 
    1882             :       // De-gridding
    1883             :       //      visResampler_p->GridToData(vbs, griddedData);
    1884             : 
    1885             : 
    1886           0 :     interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
    1887             :   }
    1888             :   //
    1889             :   //-------------------------------------------------------------------------
    1890             :   // De-gridding
    1891           0 :   void AWProjectFT::resampleGridToData(VBStore& vbs, Array<Complex>& griddedData_l,
    1892             :                                        const VisBuffer& /*vb*/)
    1893             :   {
    1894           0 :     LogIO log_l(LogOrigin("AWProjectFT", "resampleGridToData[R&D]"));
    1895             :     //    Timer tim;
    1896             :     //    tim.mark();
    1897           0 :     visResampler_p->GridToData(vbs, griddedData_l);
    1898             :     //    runTime+=tim.user();
    1899           0 :   }
    1900             :   //
    1901             :   //---------------------------------------------------------------
    1902             :   //
    1903             :   // Finalize the FFT to the Sky. Here we actually do the FFT and
    1904             :   // return the resulting image
    1905           0 :   ImageInterface<Complex>& AWProjectFT::getImage(Matrix<Float>& weights,
    1906             :                                                   Bool fftNormalization) 
    1907             :   {
    1908           0 :     LogIO log_l(LogOrigin("AWProjectFT", "getImage[R&D]"));
    1909             :     //
    1910             :     // There are three objects held by the FTMachine objects: (1)
    1911             :     // *image, (2) *lattice, and (3) griddedData.
    1912             :     //
    1913             :     // (1) is the Dirty Image (ImageInterface<Float>)
    1914             :     //
    1915             :     // (2) is the Lattice of the Dirty Image (Lattice<Float>)
    1916             :     //
    1917             :     // (3) appears to be a reference to (2).  Since FFT of *lattice is
    1918             :     // done in place, griddedData (and *lattice) have the gridded data
    1919             :     // in them before, and the Dirty Image data after the FFT.
    1920             :     //
    1921             :     // Question: Why three objects for the same precise information?
    1922             :     // --SB (Dec. 2010).
    1923           0 :     AlwaysAssert(image, AipsError);
    1924             : 
    1925           0 :     weights.resize(sumWeight.shape());
    1926           0 :     convertArray(weights, sumWeight);
    1927             : 
    1928             :     //  
    1929             :     // If the weights are all zero then we cannot normalize otherwise
    1930             :     // we don't care.
    1931             :     //
    1932           0 :     if(max(weights)==0.0) 
    1933             :       log_l // UUU //<< LogIO::SEVERE
    1934           0 :             << "No useful data in " << name() << ".  Weights all zero"
    1935           0 :             << LogIO::POST;
    1936             :     // UUU else
    1937             :       {
    1938             :         log_l << LogIO::DEBUGGING
    1939           0 :                 << "Starting FFT and scaling of image" << LogIO::POST;
    1940             :         //    
    1941             :         // x and y transforms (lattice has the gridded vis.  Make the
    1942             :         // dirty images)
    1943             :         //
    1944           0 :         if (useDoubleGrid_p)
    1945             :           {
    1946           0 :             ArrayLattice<DComplex> darrayLattice(griddedData2);
    1947           0 :             LatticeFFT::cfft2d(darrayLattice,false);
    1948           0 :             griddedData.resize(griddedData2.shape());
    1949           0 :             convertArray(griddedData, griddedData2);
    1950           0 :             SynthesisUtilMethods::getResource("mem peak in getImage");
    1951             :         
    1952             :             //Don't need the double-prec grid anymore...
    1953           0 :             griddedData2.resize();
    1954           0 :             arrayLattice = new ArrayLattice<Complex>(griddedData);
    1955           0 :             lattice=arrayLattice;
    1956             :           }
    1957             :         else
    1958             :           {
    1959           0 :             arrayLattice = new ArrayLattice<Complex>(griddedData);
    1960             :             //cerr << "##### " << griddedData2.shape() << endl;
    1961             :             //if (!makingPSF) storeArrayAsImage(String("cgrid_awp.im"), image->coordinates(), griddedData);
    1962           0 :             lattice=arrayLattice;
    1963           0 :             LatticeFFT::cfft2d(*lattice,false);
    1964             :           }
    1965           0 :         const IPosition latticeShape = lattice->shape();
    1966             :         //
    1967             :         // Now normalize the dirty image.
    1968             :         //
    1969             :         // Since *lattice is not copied to *image till the end of this
    1970             :         // method, normalizeImage also needs to work with Lattices
    1971             :         // (rather than ImageInterface).
    1972             :         //
    1973             :         // //normalizeImage(*lattice,sumWeight,*avgPB_p,fftNormalization);
    1974             :         //      normalizeImage(*lattice,sumWeight,*avgPB_p, *avgPBSq_p, fftNormalization);
    1975             :         //if (!makingPSF) storeImg(String("uvgrid0.im"), *image);
    1976             : 
    1977             :         // nx ny normalization from GridFT...
    1978             :         {
    1979           0 :           Int inx = lattice->shape()(0);
    1980           0 :           Int iny = lattice->shape()(1);
    1981           0 :           Vector<Complex> correction(inx);
    1982           0 :           correction=Complex(1.0, 0.0);
    1983             :           // Do the Grid-correction
    1984           0 :           IPosition cursorShape(4, inx, 1, 1, 1);
    1985           0 :           IPosition axisPath(4, 0, 1, 2, 3);
    1986           0 :           LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1987           0 :           LatticeIterator<Complex> lix(*lattice, lsx);
    1988           0 :           for(lix.reset();!lix.atEnd();lix++) 
    1989             :             {
    1990           0 :               Int pol=lix.position()(2);
    1991           0 :               Int chan=lix.position()(3);
    1992             :               {
    1993           0 :                 if(fftNormalization) 
    1994             :                   {
    1995           0 :                     if(weights(pol,chan)!=0.0)
    1996             :                       {
    1997           0 :                         Complex rnorm(Float(inx)*Float(iny)/( weights(pol,chan) ));
    1998           0 :                         lix.rwCursor()*=rnorm;
    1999             :                       }
    2000             :                     else
    2001           0 :                       lix.woCursor()=0.0;
    2002             :                   }
    2003             :                 else 
    2004             :                   {
    2005           0 :                     Complex rnorm(Float(inx)*Float(iny));
    2006           0 :                     lix.rwCursor()*=rnorm;
    2007             :                   }
    2008             :               }
    2009             :             }
    2010             :         }
    2011             :         //if (!makingPSF) storeImg(String("uvgrid.im"), *image);
    2012           0 :         if(!isTiled) 
    2013             :           {
    2014             :             //
    2015             :             // Check the section from the image BEFORE converting to a lattice 
    2016             :             //
    2017           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    2018           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    2019           0 :             IPosition stride(4, 1);
    2020           0 :             IPosition trc(blc+image->shape()-stride);
    2021             :             //
    2022             :             // Do the copy
    2023             :             //
    2024           0 :             image->put(griddedData(blc, trc));
    2025             :             
    2026             : 
    2027           0 :             if(!arrayLattice.null()) arrayLattice=0;
    2028           0 :             if(!lattice.null()) lattice=0;
    2029           0 :             griddedData.resize(IPosition(1,0));
    2030             :           }
    2031             :       }
    2032             : 
    2033             :     // {
    2034             :     //   // TempImage<Complex> tt(lattice->shape(), image->coordinates());
    2035             :     //   // tt.put(lattice->get());
    2036             :       //      if (!makingPSF) throw(AipsError("Exiting from AWP.cc: 1765"));
    2037             : 
    2038             :     // }
    2039             : 
    2040           0 :     return *image;
    2041             :   }
    2042             :   //
    2043             :   //---------------------------------------------------------------
    2044             :   //
    2045             :   // Get weight image
    2046           0 :   void AWProjectFT::getWeightImage(ImageInterface<Float>& weightImage,
    2047             :                                    Matrix<Float>& weights) 
    2048             :   {
    2049           0 :     LogIO log_l(LogOrigin("AWProjectFT", "getWeightImage[R&D]"));
    2050             :     
    2051           0 :     weights.resize(sumWeight.shape());
    2052           0 :     convertArray(weights,sumWeight);
    2053             :     
    2054           0 :     const IPosition latticeShape = weightImage.shape();
    2055           0 :     const IPosition avgpbShape = avgPB_p->shape();
    2056             :     //    cout << "AWP::getWeightImage : weightimage shape : " << latticeShape << "  and avgpb shape : " << avgpbShape << " " << sumWeight << endl;
    2057             :     
    2058           0 :     Int nx=latticeShape(0);
    2059           0 :     Int ny=latticeShape(1);
    2060             :     
    2061           0 :     IPosition loc(2, 0);
    2062           0 :     IPosition cursorShape(4, nx, ny, 1, 1);
    2063           0 :     IPosition axisPath(4, 0, 1, 2, 3);
    2064           0 :     LatticeStepper lsx(latticeShape, cursorShape, axisPath);
    2065           0 :     LatticeIterator<Float> lix(weightImage, lsx);
    2066           0 :     LatticeIterator<Float> liy(*avgPB_p,lsx);
    2067           0 :     for(lix.reset();!lix.atEnd();lix++) 
    2068             :       {
    2069             :         //Int pol=lix.position()(2);
    2070             :         //Int chan=lix.position()(3);
    2071             :         //lix.rwCursor()=weights(pol,chan);
    2072           0 :         lix.rwCursor()=liy.rwCursor();
    2073             :       }
    2074           0 :   }
    2075             :   //
    2076             :   //---------------------------------------------------------------
    2077             :   //
    2078           0 :   Bool AWProjectFT::toRecord(RecordInterface& outRec, Bool withImage) 
    2079             :   {
    2080           0 :     LogIO log_l(LogOrigin("AWProjectFT", "toRecord[R&D]"));
    2081             :     
    2082             :     // Save the current AWProjectFT object to an output state record
    2083           0 :     Bool retval = true;
    2084           0 :     Double cacheVal=(Double) cachesize;
    2085           0 :     outRec.define("cache", cacheVal);
    2086           0 :     outRec.define("tile", tilesize);
    2087             :     
    2088           0 :     Vector<Double> phaseValue(2);
    2089           0 :     String phaseUnit;
    2090           0 :     phaseValue=mTangent_p.getAngle().getValue();
    2091           0 :     phaseUnit= mTangent_p.getAngle().getUnit();
    2092           0 :     outRec.define("phasevalue", phaseValue);
    2093           0 :     outRec.define("phaseunit", phaseUnit);
    2094             :     
    2095           0 :     Vector<Double> dirValue(3);
    2096           0 :     String dirUnit;
    2097           0 :     dirValue=mLocation_p.get("m").getValue();
    2098           0 :     dirUnit=mLocation_p.get("m").getUnit();
    2099           0 :     outRec.define("dirvalue", dirValue);
    2100           0 :     outRec.define("dirunit", dirUnit);
    2101             :     
    2102           0 :     outRec.define("padding", padding_p);
    2103           0 :     outRec.define("maxdataval", maxAbsData);
    2104             :     
    2105           0 :     Vector<Int> center_loc(4), offset_loc(4);
    2106           0 :     for (Int k=0; k<4 ; k++)
    2107             :       {
    2108           0 :         center_loc(k)=centerLoc(k);
    2109           0 :         offset_loc(k)=offsetLoc(k);
    2110             :       }
    2111           0 :     outRec.define("centerloc", center_loc);
    2112           0 :     outRec.define("offsetloc", offset_loc);
    2113           0 :     outRec.define("sumofweights", sumWeight);
    2114           0 :     outRec.define("sumofcfweights", sumCFWeight);
    2115           0 :     if(withImage && image)
    2116             :       { 
    2117           0 :         ImageInterface<Complex>& tempimage(*image);
    2118           0 :         Record imageContainer;
    2119           0 :         String error;
    2120           0 :         retval = (retval || tempimage.toRecord(error, imageContainer));
    2121           0 :         outRec.defineRecord("image", imageContainer);
    2122             :       }
    2123           0 :     return retval;
    2124             :   }
    2125             :   //
    2126             :   //---------------------------------------------------------------
    2127             :   //
    2128           0 :   Bool AWProjectFT::fromRecord(const RecordInterface& inRec)
    2129             :   {
    2130           0 :     LogIO log_l(LogOrigin("AWProjectFT", "fromRecord[R&D]"));
    2131             : 
    2132           0 :     Bool retval = true;
    2133           0 :     imageCache=0; lattice=0; arrayLattice=0;
    2134             :     Double cacheVal;
    2135           0 :     inRec.get("cache", cacheVal);
    2136           0 :     cachesize=(Long) cacheVal;
    2137           0 :     inRec.get("tile", tilesize);
    2138             :     
    2139           0 :     Vector<Double> phaseValue(2);
    2140           0 :     inRec.get("phasevalue",phaseValue);
    2141           0 :     String phaseUnit;
    2142           0 :     inRec.get("phaseunit",phaseUnit);
    2143           0 :     Quantity val1(phaseValue(0), phaseUnit);
    2144           0 :     Quantity val2(phaseValue(1), phaseUnit); 
    2145           0 :     MDirection phasecenter(val1, val2);
    2146             :     
    2147           0 :     mTangent_p=phasecenter;
    2148             :     // This should be passed down too but the tangent plane is 
    2149             :     // expected to be specified in all meaningful cases.
    2150           0 :     tangentSpecified_p=true;  
    2151           0 :     Vector<Double> dirValue(3);
    2152           0 :     String dirUnit;
    2153           0 :     inRec.get("dirvalue", dirValue);
    2154           0 :     inRec.get("dirunit", dirUnit);
    2155           0 :     MVPosition dummyMVPos(dirValue(0), dirValue(1), dirValue(2));
    2156           0 :     MPosition mLocation(dummyMVPos, MPosition::ITRF);
    2157           0 :     mLocation_p=mLocation;
    2158             :     
    2159           0 :     inRec.get("padding", padding_p);
    2160           0 :     inRec.get("maxdataval", maxAbsData);
    2161             :     
    2162           0 :     Vector<Int> center_loc(4), offset_loc(4);
    2163           0 :     inRec.get("centerloc", center_loc);
    2164           0 :     inRec.get("offsetloc", offset_loc);
    2165           0 :     uInt ndim4 = 4;
    2166           0 :     centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2), 
    2167           0 :                         center_loc(3));
    2168           0 :     offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2), 
    2169           0 :                         offset_loc(3));
    2170           0 :     inRec.get("sumofweights", sumWeight);
    2171           0 :     inRec.get("sumofcfweights", sumCFWeight);
    2172           0 :     if(inRec.nfields() > 12 )
    2173             :       {
    2174           0 :         Record imageAsRec=inRec.asRecord("image");
    2175           0 :         if(!image) image= new TempImage<Complex>(); 
    2176             :         
    2177           0 :         String error;
    2178           0 :         retval = (retval || image->fromRecord(error, imageAsRec));    
    2179             :         
    2180             :         // Might be changing the shape of sumWeight
    2181           0 :         init(); 
    2182             :         
    2183           0 :         if(isTiled) 
    2184           0 :           lattice=CountedPtr<Lattice<Complex> > (image, false);
    2185             :         else 
    2186             :           {
    2187             :             //
    2188             :             // Make the grid the correct shape and turn it into an
    2189             :             // array lattice Check the section from the image BEFORE
    2190             :             // converting to a lattice
    2191             :             //
    2192           0 :             IPosition gridShape(4, nx, ny, npol, nchan);
    2193           0 :             griddedData.resize(gridShape);
    2194           0 :             griddedData=Complex(0.0);
    2195           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    2196           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    2197           0 :             IPosition start(4, 0);
    2198           0 :             IPosition stride(4, 1);
    2199           0 :             IPosition trc(blc+image->shape()-stride);
    2200           0 :             griddedData(blc, trc) = image->getSlice(start, image->shape());
    2201             :             
    2202           0 :             arrayLattice = new ArrayLattice<Complex>(griddedData);
    2203           0 :             lattice=arrayLattice;
    2204             :           }
    2205             :         
    2206           0 :         AlwaysAssert(image, AipsError);
    2207             :       };
    2208           0 :     return retval;
    2209             :   }
    2210             :   //
    2211             :   //---------------------------------------------------------------
    2212             :   //
    2213           0 :   void AWProjectFT::ok() 
    2214             :   {
    2215           0 :     AlwaysAssert(image, AipsError);
    2216           0 :   }
    2217             :   //----------------------------------------------------------------------
    2218             :   //
    2219             :   // Make a straightforward 2D interferometry honest-to-god
    2220             :   // image. This returns a complex image, without conversion to
    2221             :   // Stokes. The polarization representation is that required for the
    2222             :   // visibilities.
    2223             :   //
    2224           0 :   void AWProjectFT::makeImage(FTMachine::Type type, 
    2225             :                               VisSet& vs,
    2226             :                               ImageInterface<Complex>& theImage,
    2227             :                               Matrix<Float>& weight) 
    2228             :   {
    2229           0 :     LogIO log_l(LogOrigin("AWProjectFT", "makeImage[R&D]"));
    2230             :     
    2231           0 :     if(type==FTMachine::COVERAGE) 
    2232             :       log_l << "Type COVERAGE not defined for Fourier transforms"
    2233           0 :             << LogIO::EXCEPTION;
    2234             :     
    2235             :     
    2236             :     // Initialize the gradients
    2237           0 :     ROVisIter& vi(vs.iter());
    2238             :     
    2239             :     // Loop over all visibilities and pixels
    2240           0 :     VisBuffer vb(vi);
    2241             :     
    2242             :     // Initialize put (i.e. transform to Sky) for this model
    2243           0 :     vi.origin();
    2244             :     
    2245           0 :     if(vb.polFrame()==MSIter::Linear) 
    2246           0 :       StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::LINEAR);
    2247             :     else 
    2248           0 :       StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::CIRCULAR);
    2249             :     
    2250           0 :     initializeToSky(theImage,weight,vb);
    2251             : 
    2252             :     //    
    2253             :     // Loop over the visibilities, putting VisBuffers
    2254             :     //
    2255           0 :     paChangeDetector.reset();
    2256             : 
    2257           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) 
    2258             :       {
    2259           0 :         for (vi.origin(); vi.more(); vi++) 
    2260             :           {
    2261           0 :             if (type==FTMachine::PSF) makingPSF=true;
    2262           0 :             findConvFunction(theImage,vb);
    2263             :             
    2264           0 :             switch(type) 
    2265             :               {
    2266           0 :               case FTMachine::RESIDUAL:
    2267           0 :                 vb.visCube()=vb.correctedVisCube();
    2268           0 :                 vb.visCube()-=vb.modelVisCube();
    2269           0 :                 put(vb, -1, false);
    2270           0 :                 break;
    2271           0 :               case FTMachine::MODEL:
    2272           0 :                 vb.visCube()=vb.modelVisCube();
    2273           0 :                 put(vb, -1, false);
    2274           0 :                 break;
    2275           0 :               case FTMachine::CORRECTED:
    2276           0 :                 vb.visCube()=vb.correctedVisCube();
    2277           0 :                 put(vb, -1, false);
    2278           0 :                 break;
    2279           0 :               case FTMachine::PSF:
    2280           0 :                 vb.visCube()=Complex(1.0,0.0);
    2281           0 :                 makingPSF = true;
    2282           0 :                 put(vb, -1, true);
    2283           0 :                 break;
    2284           0 :               case FTMachine::OBSERVED:
    2285             :               default:
    2286           0 :                 put(vb, -1, false);
    2287           0 :                 break;
    2288             :               }
    2289             :           }
    2290             :       }
    2291           0 :     finalizeToSky();
    2292             :     // Normalize by dividing out weights, etc.
    2293           0 :     getImage(weight, true);
    2294           0 :   }
    2295             :   //
    2296             :   //-------------------------------------------------------------------------
    2297             :   //  
    2298           0 :   void AWProjectFT::setPAIncrement(const Quantity& computePAIncrement,
    2299             :                                    const Quantity& rotateOTFPAIncrement)
    2300             :   {
    2301           0 :     LogIO log_l(LogOrigin("AWProjectFT", "setPAIncrement[R&D]"));
    2302             : 
    2303             :     // Quantity tmp(abs(paIncrement.getValue("deg")), "deg");
    2304             :     // if (paIncrement.getValue("rad") < 0)
    2305             :     //   {
    2306             :     //  rotateApertureOTF_p = false;
    2307             :     //  convFuncCtor_p->setRotateCF(tmp.getValue("rad"), rotateApertureOTF_p);
    2308             :     //   }
    2309             :     // else
    2310             :     //   {
    2311             :     //  rotateApertureOTF_p = true;
    2312             :     //  convFuncCtor_p->setRotateCF(360.0*M_PI/180.0, rotateApertureOTF_p);
    2313             :     //   }
    2314             :         
    2315             : 
    2316           0 :     rotateOTFPAIncr_p = rotateOTFPAIncrement.getValue("rad");
    2317           0 :     computePAIncr_p = computePAIncrement.getValue("rad");
    2318           0 :     convFuncCtor_p->setRotateCF(computePAIncr_p, rotateOTFPAIncr_p);
    2319             : 
    2320           0 :     paChangeDetector.setTolerance(computePAIncrement);
    2321           0 :     visResampler_p->setPATolerance(computePAIncrement.getValue("rad"));
    2322             :     log_l << LogIO::NORMAL <<"Setting PA increment to " 
    2323           0 :           << computePAIncrement.getValue("deg") << " deg" << endl;
    2324           0 :     cfCache_p->setPAChangeDetector(paChangeDetector);
    2325           0 :   }
    2326             :   //
    2327             :   //-------------------------------------------------------------------------
    2328             :   //  
    2329           0 :   Bool AWProjectFT::verifyShapes(IPosition pbShape, IPosition skyShape)
    2330             :   {
    2331           0 :     LogIO log_l(LogOrigin("AWProjectFT", "verifyShapes[R&D]"));
    2332             : 
    2333           0 :     if ((pbShape(0) != skyShape(0)) && // X-axis
    2334           0 :         (pbShape(1) != skyShape(1)) && // Y-axis
    2335           0 :         (pbShape(2) != skyShape(2)))   // Poln-axis
    2336             :       {
    2337             :         log_l << "Sky and/or polarization shape of the avgPB and the sky model do not match."
    2338           0 :               << LogIO::EXCEPTION;
    2339           0 :         return false;
    2340             :       }
    2341           0 :     return true;
    2342             :     
    2343             :   }
    2344             :   //
    2345             :   //-------------------------------------------------------------------------
    2346             :   //  
    2347           0 :   void AWProjectFT::makeThGridCoords(VBStore& vbs, const Vector<Int>& gridShape)
    2348             :   {
    2349           0 :     Float dNx=(gridShape(0)/8.0), dNy=(gridShape(1)/8.0);
    2350           0 :     Int GNx=SynthesisUtils::nint(gridShape(0)/dNx),
    2351           0 :       GNy=SynthesisUtils::nint(gridShape(1)/dNy);
    2352             : 
    2353           0 :     vbs.BLCXi.resize(GNx,GNy);    
    2354           0 :     vbs.BLCYi.resize(GNx,GNy);    
    2355           0 :     vbs.TRCXi.resize(GNx,GNy);
    2356           0 :     vbs.TRCYi.resize(GNx,GNy);
    2357           0 :     vbs.BLCXi=vbs.BLCYi=vbs.TRCXi=vbs.TRCYi=-1;
    2358             : 
    2359           0 :     for (Int i=0;i<GNx;i++)
    2360           0 :       for (Int j=0;j<GNy;j++)
    2361             :         {
    2362           0 :           vbs.BLCXi(i,j)=max(0,SynthesisUtils::nint(i*dNx));
    2363           0 :           vbs.BLCYi(i,j)=max(0,SynthesisUtils::nint(j*dNy));
    2364           0 :           vbs.TRCXi(i,j)=min(gridShape(0), SynthesisUtils::nint((i+1)*dNx-1.0));
    2365           0 :           vbs.TRCYi(i,j)=min(gridShape(1), SynthesisUtils::nint((j+1)*dNy-1.0));
    2366             :         }
    2367             :     // for (Int i=0;i<GNx;i++)
    2368             :     //   for (Int j=0;j<GNy;j++)
    2369             :     //  cerr << i << " " << j << ": " << vbs.BLCXi(i,j) << " " << vbs.BLCYi(i,j) << " " << vbs.TRCXi(i,j) << " " << vbs.TRCYi(i,j) << endl;
    2370           0 :   }
    2371             :   //
    2372             :   //-------------------------------------------------------------------------
    2373             :   //  
    2374           0 :   void AWProjectFT::setupVBStore(VBStore& vbs,
    2375             :                                  const VisBuffer& vb, 
    2376             :                                  const Matrix<Float>& imagingweight,
    2377             :                                  const Cube<Complex>& visData,
    2378             :                                  const Matrix<Double>& uvw,
    2379             :                                  const Cube<Int>& flagCube,
    2380             :                                  const Vector<Double>& dphase,
    2381             :                                  const Bool& dopsf,
    2382             :                                  const Vector<Int>& /*gridShape*/)
    2383             :   {
    2384           0 :     LogIO log_l(LogOrigin("AWProjectFT", "setupVBStore[R&D]"));
    2385             : 
    2386             :     //    Vector<Int> ConjCFMap, CFMap;
    2387             : 
    2388           0 :     vbs.vb_p = &vb;
    2389           0 :     makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2390           0 :     makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2391             : 
    2392           0 :     visResampler_p->setParams(uvScale,uvOffset,dphase);
    2393           0 :     visResampler_p->setMaps(chanMap, polMap);
    2394           0 :     visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2395           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2396             :     //
    2397             :     // Set up VBStore object to point to the relavent info. of the VB.
    2398             :     //
    2399           0 :     vbs.imRefFreq_p = imRefFreq_p;
    2400           0 :     vbs.nRow_p = vb.nRow();
    2401           0 :     vbs.beginRow_p = 0;
    2402           0 :     vbs.endRow_p = vbs.nRow_p;
    2403           0 :     vbs.spwID_p = vb.spectralWindow();
    2404           0 :     vbs.nDataPol_p  = flagCube.shape()[0];
    2405           0 :     vbs.nDataChan_p = flagCube.shape()[1];
    2406             : 
    2407           0 :     vbs.antenna1_p.reference(vb.antenna1());
    2408           0 :     vbs.antenna2_p.reference(vb.antenna2());
    2409           0 :     vbs.paQuant_p = Quantity(getPA(vb),"rad");
    2410           0 :     vbs.corrType_p.reference(vb.corrType());
    2411           0 :     vbs.uvw_p.reference(uvw);
    2412           0 :     vbs.imagingWeight_p.reference(imagingweight);
    2413           0 :     vbs.visCube_p.reference(visData);
    2414             :     //    vbs.freq_p.reference(interpVisFreq_p);
    2415           0 :     vbs.freq_p.reference(vb.frequency());
    2416             :     //    vbs.rowFlag_p.assign(vb.flagRow());  
    2417           0 :     vbs.rowFlag_p.reference(vb.flagRow());
    2418           0 :     if(!usezero_p) 
    2419           0 :       for (Int rownr=0; rownr<vbs.nRow_p; rownr++) 
    2420           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) vbs.rowFlag_p(rownr)=true;
    2421             : 
    2422             :     // Really nice way of converting a Cube<Int> to Cube<Bool>.
    2423             :     // However the VBS objects should ultimately be references
    2424             :     // directly to bool cubes.
    2425             :     //  vbs.rowFlag.resize(rowFlags.shape());  vbs.rowFlag  = false; vbs.rowFlag(rowFlags) = true;
    2426           0 :     vbs.flagCube_p.resize(flagCube.shape());  vbs.flagCube_p = false; vbs.flagCube_p(flagCube!=0) = true;
    2427           0 :     vbs.conjBeams_p=conjBeams_p;
    2428             : 
    2429           0 :     timer_p.mark();
    2430             : 
    2431           0 :     Vector<Double> pointingOffset(convFuncCtor_p->findPointingOffset(*image, vb));
    2432           0 :     if (makingPSF)
    2433             :       {
    2434           0 :         cfwts2_p->invokeGC(vbs.spwID_p);
    2435             :         //SynthesisUtilMethods::getResource(String("AfterWTS_CFBClearing"),String("memusage"));
    2436             :         
    2437           0 :         visResampler_p->makeVBRow2CFMap(*cfwts2_p,*convFuncCtor_p, vb,
    2438           0 :                                         paChangeDetector.getParAngleTolerance(),
    2439           0 :                                         chanMap,polMap,pointingOffset);
    2440             :         //SynthesisUtilMethods::getResource(String("PSFGridding"),String("memusage"));
    2441             :       }
    2442             :     else
    2443             :       {
    2444             :         // If the Wt. CFs are still in the memory, clear them.  They
    2445             :         // won't be required again (though with the silly check below,
    2446             :         // if the in-memory Wt. CFs are less than 1KB, they will be
    2447             :         // left in memory).
    2448           0 :         if (cfwts2_p->memUsage() > 1000)
    2449             :           {
    2450             :             //SynthesisUtilMethods::getResource(String("BeforeWTSClearing"),String("memusage"));
    2451             :             //cerr << "CFWTS memusage before clearing: " << cfwts2_p->memUsage() << endl;
    2452             : 
    2453           0 :             cfwts2_p->clear();
    2454             : 
    2455             :             //cerr << "CFWTS memusage after clearing: " << cfwts2_p->memUsage() << endl;
    2456             :             //SynthesisUtilMethods::getResource(String("AfterWTSClearing"),String("memusage"));
    2457             :           }
    2458             : 
    2459           0 :         cfs2_p->invokeGC(vbs.spwID_p);
    2460             :         //SynthesisUtilMethods::getResource(String("After_CFBClearing"),String("memusage"));
    2461           0 :         visResampler_p->makeVBRow2CFMap(*cfs2_p,*convFuncCtor_p, vb,
    2462           0 :                                         paChangeDetector.getParAngleTolerance(),
    2463           0 :                                         chanMap,polMap,pointingOffset);
    2464             :         //SynthesisUtilMethods::getResource(String("ImGridding"),String("memusage"));
    2465             :       }
    2466             : 
    2467             : 
    2468             :     //    VBRow2CFMapType theMap(visResampler_p->getVBRow2CFMap());
    2469           0 :     VBRow2CFBMapType& theMap=visResampler_p->getVBRow2CFBMap();
    2470             :     //
    2471             :     // For AzElApertures, this rotates the CFs.
    2472             :     //
    2473           0 :     convFuncCtor_p->prepareConvFunction(vb,theMap);
    2474             :     
    2475             :     
    2476             :     //    CFBStruct cfbst_pub;
    2477             :     //UUU    theMap[0]->getAsStruct(cfbst_pub);
    2478             :     //UUU    vbs.cfBSt_p=cfbst_pub;
    2479           0 :     vbs.accumCFs_p=((vbs.uvw_p.nelements() == 0) && dopsf);
    2480             :     
    2481             :     
    2482             :     // for(int ii=0;ii<cfbst_pub.shape[0];ii++)
    2483             :     //   for(int jj=0;jj<cfbst_pub.shape[1];jj++)
    2484             :     //  for(int kk=0;kk<cfbst_pub.shape[2];kk++)
    2485             :     //    {
    2486             :     //      CFCStruct cfcst=cfbst_pub.getCFB(ii,jj,kk);
    2487             :     //      cerr << "[" << ii << "," << jj << "," << kk << "]:" 
    2488             :     //           << cfcst.sampling << " "
    2489             :     //           << cfcst.xSupport << " "
    2490             :     //           << cfcst.ySupport 
    2491             :     //           << endl;
    2492             :     //    }
    2493             : 
    2494             :     
    2495             :     // The following code is required only for GPU or multi-threaded
    2496             :     //gridder.  Currently does not work without the rest of the
    2497             :     //GPU/multi-threaded infrastructure (though, I (SB) thought this
    2498             :     //was designed to be benign for normal gridding).
    2499             :     //
    2500             :     //makeThGridCoords(vbs,gridShape);
    2501             : 
    2502           0 :     runTime1_p += timer_p.real();
    2503           0 :     visResampler_p->initializeDataBuffers(vbs);
    2504             :     //    visResampler_p->setConvFunc(cfs_p);
    2505           0 :   }
    2506             : 
    2507             :   //
    2508             :   //---------------------------------------------------------------
    2509             :   //
    2510             :   // Predict the coherences as well as their derivatives w.r.t. the
    2511             :   // pointing offsets.
    2512             :   //
    2513           0 :   void AWProjectFT::nget(VisBuffer& vb,
    2514             :                           // These offsets should be appropriate for the VB
    2515             :                           Array<Float>& l_off, Array<Float>& m_off,
    2516             :                           Cube<Complex>& Mout,
    2517             :                           Cube<Complex>& dMout1,
    2518             :                           Cube<Complex>& dMout2,
    2519             :                           Int Conj, Int doGrad)
    2520             :   {
    2521           0 :     LogIO log_l(LogOrigin("AWProjectFT", "nget[R&D]"));
    2522             :     Int startRow, endRow, nRow;
    2523           0 :     nRow=vb.nRow();
    2524           0 :     startRow=0;
    2525           0 :     endRow=nRow-1;
    2526             : 
    2527           0 :     Mout = dMout1 = dMout2 = Complex(0,0);
    2528             : 
    2529           0 :     findConvFunction(*image, vb);
    2530           0 :     Int NAnt=0;
    2531           0 :     Nant_p     = vb.msColumns().antenna().nrow();
    2532           0 :     if (doPointing)   
    2533           0 :       NAnt = findPointingOffsets(vb,l_offsets,m_offsets,false);
    2534             : 
    2535           0 :     l_offsets=l_off;
    2536           0 :     m_offsets=m_off;
    2537           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    2538           0 :     uvw=0.0;
    2539           0 :     Vector<Double> dphase(vb.uvw().nelements());
    2540           0 :     dphase=0.0;
    2541             :     //NEGATING to correct for an image inversion problem
    2542           0 :     for (Int i=startRow;i<=endRow;i++) 
    2543             :       {
    2544           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    2545           0 :         uvw(2,i)=vb.uvw()(i)(2);
    2546             :       }
    2547             :     
    2548           0 :     doUVWRotation_p=true;
    2549             :     //rotateUVW(uvw, dphase, vb);
    2550           0 :     girarUVW(uvw, dphase, vb);
    2551           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2552             :     
    2553             :     // This is the convention for dphase
    2554             :     //    dphase*=-1.0;
    2555             : 
    2556           0 :     Cube<Int> flags(vb.flagCube().shape());
    2557           0 :     flags=0;
    2558           0 :     flags(vb.flagCube())=true;
    2559             :     
    2560             :     //Check if ms has changed then cache new spw and chan selection
    2561           0 :     if(vb.newMS())
    2562           0 :       matchAllSpwChans(vb);
    2563             :     
    2564             :     //Here we redo the match or use previous match
    2565             :     //
    2566             :     //Channel matching for the actual spectral window of buffer
    2567             :     //
    2568           0 :     if(doConversion_p[vb.spectralWindow()])
    2569           0 :       matchChannel(vb.spectralWindow(), vb);
    2570             :     else
    2571             :       {
    2572           0 :         chanMap.resize();
    2573           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    2574             :       }
    2575             :     
    2576           0 :     Vector<Int> rowFlags(vb.nRow());
    2577           0 :     rowFlags=0;
    2578           0 :     rowFlags(vb.flagRow())=true;
    2579           0 :     if(!usezero_p) 
    2580           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2581           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2582             :     
    2583           0 :     IPosition s,gradS;
    2584           0 :     Cube<Complex> visdata,gradVisAzData,gradVisElData;
    2585             :     //
    2586             :     // visdata now references the Mout data structure rather than to the internal VB storeage.
    2587             :     //
    2588           0 :     visdata.reference(Mout);
    2589             : 
    2590           0 :     if (doGrad)
    2591             :       {
    2592             :         // The following should reference some slice of dMout?
    2593           0 :         gradVisAzData.reference(dMout1);
    2594           0 :         gradVisElData.reference(dMout2);
    2595             :       }
    2596           0 :       visResampler_p->setParams(uvScale,uvOffset,dphase);
    2597           0 :       visResampler_p->setMaps(chanMap, polMap);
    2598           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2599             :       //  Vector<Int> ConjCFMap, CFMap;
    2600           0 :       makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2601           0 :       makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2602           0 :       visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2603             :     //
    2604             :     // Begin the actual de-gridding.
    2605             :     //
    2606           0 :     if(isTiled) 
    2607             :       {
    2608           0 :         log_l << "The sky model is tiled" << LogIO::NORMAL << LogIO::POST;
    2609           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    2610           0 :         Vector<Double> uvLambda(2);
    2611           0 :         Vector<Int> centerLoc2D(2);
    2612           0 :         centerLoc2D=0;
    2613             :         
    2614             :         // Loop over all rows
    2615           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2616             :           {
    2617             :             
    2618             :             // Calculate uvw for this row at the center frequency
    2619           0 :             uvLambda(0)=uvw(0, rownr)*invLambdaC;
    2620           0 :             uvLambda(1)=uvw(1, rownr)*invLambdaC;
    2621           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    2622             :             
    2623             :             // Is this point on the grid?
    2624           0 :             if(gridder->onGrid(centerLoc2D)) 
    2625             :               {
    2626             :                 
    2627             :                 // Get the tile
    2628           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    2629           0 :                 gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    2630           0 :                 Int aNx=dataPtr->shape()(0);
    2631           0 :                 Int aNy=dataPtr->shape()(1);
    2632             :                 
    2633             :                 // Now use FORTRAN to do the gridding. Remember to 
    2634             :                 // ensure that the shape and offsets of the tile are 
    2635             :                 // accounted for.
    2636             :                 
    2637           0 :                 Vector<Double> actualOffset(3);
    2638           0 :                 for (Int i=0;i<2;i++) 
    2639           0 :                   actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    2640             :                 
    2641           0 :                 actualOffset(2)=uvOffset(2);
    2642           0 :                 IPosition s(vb.modelVisCube().shape());
    2643             :                 
    2644           0 :                 Int ScanNo=0, tmpPAI;
    2645           0 :                 Double area=1.0;
    2646           0 :                 tmpPAI = 1;
    2647           0 :                 runFortranGetGrad(uvw,dphase,visdata,s,
    2648             :                                   gradVisAzData,gradVisElData,
    2649             :                                   Conj,flags,rowFlags,rownr,
    2650           0 :                                   actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    2651           0 :                                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    2652             :               }
    2653             :           }
    2654             :       }
    2655             :     else 
    2656             :       {
    2657           0 :         IPosition s(vb.modelVisCube().shape());
    2658           0 :         Int ScanNo=0, tmpPAI, trow=-1;
    2659           0 :         Double area=1.0;
    2660           0 :         tmpPAI = 1;
    2661           0 :         runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    2662             :                           gradVisAzData, gradVisElData,
    2663             :                           Conj,flags,rowFlags,trow,
    2664           0 :                           uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2665           0 :                           l_offsets,m_offsets,area,doGrad,tmpPAI);
    2666             :       }
    2667             :     
    2668           0 :   }
    2669           0 :   void AWProjectFT::get(VisBuffer& vb,       
    2670             :                          VisBuffer& gradVBAz,
    2671             :                          VisBuffer& gradVBEl,
    2672             :                          Cube<Float>& pointingOffsets,
    2673             :                          Int row,  // default row=-1 
    2674             :                          Type whichVBColumn, // default whichVBColumn = FTMachine::MODEL
    2675             :                          Type whichGradVBColumn,// default whichGradVBColumn = FTMachine::MODEL
    2676             :                          Int Conj, Int doGrad) // default Conj=0, doGrad=1
    2677             :   {
    2678             :     // If row is -1 then we pass through all rows
    2679             :     Int startRow, endRow, nRow;
    2680           0 :     if (row==-1) 
    2681             :       {
    2682           0 :         nRow=vb.nRow();
    2683           0 :         startRow=0;
    2684           0 :         endRow=nRow-1;
    2685           0 :         initVisBuffer(vb,whichVBColumn);
    2686           0 :         if (doGrad)
    2687             :           {
    2688           0 :             initVisBuffer(gradVBAz, whichGradVBColumn);
    2689           0 :             initVisBuffer(gradVBEl, whichGradVBColumn);
    2690             :           }
    2691             :       }
    2692             :     else 
    2693             :       {
    2694           0 :         nRow=1;
    2695           0 :         startRow=row;
    2696           0 :         endRow=row;
    2697           0 :         initVisBuffer(vb,whichVBColumn,row);
    2698           0 :         if (doGrad)
    2699             :           {
    2700           0 :             initVisBuffer(gradVBAz, whichGradVBColumn,row);
    2701           0 :             initVisBuffer(gradVBEl, whichGradVBColumn,row);
    2702             :           }
    2703             :       }
    2704             :     
    2705           0 :     findConvFunction(*image, vb);
    2706             : 
    2707           0 :     Nant_p     = vb.msColumns().antenna().nrow();
    2708           0 :     Int NAnt=0;
    2709           0 :     if (doPointing)   
    2710           0 :       NAnt = findPointingOffsets(vb,pointingOffsets,l_offsets,m_offsets,false);
    2711             : 
    2712           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    2713           0 :     uvw=0.0;
    2714           0 :     Vector<Double> dphase(vb.uvw().nelements());
    2715           0 :     dphase=0.0;
    2716             :     //NEGATING to correct for an image inversion problem
    2717           0 :     for (Int i=startRow;i<=endRow;i++) 
    2718             :       {
    2719           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    2720           0 :         uvw(2,i)=vb.uvw()(i)(2);
    2721             :       }
    2722             :     
    2723           0 :     doUVWRotation_p=true;
    2724             :     //rotateUVW(uvw, dphase, vb);
    2725           0 :     girarUVW(uvw, dphase, vb);
    2726           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2727             :     
    2728             :     // This is the convention for dphase
    2729             :     //dphase*=-1.0;
    2730             :     
    2731             :     
    2732           0 :     Cube<Int> flags(vb.flagCube().shape());
    2733           0 :     flags=0;
    2734           0 :     flags(vb.flagCube())=true;
    2735             :     //    
    2736             :     //Check if ms has changed then cache new spw and chan selection
    2737             :     //
    2738           0 :     if(vb.newMS()) matchAllSpwChans(vb);
    2739             :     
    2740             :     //Here we redo the match or use previous match
    2741             :     //
    2742             :     //Channel matching for the actual spectral window of buffer
    2743             :     //
    2744           0 :     if(doConversion_p[vb.spectralWindow()])
    2745           0 :       matchChannel(vb.spectralWindow(), vb);
    2746             :     else
    2747             :       {
    2748           0 :         chanMap.resize();
    2749           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    2750             :       }
    2751             :     
    2752           0 :     Vector<Int> rowFlags(vb.nRow());
    2753           0 :     rowFlags=0;
    2754           0 :     rowFlags(vb.flagRow())=true;
    2755           0 :     if(!usezero_p) 
    2756           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2757           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2758             :         
    2759           0 :     for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2760           0 :       if (vb.antenna1()(rownr) != vb.antenna2()(rownr)) 
    2761           0 :         rowFlags(rownr) = (vb.flagRow()(rownr)==true);
    2762             :     
    2763           0 :     IPosition s,gradS;
    2764           0 :     Cube<Complex> visdata,gradVisAzData,gradVisElData;
    2765           0 :     if (whichVBColumn == FTMachine::MODEL) 
    2766             :       {
    2767           0 :         s = vb.modelVisCube().shape();
    2768           0 :         visdata.reference(vb.modelVisCube());
    2769             :       }
    2770           0 :     else if (whichVBColumn == FTMachine::OBSERVED)  
    2771             :       {
    2772           0 :         s = vb.visCube().shape();
    2773           0 :         visdata.reference(vb.visCube());
    2774             :       }
    2775             :     
    2776           0 :     if (doGrad)
    2777             :       {
    2778           0 :         if (whichGradVBColumn == FTMachine::MODEL) 
    2779             :           {
    2780             :             //      gradS = gradVBAz.modelVisCube().shape();
    2781           0 :             gradVisAzData.reference(gradVBAz.modelVisCube());
    2782           0 :             gradVisElData.reference(gradVBEl.modelVisCube());
    2783             :           }
    2784           0 :         else if (whichGradVBColumn == FTMachine::OBSERVED)  
    2785             :           {
    2786             :             //      gradS = gradVBAz.visCube().shape();
    2787           0 :             gradVisAzData.reference(gradVBAz.visCube());
    2788           0 :             gradVisElData.reference(gradVBEl.visCube());
    2789             :           }
    2790             :       }
    2791           0 :       visResampler_p->setParams(uvScale,uvOffset,dphase);
    2792           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2793           0 :       visResampler_p->setMaps(chanMap, polMap);
    2794             :       //  Vector<Int> ConjCFMap, CFMap;
    2795           0 :     makeCFPolMap(vb,cfStokes_p,CFMap_p);
    2796           0 :   makeConjPolMap(vb,CFMap_p,ConjCFMap_p);
    2797           0 :   visResampler_p->setCFMaps(CFMap_p, ConjCFMap_p);
    2798             :     
    2799           0 :     if(isTiled) 
    2800             :       {
    2801           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    2802           0 :         Vector<Double> uvLambda(2);
    2803           0 :         Vector<Int> centerLoc2D(2);
    2804           0 :         centerLoc2D=0;
    2805             :         
    2806             :         // Loop over all rows
    2807           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2808             :           {
    2809             :             
    2810             :             // Calculate uvw for this row at the center frequency
    2811           0 :             uvLambda(0)=uvw(0, rownr)*invLambdaC;
    2812           0 :             uvLambda(1)=uvw(1, rownr)*invLambdaC;
    2813           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    2814             :             
    2815             :             // Is this point on the grid?
    2816           0 :             if(gridder->onGrid(centerLoc2D)) 
    2817             :               {
    2818             :                 
    2819             :                 // Get the tile
    2820           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    2821           0 :                 gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    2822           0 :                 Int aNx=dataPtr->shape()(0);
    2823           0 :                 Int aNy=dataPtr->shape()(1);
    2824             :                 
    2825             :                 // Now use FORTRAN to do the gridding. Remember to 
    2826             :                 // ensure that the shape and offsets of the tile are 
    2827             :                 // accounted for.
    2828             :                 
    2829           0 :                 Vector<Double> actualOffset(3);
    2830           0 :                 for (Int i=0;i<2;i++) 
    2831           0 :                   actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    2832             :                 
    2833           0 :                 actualOffset(2)=uvOffset(2);
    2834           0 :                 IPosition s(vb.modelVisCube().shape());
    2835             :                 
    2836           0 :                 Int ScanNo=0, tmpPAI;
    2837           0 :                 Double area=1.0;
    2838           0 :                 tmpPAI = 1;
    2839           0 :                 runFortranGetGrad(uvw,dphase,visdata,s,
    2840             :                                   gradVisAzData,gradVisElData,
    2841             :                                   Conj,flags,rowFlags,rownr,
    2842           0 :                                   actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    2843           0 :                                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    2844             :               }
    2845             :           }
    2846             :       }
    2847             :     else 
    2848             :       {
    2849             :         
    2850           0 :         IPosition s(vb.modelVisCube().shape());
    2851           0 :         Int ScanNo=0, tmpPAI;
    2852           0 :         Double area=1.0;
    2853             : 
    2854           0 :         tmpPAI = 1;
    2855             : 
    2856           0 :         runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    2857             :                           gradVisAzData, gradVisElData,
    2858             :                           Conj,flags,rowFlags,row,
    2859           0 :                           uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2860           0 :                           l_offsets,m_offsets,area,doGrad,tmpPAI);
    2861             : //      runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,row,
    2862             : //                    uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2863             : //                    l_offsets,m_offsets,area,doGrad,tmpPAI);
    2864             :       }
    2865           0 :   }
    2866             :   //
    2867             :   //---------------------------------------------------------------
    2868             :   //
    2869           0 :   void AWProjectFT::get(VisBuffer& vb, Cube<Complex>& modelVis, 
    2870             :                          Array<Complex>& griddedVis, Vector<Double>& scale,
    2871             :                          Int row)
    2872             :   {
    2873             : 
    2874             :     (void)scale; //Suppress the warning
    2875             : 
    2876           0 :     Int nX=griddedVis.shape()(0);
    2877           0 :     Int nY=griddedVis.shape()(1);
    2878           0 :     Vector<Double> offset(2);
    2879           0 :     offset(0)=Double(nX)/2.0;
    2880           0 :     offset(1)=Double(nY)/2.0;
    2881             :     // If row is -1 then we pass through all rows
    2882             :     Int startRow, endRow, nRow;
    2883           0 :     if (row==-1) 
    2884             :       {
    2885           0 :         nRow=vb.nRow();
    2886           0 :         startRow=0;
    2887           0 :         endRow=nRow-1;
    2888           0 :         modelVis.set(Complex(0.0,0.0));
    2889             :       } 
    2890             :     else 
    2891             :       {
    2892           0 :         nRow=1;
    2893           0 :         startRow=row;
    2894           0 :         endRow=row;
    2895           0 :         modelVis.xyPlane(row)=Complex(0.0,0.0);
    2896             :       }
    2897             :     
    2898           0 :     Int NAnt=0;
    2899             :     
    2900           0 :     if (doPointing) 
    2901           0 :       NAnt = findPointingOffsets(vb,l_offsets, m_offsets,true);
    2902             :     
    2903             :     
    2904             :     //  
    2905             :     // Get the uvws in a form that Fortran can use
    2906             :     //
    2907           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    2908           0 :     uvw=0.0;
    2909           0 :     Vector<Double> dphase(vb.uvw().nelements());
    2910           0 :     dphase=0.0;
    2911             :     //
    2912             :     //NEGATING to correct for an image inversion problem
    2913             :     //
    2914           0 :     for (Int i=startRow;i<=endRow;i++) 
    2915             :       {
    2916           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    2917           0 :         uvw(2,i)=vb.uvw()(i)(2);
    2918             :       }
    2919             :     
    2920           0 :     doUVWRotation_p=true;
    2921             :     //rotateUVW(uvw, dphase, vb);
    2922           0 :     girarUVW(uvw, dphase, vb);
    2923           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2924             :     
    2925             :     // This is the convention for dphase
    2926             :     //dphase*=-1.0;
    2927             :     
    2928           0 :     Cube<Int> flags(vb.flagCube().shape());
    2929           0 :     flags=0;
    2930           0 :     flags(vb.flagCube())=true;
    2931             :     
    2932             :     //Check if ms has changed then cache new spw and chan selection
    2933           0 :     if(vb.newMS())
    2934           0 :       matchAllSpwChans(vb);
    2935             :     
    2936             :     //Channel matching for the actual spectral window of buffer
    2937           0 :     if(doConversion_p[vb.spectralWindow()])
    2938           0 :       matchChannel(vb.spectralWindow(), vb);
    2939             :     else
    2940             :       {
    2941           0 :         chanMap.resize();
    2942           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    2943             :       }
    2944             :     
    2945           0 :     Vector<Int> rowFlags(vb.nRow());
    2946           0 :     rowFlags=0;
    2947           0 :     rowFlags(vb.flagRow())=true;
    2948           0 :     if(!usezero_p) 
    2949           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2950           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2951             :     
    2952           0 :     visResampler_p->setParams(uvScale,uvOffset,dphase);
    2953           0 :     visResampler_p->setMaps(chanMap, polMap);
    2954           0 :     visResampler_p->setFreqMaps(expandedSpwFreqSel_p,expandedSpwConjFreqSel_p);
    2955             : 
    2956           0 :     IPosition s(modelVis.shape());
    2957           0 :     Int Conj=0,doGrad=0,ScanNo=0;
    2958           0 :     Double area=1.0;
    2959           0 :     Int tmpPAI=1;
    2960           0 :     runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,row,
    2961           0 :                   offset,&griddedVis,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    2962           0 :                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    2963           0 :   }
    2964             :   //
    2965             :   //----------------------------------------------------------------------
    2966             :   //
    2967           0 :   void AWProjectFT::initVisBuffer(VisBuffer& vb, Type whichVBColumn)
    2968             :   {
    2969           0 :     if (whichVBColumn      == FTMachine::MODEL)    vb.modelVisCube()=Complex(0.0,0.0);
    2970           0 :     else if (whichVBColumn == FTMachine::OBSERVED) vb.visCube()=Complex(0.0,0.0);
    2971           0 :   }
    2972             :   //
    2973             :   //----------------------------------------------------------------------
    2974             :   //
    2975           0 :   void AWProjectFT::initVisBuffer(VisBuffer& vb, Type whichVBColumn, Int row)
    2976             :   {
    2977           0 :     if (whichVBColumn == FTMachine::MODEL)
    2978           0 :       vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
    2979           0 :     else if (whichVBColumn == FTMachine::OBSERVED)
    2980           0 :       vb.visCube().xyPlane(row)=Complex(0.0,0.0);
    2981           0 :   }
    2982             : 
    2983           0 :   void AWProjectFT::ComputeResiduals(VisBuffer&vb, Bool useCorrected)
    2984             :   {
    2985           0 :     VBStore vbs;
    2986             : 
    2987           0 :     vbs.nRow_p = vb.nRow();
    2988           0 :     vbs.beginRow_p = 0;
    2989           0 :     vbs.endRow_p = vbs.nRow_p;
    2990             : 
    2991           0 :     vbs.modelCube_p.reference(vb.modelVisCube());
    2992           0 :     if (useCorrected) vbs.correctedCube_p.reference(vb.correctedVisCube());
    2993           0 :     else vbs.visCube_p.reference(vb.visCube());
    2994           0 :     vbs.useCorrected_p = useCorrected;
    2995           0 :     visResampler_p->ComputeResiduals(vbs);
    2996           0 :   }
    2997             : 
    2998             :   // void AWProjectFT::ComputeResiduals(VBStore &vbs)
    2999             :   // {
    3000             :   //   vbs.nRow_p = vb.nRow();
    3001             :   //   vbs.modelCube_p.reference(vb.modelVisCube());
    3002             :   //   if (useCorrected) vbs.correctedCube_p.reference(vb.correctedVisCube());
    3003             :   //   else vbs.visCube_p.reference(vb.visCube());
    3004             :   //   vbs.useCorrected_p = useCorrected;
    3005             :   //   visResampler_p->ComputeResiduals(vbs);
    3006             :   // }
    3007             : 
    3008             : } //# NAMESPACE CASA - END
    3009             : 
    3010             : 
    3011             : 
    3012             : 
    3013             :   // //
    3014             :   // //---------------------------------------------------------------
    3015             :   // //
    3016             :   // void AWProjectFT::normalizeImage(Lattice<Complex>& skyImage,
    3017             :   //                               const Matrix<Double>& sumOfWts,
    3018             :   //                               Lattice<Float>& sensitivityImage,
    3019             :   //                               Lattice<Complex>& sensitivitySqImage,
    3020             :   //                               Bool fftNorm)
    3021             :   // {
    3022             :   //   //
    3023             :   //   // Apply the gridding correction
    3024             :   //   //    
    3025             :   //   Int inx = skyImage.shape()(0);
    3026             :   //   Int iny = skyImage.shape()(1);
    3027             :   //   //    Vector<Complex> correction(inx);
    3028             :           
    3029             :   //   Vector<Float> sincConv(nx);
    3030             :   //   Float centerX=nx/2;
    3031             :   //   for (Int ix=0;ix<nx;ix++) 
    3032             :   //     {
    3033             :   //    Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    3034             :   //    if(ix==centerX) sincConv(ix)=1.0;
    3035             :   //    else        sincConv(ix)=sin(x)/x;
    3036             :   //     }
    3037             :           
    3038             :   //   IPosition cursorShape(4, inx, 1, 1, 1);
    3039             :   //   IPosition axisPath(4, 0, 1, 2, 3);
    3040             :   //   LatticeStepper lsx(skyImage.shape(), cursorShape, axisPath);
    3041             :   //   LatticeIterator<Complex> lix(skyImage, lsx);
    3042             :     
    3043             :   //   LatticeStepper lavgpb(sensitivityImage.shape(),cursorShape,axisPath);
    3044             :   //   LatticeIterator<Float> liavgpb(sensitivityImage, lavgpb);
    3045             :   //   LatticeStepper lavgpbSq(sensitivitySqImage.shape(),cursorShape,axisPath);
    3046             :   //   LatticeIterator<Complex> liavgpbSq(sensitivitySqImage, lavgpbSq);
    3047             :           
    3048             :   //   for(lix.reset(),liavgpb.reset(),liavgpbSq.reset();
    3049             :   //    !lix.atEnd();
    3050             :   //    lix++,liavgpb++,liavgpbSq++) 
    3051             :   //     {
    3052             :   //    Int pol=lix.position()(2);
    3053             :   //    Int chan=lix.position()(3);
    3054             :   //    //      Int iy=lix.position()(1);
    3055             : 
    3056             :   //    //      gridder->correctX1D(correction,iy);
    3057             :             
    3058             :   //    Vector<Complex> PBCorrection(liavgpb.rwVectorCursor().shape());
    3059             :   //    Vector<Float> avgPBVec(liavgpb.rwVectorCursor().shape());
    3060             :   //    Vector<Complex> avgPBSqVec(liavgpbSq.rwVectorCursor().shape());
    3061             :             
    3062             :   //    avgPBSqVec= liavgpbSq.rwVectorCursor();
    3063             :   //    avgPBVec = liavgpb.rwVectorCursor();
    3064             : 
    3065             :   //    for(int i=0;i<PBCorrection.shape();i++)
    3066             :   //      {
    3067             :   //        PBCorrection(i)=(avgPBSqVec(i)/avgPBVec(i));///(sincConv(i)*sincConv(iy));
    3068             :   //        if ((abs(avgPBVec(i))) >= pbLimit_p)
    3069             :   //          lix.rwVectorCursor()(i) /= PBCorrection(i);
    3070             :   //      }
    3071             : 
    3072             :   //    //      if(sumOfWts(pol, chan)>0.0)  // UUU Changing this again....
    3073             :   //      {
    3074             :   //        if(fftNorm)
    3075             :   //          {
    3076             :   //            if(sumOfWts(pol, chan)>0.0) // UUU Moving this inside the fftNorm check.
    3077             :   //              {
    3078             :   //                Complex rnorm(Float(inx)*Float(iny)/sumOfWts(pol,chan));
    3079             :   //                lix.rwCursor()*=rnorm;
    3080             :   //              }
    3081             :   //            else 
    3082             :   //              lix.woCursor()=0.0;
    3083             :   //          }
    3084             :   //        else 
    3085             :   //          {
    3086             :   //            Complex rnorm(Float(inx)*Float(iny));
    3087             :   //            lix.rwCursor()*=rnorm;
    3088             :   //          }
    3089             :   //      }
    3090             :   //      //else 
    3091             :   //      //lix.woCursor()=0.0;
    3092             :   //     }
    3093             :   // }
    3094             :   // //
    3095             :   // //---------------------------------------------------------------
    3096             :   // //
    3097             :   // void AWProjectFT::normalizeImage(Lattice<Complex>& skyImage,
    3098             :   //                               const Matrix<Double>& sumOfWts,
    3099             :   //                               Lattice<Float>& sensitivityImage,
    3100             :   //                               Bool fftNorm)
    3101             :   // {
    3102             :   //   //
    3103             :   //   // Apply the gridding correction
    3104             :   //   //    
    3105             :   //   Int inx = skyImage.shape()(0);
    3106             :   //   Int iny = skyImage.shape()(1);
    3107             :   //   Vector<Complex> correction(inx);
    3108             :           
    3109             :   //   Vector<Float> sincConv(nx);
    3110             :   //   Float centerX=nx/2;
    3111             :   //   for (Int ix=0;ix<nx;ix++) 
    3112             :   //     {
    3113             :   //    Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    3114             :   //    if(ix==centerX) sincConv(ix)=1.0;
    3115             :   //    else        sincConv(ix)=sin(x)/x;
    3116             :   //     }
    3117             :           
    3118             :   //   IPosition cursorShape(4, inx, 1, 1, 1);
    3119             :   //   IPosition axisPath(4, 0, 1, 2, 3);
    3120             :   //   LatticeStepper lsx(skyImage.shape(), cursorShape, axisPath);
    3121             :   //   //    LatticeIterator<Complex> lix(skyImage, lsx);
    3122             :   //   LatticeIterator<Complex> lix(skyImage, lsx);
    3123             :     
    3124             :   //   LatticeStepper lavgpb(sensitivityImage.shape(),cursorShape,axisPath);
    3125             :   //   // Array<Float> senArray;sensitivityImage.get(senArray,true);
    3126             :   //   // ArrayLattice<Float> senLat(senArray,true);
    3127             :   //   //    LatticeIterator<Float> liavgpb(senLat, lavgpb);
    3128             :   //   LatticeIterator<Float> liavgpb(sensitivityImage, lavgpb);
    3129             : 
    3130             :   //   for(lix.reset(),liavgpb.reset();
    3131             :   //    !lix.atEnd();
    3132             :   //    lix++,liavgpb++) 
    3133             :   //     {
    3134             :   //    Int pol=lix.position()(2);
    3135             :   //    Int chan=lix.position()(3);
    3136             :         
    3137             :   //    //      if(sumOfWts(pol, chan)>0.0)  // UUU Changing this again.....
    3138             :   //      {
    3139             :   //        Int iy=lix.position()(1);
    3140             :   //        gridder->correctX1D(correction,iy);
    3141             :             
    3142             :   //        Vector<Float> avgPBVec(liavgpb.rwVectorCursor().shape());
    3143             :             
    3144             :   //        avgPBVec = liavgpb.rwVectorCursor();
    3145             : 
    3146             :   //        for(int i=0;i<avgPBVec.shape();i++)
    3147             :   //          {
    3148             :   //            //
    3149             :   //            // This with the PS functions
    3150             :   //            //
    3151             :   //            // PBCorrection(i)=FUNC(avgPBVec(i))*sincConv(i)*sincConv(iy);
    3152             :   //            // if ((abs(PBCorrection(i)*correction(i))) >= pbLimit_p)
    3153             :   //            //      lix.rwVectorCursor()(i) /= PBCorrection(i)*correction(i);
    3154             :   //            // else if (!makingPSF)
    3155             :   //            //      lix.rwVectorCursor()(i) /= correction(i)*sincConv(i)*sincConv(iy);
    3156             :   //            //
    3157             :   //            // This without the PS functions
    3158             :   //            //
    3159             :   //            Float tt = pbFunc(avgPBVec(i),pbLimit_p)*sincConv(i)*sincConv(iy);
    3160             :   //                 //         PBCorrection(i)=pbFunc(avgPBVec(i),pbLimit_p)*sincConv(i)*sincConv(iy);
    3161             :   //                 //                lix.rwVectorCursor()(i) /= PBCorrection(i);
    3162             :   //            //                lix.rwVectorCursor()(i) *= tt;
    3163             :   //            //              if (!makingPSF)
    3164             : 
    3165             :   //            lix.rwVectorCursor()(i) /= tt;
    3166             :   //          }
    3167             :             
    3168             :   //        if(fftNorm)
    3169             :   //          {
    3170             :   //            if(sumOfWts(pol, chan)>0.0) // UUU Moved this inside the fftNorm check.
    3171             :   //              {
    3172             :   //                Complex rnorm(Float(inx)*Float(iny)/sumOfWts(pol,chan));
    3173             :   //                lix.rwCursor()*=rnorm;
    3174             :   //              }
    3175             :   //            else 
    3176             :   //              lix.woCursor()=0.0;
    3177             :   //          }
    3178             :   //        else 
    3179             :   //          {
    3180             :   //            Complex rnorm(Float(inx)*Float(iny));
    3181             :   //            lix.rwCursor()*=rnorm;
    3182             :   //          }
    3183             :   //      }
    3184             :   //      //else 
    3185             :   //      //lix.woCursor()=0.0;
    3186             :   //     }
    3187             :   // }

Generated by: LCOV version 1.16