LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - nPBWProjectFT.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 0 1805 0.0 %
Date: 2023-11-02 14:27:30 Functions: 0 51 0.0 %

          Line data    Source code
       1             : // -*- C++ -*-
       2             : //# nPBWProjectFT.cc: Implementation of nPBWProjectFT 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 <msvis/MSVis/VisibilityIterator.h>
      30             : #include <casacore/casa/Quanta/UnitMap.h>
      31             : #include <casacore/casa/Quanta/MVTime.h>
      32             : #include <casacore/casa/Quanta/UnitVal.h>
      33             : #include <casacore/measures/Measures/Stokes.h>
      34             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      35             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      36             : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
      37             : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
      38             : #include <casacore/coordinates/Coordinates/Projection.h>
      39             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      40             : #include <casacore/ms/MeasurementSets/MSRange.h>
      41             : #include <casacore/casa/BasicSL/Constants.h>
      42             : #include <casacore/scimath/Mathematics/FFTServer.h>
      43             : #include <synthesis/MeasurementComponents/nPBWProjectFT.h>
      44             : #include <casacore/scimath/Mathematics/RigidVector.h>
      45             : #include <msvis/MSVis/StokesVector.h>
      46             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      47             : #include <msvis/MSVis/VisBuffer.h>
      48             : #include <msvis/MSVis/VisSet.h>
      49             : #include <casacore/images/Images/ImageInterface.h>
      50             : #include <casacore/images/Images/ImageRegrid.h>
      51             : #include <casacore/images/Images/PagedImage.h>
      52             : #include <casacore/casa/Containers/Block.h>
      53             : #include <casacore/casa/Containers/Record.h>
      54             : #include <casacore/casa/Arrays/ArrayLogical.h>
      55             : #include <casacore/casa/Arrays/ArrayMath.h>
      56             : #include <casacore/casa/Arrays/Array.h>
      57             : #include <casacore/casa/Arrays/MaskedArray.h>
      58             : #include <casacore/casa/Arrays/Vector.h>
      59             : #include <casacore/casa/Arrays/Slice.h>
      60             : #include <casacore/casa/Arrays/Matrix.h>
      61             : #include <casacore/casa/Arrays/Cube.h>
      62             : #include <casacore/casa/Arrays/MatrixIter.h>
      63             : #include <casacore/casa/BasicSL/String.h>
      64             : #include <casacore/casa/Utilities/Assert.h>
      65             : #include <casacore/casa/Exceptions/Error.h>
      66             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      67             : #include <casacore/lattices/Lattices/SubLattice.h>
      68             : #include <casacore/lattices/LRegions/LCBox.h>
      69             : #include <casacore/lattices/LEL/LatticeExpr.h>
      70             : #include <casacore/lattices/Lattices/LatticeCache.h>
      71             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      72             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      73             : #include <casacore/lattices/Lattices/LatticeStepper.h>
      74             : #include <casacore/casa/Utilities/CompositeNumber.h>
      75             : #include <casacore/casa/OS/Timer.h>
      76             : #include <casacore/casa/OS/HostInfo.h>
      77             : #include <sstream>
      78             : 
      79             : #include <synthesis/TransformMachines/VLACalcIlluminationConvFunc.h>
      80             : #include <synthesis/TransformMachines/IlluminationConvFunc.h>
      81             : #include <synthesis/MeasurementComponents/ExpCache.h>
      82             : #include <synthesis/MeasurementComponents/CExp.h>
      83             : #include <synthesis/TransformMachines/Utils.h>
      84             : #include <synthesis/TransformMachines/SynthesisError.h>
      85             : #include <casacore/measures/Measures/MEpoch.h>
      86             : #include <casacore/measures/Measures/MeasTable.h>
      87             : #include <casacore/scimath/Mathematics/MathFunc.h>
      88             : 
      89             : #include <casacore/casa/System/ProgressMeter.h>
      90             : 
      91             : #define CONVSIZE (1024*2)
      92             : #define CONVWTSIZEFACTOR 1.0
      93             : #define OVERSAMPLING 20
      94             : #define THRESHOLD 1E-4
      95             : #define USETABLES 0           // If equal to 1, use tabulated exp() and
      96             :                               // complex exp() functions.
      97             : #define MAXPOINTINGERROR 250.0 // Max. pointing error in arcsec used to
      98             : // determine the resolution of the
      99             : // tabulated exp() function.
     100             : using namespace casacore;
     101             : namespace casa { //# NAMESPACE CASA - BEGIN
     102             :   
     103             : #define NEED_UNDERSCORES
     104             :   extern "C" 
     105             :   {
     106             :     //
     107             :     // The Gridding Convolution Function (GCF) used by the underlying
     108             :     // gridder written in FORTRAN.
     109             :     //
     110             :     // The arguments must all be pointers and the value of the GCF at
     111             :     // the given (u,v) point is returned in the weight variable.  Making
     112             :     // this a function which returns a complex value (namely the weight)
     113             :     // has problems when called in FORTRAN - I (SB) don't understand
     114             :     // why.
     115             :     //
     116             : #if defined(NEED_UNDERSCORES)
     117             : #define nwcppeij nwcppeij_
     118             : #endif
     119             :     //
     120             :     //---------------------------------------------------------------
     121             :     //
     122             :     IlluminationConvFunc nwEij;
     123           0 :     void nwcppeij(Double *griduvw, Double *area,
     124             :                  Double *raoff1, Double *decoff1,
     125             :                  Double *raoff2, Double *decoff2, 
     126             :                  Int *doGrad,
     127             :                  Complex *weight,
     128             :                  Complex *dweight1,
     129             :                  Complex *dweight2,
     130             :                  Double *currentCFPA)
     131             :     {
     132           0 :       Complex w,d1,d2;
     133           0 :       nwEij.getValue(griduvw, raoff1, raoff2, decoff1, decoff2,
     134             :                     area,doGrad,w,d1,d2,*currentCFPA);
     135           0 :       *weight   = w;
     136           0 :       *dweight1 = d1;
     137           0 :       *dweight2 = d2;
     138           0 :     }
     139             :   }
     140             :   //
     141             :   //---------------------------------------------------------------
     142             :   //
     143             : #define FUNC(a)  (((a)))
     144           0 :   nPBWProjectFT::nPBWProjectFT(Int nWPlanes, Long icachesize, 
     145             :                                String& cfCacheDirName,
     146             :                                Bool applyPointingOffset,
     147             :                                Bool doPBCorr,
     148             :                                Int itilesize, 
     149             :                                Float /*paSteps*/,
     150             :                                Float pbLimit,
     151           0 :                                Bool usezero)
     152             :     : FTMachine(), padding_p(1.0), nWPlanes_p(nWPlanes),
     153             :       imageCache(0), cachesize(icachesize), tilesize(itilesize),
     154             :       gridder(0), isTiled(false), arrayLattice( ), lattice( ), 
     155             :       maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
     156             :       mspc(0), msac(0), pointingToImage(0), usezero_p(usezero),
     157             :       doPBCorrection(doPBCorr),
     158             :       Second("s"),Radian("rad"),Day("d"), noOfPASteps(0),
     159             :       pbNormalized(false),resetPBs(true), rotateAperture_p(true),
     160             :       cfCache(), paChangeDetector(), cfStokes(),Area(), 
     161           0 :       avgPBSaved(false),avgPBReady(false)
     162             :   {
     163           0 :     epJ=NULL;
     164           0 :     convSize=0;
     165           0 :     tangentSpecified_p=false;
     166           0 :     lastIndex_p=0;
     167           0 :     paChangeDetector.reset();
     168           0 :     pbLimit_p=pbLimit;
     169             :     //
     170             :     // Get various parameters from the visibilities.  
     171             :     //
     172           0 :     bandID_p=-1;
     173           0 :     if (applyPointingOffset) doPointing=1; else doPointing=0;
     174             : 
     175           0 :     convFuncCacheReady=false;
     176           0 :     PAIndex = -1;
     177           0 :     maxConvSupport=-1;  
     178             :     //
     179             :     // Set up the Conv. Func. disk cache manager object.
     180             :     //
     181           0 :     cfCache.setCacheDir(cfCacheDirName.data());
     182           0 :     cfCache.initCache();
     183           0 :     convSampling=OVERSAMPLING;
     184           0 :     convSize=CONVSIZE;
     185           0 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     186           0 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     187           0 :     if (cachesize > hostRAM) cachesize=hostRAM;
     188           0 :   }
     189             :   //
     190             :   //---------------------------------------------------------------
     191             :   //
     192           0 :   nPBWProjectFT::nPBWProjectFT(const RecordInterface& stateRec)
     193           0 :     : FTMachine(),Second("s"),Radian("rad"),Day("d")
     194             :   {
     195             :     //
     196             :     // Construct from the input state record
     197             :     //
     198           0 :     String error;
     199             :     
     200           0 :     if (!fromRecord(error, stateRec)) {
     201           0 :       throw (AipsError("Failed to create nPBWProjectFT: " + error));
     202             :     };
     203           0 :     bandID_p = -1;
     204           0 :     PAIndex = -1;
     205           0 :     maxConvSupport=-1;
     206           0 :     convSampling=OVERSAMPLING;
     207           0 :     convSize=CONVSIZE;
     208           0 :   }
     209             :   //
     210             :   //----------------------------------------------------------------------
     211             :   //
     212           0 :   nPBWProjectFT::nPBWProjectFT(const nPBWProjectFT& other):FTMachine()
     213             :   {
     214           0 :     operator=(other);
     215           0 :   }
     216             :   //
     217             :   //---------------------------------------------------------------
     218             :   //
     219           0 :   nPBWProjectFT& nPBWProjectFT::operator=(const nPBWProjectFT& other)
     220             :   {
     221           0 :     if(this!=&other) 
     222             :       {
     223             :         //Do the base parameters
     224           0 :         FTMachine::operator=(other);
     225             : 
     226             :         
     227           0 :         padding_p=other.padding_p;
     228             :         
     229           0 :         nWPlanes_p=other.nWPlanes_p;
     230           0 :         imageCache=other.imageCache;
     231           0 :         cachesize=other.cachesize;
     232           0 :         tilesize=other.tilesize;
     233           0 :         cfRefFreq_p = other.cfRefFreq_p;
     234           0 :         if(other.gridder==0) gridder=0;
     235             :         else
     236             :           {
     237           0 :             uvScale.resize();
     238           0 :             uvOffset.resize();
     239           0 :             uvScale=other.uvScale;
     240           0 :             uvOffset=other.uvOffset;
     241           0 :             gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     242           0 :                                                            uvScale, uvOffset,
     243           0 :                                                            "SF");
     244             :           }
     245             : 
     246           0 :         isTiled=other.isTiled;
     247           0 :         lattice=0;
     248           0 :         arrayLattice=0;
     249             : 
     250           0 :         maxAbsData=other.maxAbsData;
     251           0 :         centerLoc=other.centerLoc;
     252           0 :         offsetLoc=other.offsetLoc;
     253           0 :         pointingToImage=other.pointingToImage;
     254           0 :         usezero_p=other.usezero_p;
     255             : 
     256             :         
     257           0 :         padding_p=other.padding_p;
     258           0 :         nWPlanes_p=other.nWPlanes_p;
     259           0 :         imageCache=other.imageCache;
     260           0 :         cachesize=other.cachesize;
     261           0 :         tilesize=other.tilesize;
     262           0 :         isTiled=other.isTiled;
     263           0 :         maxAbsData=other.maxAbsData;
     264           0 :         centerLoc=other.centerLoc;
     265           0 :         offsetLoc=other.offsetLoc;
     266           0 :         mspc=other.mspc;
     267           0 :         msac=other.msac;
     268           0 :         pointingToImage=other.pointingToImage;
     269           0 :         usezero_p=other.usezero_p;
     270           0 :         doPBCorrection = other.doPBCorrection;
     271           0 :         maxConvSupport= other.maxConvSupport;
     272             : 
     273           0 :         epJ=other.epJ;
     274           0 :         convSize=other.convSize;
     275           0 :         lastIndex_p=other.lastIndex_p;
     276           0 :         paChangeDetector=other.paChangeDetector;
     277           0 :         pbLimit_p=other.pbLimit_p;
     278             :         //
     279             :         // Get various parameters from the visibilities.  
     280             :         //
     281           0 :         bandID_p = other.bandID_p;
     282           0 :         doPointing=other.doPointing;
     283             : 
     284           0 :         convFuncCacheReady=other.convFuncCacheReady;
     285           0 :         PAIndex = other.PAIndex;
     286           0 :         maxConvSupport=other.maxConvSupport;
     287             :         //
     288             :         // Set up the Conv. Func. disk cache manager object.
     289             :         //
     290           0 :         cfCache=other.cfCache;
     291           0 :         convSampling=other.convSampling;
     292           0 :         convSize=other.convSize;
     293           0 :         cachesize=other.cachesize;
     294             :     
     295           0 :         resetPBs=other.resetPBs;
     296           0 :         pbNormalized=other.pbNormalized;
     297           0 :         currentCFPA=other.currentCFPA;
     298           0 :         lastPAUsedForWtImg = other.lastPAUsedForWtImg;
     299           0 :         cfStokes=other.cfStokes;
     300           0 :         Area=other.Area;
     301           0 :         avgPB = other.avgPB;
     302           0 :         avgPBReady = other.avgPBReady;
     303             :       };
     304           0 :     return *this;
     305             :   };
     306             :   //
     307             :   //---------------------------------------------------------------------
     308             :   //
     309           0 :   int nPBWProjectFT::getVisParams(const VisBuffer& vb)
     310             :   {
     311             :     Double Freq;
     312           0 :     Vector<String> telescopeNames=vb.msColumns().observation().telescopeName().getColumn();
     313           0 :     for(uInt nt=0;nt<telescopeNames.nelements();nt++)
     314             :       {
     315           0 :         if ((telescopeNames(nt) != "VLA") && (telescopeNames(nt) != "EVLA"))
     316             :           {
     317           0 :             String mesg="pbwproject algorithm can handle only (E)VLA antennas for now.\n";
     318           0 :             mesg += "Erroneous telescope name = " + telescopeNames(nt) + ".";
     319           0 :             SynthesisError err(mesg);
     320           0 :             throw(err);
     321             :           }
     322           0 :         if (telescopeNames(nt) != telescopeNames(0))
     323             :           {
     324           0 :             String mesg="pbwproject algorithm does not (yet) handle inhomogeneous arrays!\n";
     325           0 :             mesg += "Not yet a \"priority\"!!";
     326           0 :             SynthesisError err(mesg);
     327           0 :             throw(err);
     328             :           }
     329             :       }
     330             :     //    MSSpWindowColumns mssp(vb.msColumns().spectralWindow());
     331           0 :     Freq = vb.msColumns().spectralWindow().refFrequency()(0);
     332           0 :     Diameter_p=0;
     333           0 :     Nant_p     = vb.msColumns().antenna().nrow();
     334           0 :     for (Int i=0; i < Nant_p; i++)
     335           0 :       if (!vb.msColumns().antenna().flagRow()(i))
     336             :         {
     337           0 :           Diameter_p = vb.msColumns().antenna().dishDiameter()(i);
     338           0 :           break;
     339             :         }
     340           0 :     if (Diameter_p == 0)
     341             :       {
     342           0 :         logIO() << LogOrigin("nPBWProjectFT", "getVisParams")
     343             :                 << "No valid or finite sized antenna found in the antenna table. "
     344             :                 << "Assuming diameter = 25m."
     345             :                 << LogIO::WARN
     346           0 :                 << LogIO::POST;
     347           0 :         Diameter_p=25.0;
     348             :       }
     349             :     
     350           0 :     Double Lambda=C::c/Freq;
     351           0 :     HPBW = Lambda/(Diameter_p*sqrt(log(2.0)));
     352           0 :     sigma = 1.0/(HPBW*HPBW);
     353           0 :     nwEij.setSigma(sigma);
     354           0 :     Int bandID = BeamCalc::Instance()->getBandID(Freq,telescopeNames(0),"");
     355             :     //    Int bandID = getVLABandID(Freq,telescopeNames(0));
     356           0 :     return bandID;
     357             :   }
     358             :   //
     359             :   //----------------------------------------------------------------------
     360             :   //
     361           0 :   void nPBWProjectFT::init() 
     362             :   {
     363           0 :     nx    = image->shape()(0);
     364           0 :     ny    = image->shape()(1);
     365           0 :     npol  = image->shape()(2);
     366           0 :     nchan = image->shape()(3);
     367             :     
     368           0 :     if(image->shape().product()>cachesize) 
     369           0 :       isTiled=true;
     370             :     else 
     371           0 :       isTiled=false;
     372             :     
     373           0 :     sumWeight.resize(npol, nchan);
     374             :     
     375           0 :     wConvSize=max(1, nWPlanes_p);
     376           0 :     if (!convFuncCacheReady) 
     377             :       {
     378           0 :         if (convSupport.shape()(0) != wConvSize)
     379             :           {
     380           0 :             convSupport.resize(wConvSize,1,1,true);
     381           0 :             convSupport=0;
     382             :           }
     383             :       }
     384             :     
     385           0 :     uvScale.resize(3);
     386           0 :     uvScale=0.0;
     387           0 :     uvScale(0)=Float(nx)*image->coordinates().increment()(0); 
     388           0 :     uvScale(1)=Float(ny)*image->coordinates().increment()(1); 
     389           0 :     uvScale(2)=Float(wConvSize)*abs(image->coordinates().increment()(0));
     390             :     
     391           0 :     uvOffset.resize(3);
     392           0 :     uvOffset(0)=nx/2;
     393           0 :     uvOffset(1)=ny/2;
     394           0 :     uvOffset(2)=0;
     395             :     
     396           0 :     if(gridder) delete gridder; gridder=0;
     397           0 :     gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     398           0 :                                                    uvScale, uvOffset,
     399           0 :                                                    "SF");
     400             :     
     401             :     // Set up image cache needed for gridding. 
     402           0 :     if(imageCache) delete imageCache;   imageCache=0;
     403             :     
     404             :     // The tile size should be large enough that the
     405             :     // extended convolution function can fit easily
     406           0 :     if(isTiled) 
     407             :       {
     408           0 :         Float tileOverlap=0.5;
     409           0 :         tilesize=min(256,tilesize);
     410           0 :         IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
     411           0 :         Vector<Float> tileOverlapVec(4);
     412           0 :         tileOverlapVec=0.0;
     413           0 :         tileOverlapVec(0)=tileOverlap;
     414           0 :         tileOverlapVec(1)=tileOverlap;
     415             :         if (sizeof(long) < 4)  // 32-bit machine
     416             :           {
     417             :             Int tmpCacheVal=static_cast<Int>(cachesize);
     418             :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     419             :                                                    tileOverlapVec,
     420             :                                                    (tileOverlap>0.0));
     421             :           }
     422             :         else  // 64-bit machine
     423             :           {
     424           0 :             Long tmpCacheVal=cachesize;
     425           0 :             imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     426             :                                                    tileOverlapVec,
     427           0 :                                                    (tileOverlap>0.0));
     428             :           }
     429             :       }
     430             :     
     431             : #if(USETABLES)
     432             :     Double StepSize;
     433             :     Int N=500000;
     434             :     StepSize = abs((((2*nx)/uvScale(0))/(sigma) + 
     435             :                     MAXPOINTINGERROR*1.745329E-02*(sigma)/3600.0))/N;
     436             :     if (!nwEij.isReady())
     437             :       {
     438             :         logIO() << LogOrigin("nPBWProjectFT","init")
     439             :                 << "Making lookup table for exp function with a resolution of " 
     440             :                 << StepSize << " radians.  "
     441             :                 << "Memory used: " << sizeof(Float)*N/(1024.0*1024.0)<< " MB." 
     442             :                 << LogIO::NORMAL 
     443             :                 <<LogIO::POST;
     444             :         
     445             :         nwEij.setSigma(sigma);
     446             :         nwEij.initExpTable(N,StepSize);
     447             :         //    ExpTab.build(N,StepSize);
     448             :         
     449             :         logIO() << LogOrigin("nPBWProjectFT","init")
     450             :                 << "Making lookup table for complex exp function with a resolution of " 
     451             :                 << 2*M_PI/N << " radians.  "
     452             :                 << "Memory used: " << 2*sizeof(Float)*N/(1024.0*1024.0) << " MB." 
     453             :                 << LogIO::NORMAL
     454             :                 << LogIO::POST;
     455             :         nwEij.initCExpTable(N);
     456             :         //    CExpTab.build(N);
     457             :       }
     458             : #endif
     459             :     //    vpSJ->reset();
     460           0 :     paChangeDetector.reset();
     461           0 :     makingPSF = false;
     462           0 :   }
     463             :   //
     464             :   //---------------------------------------------------------------
     465             :   //
     466             :   // This is nasty, we should use CountedPointers here.
     467           0 :   nPBWProjectFT::~nPBWProjectFT() 
     468             :   {
     469           0 :       if(imageCache) delete imageCache; imageCache=0;
     470           0 :       if(gridder) delete gridder; gridder=0;
     471             :       
     472           0 :       Int NCF=convFuncCache.nelements();
     473           0 :       for(Int i=0;i<NCF;i++) delete convFuncCache[i];
     474           0 :       NCF=convWeightsCache.nelements();
     475           0 :       for(Int i=0;i<NCF;i++) delete convWeightsCache[i];
     476           0 :   }
     477             :   //
     478             :   //---------------------------------------------------------------
     479             :   //
     480           0 :   Int nPBWProjectFT::makePBPolnCoords(CoordinateSystem& squintCoord,const VisBuffer&vb)
     481             :   {
     482             :     //
     483             :     // Make an image with circular polarization axis.
     484             :     //
     485           0 :     Int NPol=0,M,N=0;
     486           0 :     M=polMap.nelements();
     487           0 :     for(Int i=0;i<M;i++) if (polMap(i) > -1) NPol++;
     488           0 :     Vector<Int> poln(NPol);
     489             :     
     490             :     Int index;
     491           0 :     Vector<Int> inStokes;
     492           0 :     index = squintCoord.findCoordinate(Coordinate::STOKES);
     493           0 :     inStokes = squintCoord.stokesCoordinate(index).stokes();
     494           0 :     N = 0;
     495             :     try
     496             :       {
     497           0 :         for(Int i=0;i<M;i++) if (polMap(i) > -1) {poln(N) = vb.corrType()(i);N++;}
     498           0 :         StokesCoordinate polnCoord(poln);
     499           0 :         Int StokesIndex = squintCoord.findCoordinate(Coordinate::STOKES);
     500           0 :         squintCoord.replaceCoordinate(polnCoord,StokesIndex);
     501           0 :         cfStokes = poln;
     502             :       }
     503           0 :     catch(AipsError& x)
     504             :       {
     505             :         throw(SynthesisFTMachineError("Likely cause: Discrepancy between the poln. "
     506           0 :                                       "axis of the data and the image specifications."));
     507             :       }
     508             :     
     509           0 :     return NPol;
     510             :   }
     511             :   //
     512             :   //---------------------------------------------------------------
     513             :   //
     514           0 :   MDirection::Convert nPBWProjectFT::makeCoordinateMachine(const VisBuffer& vb,
     515             :                                                            const MDirection::Types& From,
     516             :                                                            const MDirection::Types& To,
     517             :                                                            MEpoch& last)
     518             :   {
     519           0 :     Double time = getCurrentTimeStamp(vb);
     520             :     
     521           0 :     MEpoch epoch(Quantity(time,Second),MEpoch::TAI);
     522             :     //  epoch = MEpoch(Quantity(time,Second),MEpoch::TAI);
     523             :     //
     524             :     // ...now make an object to hold the observatory position info...
     525             :     //
     526           0 :     MPosition pos;
     527           0 :     String ObsName=vb.msColumns().observation().telescopeName()(vb.arrayId());
     528             :     
     529           0 :     if (!MeasTable::Observatory(pos,ObsName))
     530           0 :       throw(AipsError("Observatory position for "+ ObsName + " not found"));
     531             :     //
     532             :     // ...now make a Frame object out of the observatory position and
     533             :     // time objects...
     534             :     //
     535           0 :     MeasFrame frame(epoch,pos);
     536             :     //
     537             :     // ...finally make the convert machine.
     538             :     //
     539           0 :     MDirection::Convert mac(MDirection::Ref(From,frame),
     540           0 :                             MDirection::Ref(To,frame));
     541             :     
     542           0 :     MEpoch::Convert toLAST = MEpoch::Convert(MEpoch::Ref(MEpoch::TAI,frame),
     543           0 :                                              MEpoch::Ref(MEpoch::LAST,frame));
     544           0 :     last = toLAST(epoch);
     545             :     
     546           0 :     return mac;
     547             :   }
     548             :   //
     549             :   //---------------------------------------------------------------
     550             :   //
     551           0 :   int nPBWProjectFT::findPointingOffsets(const VisBuffer& vb, 
     552             :                                         Array<Float> &l_off,
     553             :                                         Array<Float> &m_off,
     554             :                                         Bool Evaluate)
     555             :   {
     556             : 
     557             :     //    throw(AipsError("PBWProject::findPointingOffsets temporarily disabled. (gmoellen 06Nov10)"));
     558             : 
     559           0 :     Int NAnt = 0;
     560           0 :     MEpoch LAST;
     561           0 :     Double thisTime = getCurrentTimeStamp(vb);
     562             :     //    Array<Float> pointingOffsets = epJ->nearest(thisTime);
     563           0 :     if (epJ==NULL) return 0;
     564           0 :     Array<Float> pointingOffsets; epJ->nearest(thisTime,pointingOffsets);
     565           0 :     NAnt=pointingOffsets.shape()(2);
     566           0 :     l_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     567           0 :     m_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     568             :     // Can't figure out how to do the damn slicing of [Pol,NChan,NAnt,1] array
     569             :     // into [Pol,NChan,NAnt] array
     570             :     //
     571             :     //    l_off = pointingOffsets(Slicer(IPosition(4,0,0,0,0),IPosition(4,1,1,NAnt+1,0)));
     572             :     //    m_off = pointingOffsets(Slicer(IPosition(4,1,0,0,0),IPosition(4,1,1,NAnt+1,0)));
     573           0 :     IPosition tndx(3,0,0,0), sndx(4,0,0,0,0);
     574           0 :     for(tndx(2)=0;tndx(2)<NAnt; tndx(2)++,sndx(2)++)
     575             :       //    for(Int j=0;j<NAnt;j++)
     576             :       {
     577             :         // l_off(IPosition(3,0,0,j)) = pointingOffsets(IPosition(4,0,0,j,0));
     578             :         // m_off(IPosition(3,0,0,j)) = pointingOffsets(IPosition(4,1,0,j,0));
     579             : 
     580           0 :         sndx(0)=0; l_off(tndx) = pointingOffsets(sndx);
     581           0 :         sndx(0)=2; m_off(tndx) = pointingOffsets(sndx);
     582             :       }
     583           0 :     return NAnt;
     584             :     if (!Evaluate) return NAnt;
     585             :     
     586             :     //  cout << "AzEl Offsets: " << pointingOffsets << endl;
     587             :     //
     588             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     589             :     // (HA,Dec).
     590             :     //
     591             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     592             :                                                        MDirection::AZEL,
     593             :                                                        LAST);
     594             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     595             :                                                         MDirection::HADEC,
     596             :                                                         LAST);
     597             :     //
     598             :     // ...and now hope that it all works and works correctly!!!
     599             :     //
     600             :     Quantity dAz(0,Radian),dEl(0,Radian);
     601             :     //
     602             :     // An array of shape [2,1,1]!
     603             :     //
     604             :     Array<Double> phaseDir = vb.msColumns().field().phaseDir().getColumn();
     605             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     606             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     607             :     //  
     608             :     // Compute reference (HA,Dec)
     609             :     //
     610             :     Double LST   = LAST.get(Day).getValue();
     611             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     612             :     LST -= floor(LST); // Extract the fractional day
     613             :     LST *= 2*C::pi;// Convert to Raidan
     614             :     
     615             :     Double HA0;
     616             :     HA0 = LST - RA0;
     617             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     618             :     //
     619             :     // Convert reference (HA,Dec) to reference (Az,El)
     620             :     //
     621             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     622             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     623             :     
     624             :     MDirection tmpHADec = toHADec(AzEl0);
     625             :     
     626             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     627             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     628             :     
     629             :     //
     630             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     631             :     //
     632             :     
     633             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     634             :       {
     635             :         //
     636             :         // From (Az,El) -> (HA,Dec)
     637             :         //
     638             :         // Add (Az,El) offsets to the reference (Az,El)
     639             :         //
     640             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     641             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     642             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     643             :         //
     644             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     645             :         //
     646             :         MDirection HADec = toHADec(AzEl);
     647             :         Double HA,Dec,RA, dRA;
     648             :         HA  = HADec.getAngle(Radian).getValue()(0);
     649             :         Dec = HADec.getAngle(Radian).getValue()(1);
     650             :         RA  = LST - HA;
     651             :         dRA = RA - RA0;
     652             :         //
     653             :         // Convert offsetted (RA,Dec) -> (l,m)
     654             :         //
     655             :         l_off(n)  = sin(dRA)*cos(Dec);
     656             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     657             :         //      cout << "FindOff: " << n(2) << " " << l_offsets(n) << " " << m_offsets(n) << endl;
     658             :         
     659             :         //       cout << l_off(n) << " " << m_off(n) << " "
     660             :         //         << " " << HA << " " << Dec
     661             :         //         << " " << LST << " " << RA0 << " " << Dec0 
     662             :         //         << " " << RA << " " << Dec
     663             :         //         << endl;
     664             :       }
     665             :     
     666             :     return NAnt+1;
     667             :   }
     668             :   //
     669             :   //---------------------------------------------------------------
     670             :   //
     671           0 :   int nPBWProjectFT::findPointingOffsets(const VisBuffer& vb, 
     672             :                                          Cube<Float>& pointingOffsets,
     673             :                                         Array<Float> &l_off,
     674             :                                         Array<Float> &m_off,
     675             :                                         Bool Evaluate)
     676             :   {
     677           0 :     Int NAnt = 0;
     678             :     // TBD: adapt the following to VisCal mechanism:
     679           0 :     MEpoch LAST;
     680             :     
     681           0 :     NAnt=pointingOffsets.shape()(2);
     682           0 :     l_off.resize(IPosition(3,2,1,NAnt));
     683           0 :     m_off.resize(IPosition(3,2,1,NAnt));
     684           0 :     IPosition ndx(3,0,0,0),ndx1(3,0,0,0);
     685           0 :     for(ndx(2)=0;ndx(2)<NAnt;ndx(2)++)
     686             :       {
     687           0 :         ndx1=ndx;
     688           0 :         ndx(0)=0;ndx1(0)=0;     l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_0,Ant_i
     689           0 :         ndx(0)=1;ndx1(0)=1;     l_off(ndx)  = pointingOffsets(ndx1);//Axis_0,Pol_1,Ant_i
     690           0 :         ndx(0)=0;ndx1(0)=2;     m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_0,Ant_i
     691           0 :         ndx(0)=1;ndx1(0)=3;     m_off(ndx)  = pointingOffsets(ndx1);//Axis_1,Pol_1,Ant_i
     692             :       }
     693             : 
     694             : //     l_off  = pointingOffsets(IPosition(3,0,0,0),IPosition(3,0,0,NAnt));
     695             : //     m_off = pointingOffsets(IPosition(3,1,0,0),IPosition(3,1,0,NAnt));
     696             :     /*
     697             :     IPosition shp(pointingOffsets.shape());
     698             :     IPosition shp1(l_off.shape()),shp2(m_off.shape());
     699             :     for(Int ii=0;ii<NAnt;ii++)
     700             :       {
     701             :         IPosition ndx(3,0,0,0);
     702             :         ndx(2)=ii;
     703             :         cout << "Pointing Offsets: " << ii << " " 
     704             :              << l_off(ndx)*57.295*60.0 << " " 
     705             :              << m_off(ndx)*57.295*60.0 << endl;
     706             :       }
     707             :     */
     708           0 :     return NAnt;
     709             :     if (!Evaluate) return NAnt;
     710             :     
     711             :     //
     712             :     // Make a Coordinate Conversion Machine to go from (Az,El) to
     713             :     // (HA,Dec).
     714             :     //
     715             :     MDirection::Convert toAzEl = makeCoordinateMachine(vb,MDirection::HADEC,
     716             :                                                        MDirection::AZEL,
     717             :                                                        LAST);
     718             :     MDirection::Convert toHADec = makeCoordinateMachine(vb,MDirection::AZEL,
     719             :                                                         MDirection::HADEC,
     720             :                                                         LAST);
     721             :     //
     722             :     // ...and now hope that it all works and works correctly!!!
     723             :     //
     724             :     Quantity dAz(0,Radian),dEl(0,Radian);
     725             :     //
     726             :     // An array of shape [2,1,1]!
     727             :     //
     728             :     Array<Double> phaseDir = vb.msColumns().field().phaseDir().getColumn();
     729             :     Double RA0   = phaseDir(IPosition(3,0,0,0));
     730             :     Double Dec0  = phaseDir(IPosition(3,1,0,0));
     731             :     //  
     732             :     // Compute reference (HA,Dec)
     733             :     //
     734             :     Double LST   = LAST.get(Day).getValue();
     735             :     Double SDec0 = sin(Dec0), CDec0=cos(Dec0);
     736             :     LST -= floor(LST); // Extract the fractional day
     737             :     LST *= 2*C::pi;// Convert to Raidan
     738             :     
     739             :     Double HA0;
     740             :     HA0 = LST - RA0;
     741             :     Quantity QHA0(HA0,Radian), QDEC0(Dec0,Radian);
     742             :     //
     743             :     // Convert reference (HA,Dec) to reference (Az,El)
     744             :     //
     745             :     MDirection PhaseCenter(QHA0, QDEC0,MDirection::Ref(MDirection::HADEC));
     746             :     MDirection AzEl0 = toAzEl(PhaseCenter);
     747             :     
     748             :     MDirection tmpHADec = toHADec(AzEl0);
     749             :     
     750             :     Double Az0_Rad = AzEl0.getAngle(Radian).getValue()(0);
     751             :     Double El0_Rad = AzEl0.getAngle(Radian).getValue()(1);
     752             :     
     753             :     //
     754             :     // Convert the antenna pointing offsets from (Az,El)-->(RA,Dec)-->(l,m) 
     755             :     //
     756             :     
     757             :     for(IPosition n(3,0,0,0);n(2)<=NAnt;n(2)++)
     758             :       {
     759             :         //
     760             :         // From (Az,El) -> (HA,Dec)
     761             :         //
     762             :         // Add (Az,El) offsets to the reference (Az,El)
     763             :         //
     764             :         dAz.setValue(l_off(n)+Az0_Rad);  dEl.setValue(m_off(n)+El0_Rad);
     765             :         //      dAz.setValue(0.0+Az0_Rad);  dEl.setValue(0.0+El0_Rad);
     766             :         MDirection AzEl(dAz,dEl,MDirection::Ref(MDirection::AZEL));
     767             :         //
     768             :         // Convert offsetted (Az,El) to (HA,Dec) and then to (RA,Dec)
     769             :         //
     770             :         MDirection HADec = toHADec(AzEl);
     771             :         Double HA,Dec,RA, dRA;
     772             :         HA  = HADec.getAngle(Radian).getValue()(0);
     773             :         Dec = HADec.getAngle(Radian).getValue()(1);
     774             :         RA  = LST - HA;
     775             :         dRA = RA - RA0;
     776             :         //
     777             :         // Convert offsetted (RA,Dec) -> (l,m)
     778             :         //
     779             :         l_off(n)  = sin(dRA)*cos(Dec);
     780             :         m_off(n) = sin(Dec)*CDec0-cos(Dec)*SDec0*cos(dRA);
     781             :         //      cout << "FindOff: " << n(2) << " " << l_offsets(n) << " " << m_offsets(n) << endl;
     782             :         
     783             :         //       cout << l_off(n) << " " << m_off(n) << " "
     784             :         //         << " " << HA << " " << Dec
     785             :         //         << " " << LST << " " << RA0 << " " << Dec0 
     786             :         //         << " " << RA << " " << Dec
     787             :         //         << endl;
     788             :       }
     789             :     
     790             :     return NAnt+1;
     791             :   }
     792             :   //
     793             :   //---------------------------------------------------------------
     794             :   //
     795           0 :   void nPBWProjectFT::makeSensitivityImage(Lattice<Complex>& wtImage,
     796             :                                            ImageInterface<Float>& sensitivityImage,
     797             :                                            const Matrix<Float>& sumWt,
     798             :                                            const Bool& doFFTNorm)
     799             :   {
     800           0 :     Bool doSumWtNorm=true;
     801           0 :     if (sumWt.shape().nelements()==0) doSumWtNorm=false;
     802             : 
     803           0 :     if ((sumWt.shape().nelements() < 2) || 
     804           0 :         (sumWt.shape()(0) != wtImage.shape()(2)) || 
     805           0 :         (sumWt.shape()(1) != wtImage.shape()(3)))
     806             :       throw(AipsError("makeSensitivityImage(): "
     807           0 :                       "Sum of weights per poln and chan required"));
     808           0 :     Float sumWtVal=1.0;
     809             : 
     810           0 :     LatticeFFT::cfft2d(wtImage,false);
     811           0 :     Int sizeX=wtImage.shape()(0), sizeY=wtImage.shape()(1);
     812           0 :     sensitivityImage.resize(wtImage.shape());
     813           0 :     Array<Float> senBuf;
     814           0 :     sensitivityImage.get(senBuf,false);
     815           0 :     ArrayLattice<Float> senLat(senBuf, true);
     816             : 
     817             :     //
     818             :     // Copy one 2D plane at a time, normalizing by the sum of weights
     819             :     // and possibly 2D FFT.
     820             :     //
     821             :     // Set up Lattice iteratos on wtImage and sensitivityImage
     822             :     //
     823           0 :     IPosition axisPath(4, 0, 1, 2, 3);
     824           0 :     IPosition cursorShape(4, sizeX, sizeY, 1, 1);
     825           0 :     LatticeStepper wtImStepper(wtImage.shape(), cursorShape, axisPath);
     826           0 :     LatticeIterator<Complex> wtImIter(wtImage, wtImStepper);
     827           0 :     LatticeStepper senImStepper(senLat.shape(), cursorShape, axisPath);
     828           0 :     LatticeIterator<Float> senImIter(senLat, senImStepper);
     829             :     //
     830             :     // Iterate over channel and polarization axis
     831             :     //
     832           0 :     if (!doFFTNorm) sizeX=sizeY=1;
     833           0 :     for(wtImIter.reset(),senImIter.reset();  !wtImIter.atEnd(); wtImIter++,senImIter++) 
     834             :       {
     835           0 :         Int pol=wtImIter.position()(2), chan=wtImIter.position()(3);
     836           0 :         if (doSumWtNorm) sumWtVal=sumWt(pol,chan);
     837           0 :         senImIter.rwCursor() = (real(wtImIter.rwCursor())
     838           0 :                                 *Float(sizeX)*Float(sizeY)/sumWtVal);
     839             :       }
     840             :     //
     841             :     // The following code is averaging RR and LL planes and writing
     842             :     // the result to back to both planes.  This needs to be
     843             :     // generalized for full-pol case.
     844             :     //
     845           0 :     IPosition start0(4,0,0,0,0), start1(4,0,0,1,0), length(4,sizeX,sizeY,1,1);
     846           0 :     Slicer slicePol0(start0,length), slicePol1(start1,length);
     847           0 :     Array<Float> polPlane0, polPlane1;
     848           0 :     senLat.getSlice(polPlane0,slicePol0);
     849           0 :     senLat.getSlice(polPlane1,slicePol1);
     850           0 :     polPlane0=(polPlane0+polPlane1)/2.0;
     851           0 :     polPlane1=polPlane0;
     852             :     // senLat.putSlice(polPlane0,IPosition(4,0,0,0,0));
     853             :     // senLat.putSlice(polPlane1,IPosition(4,0,0,1,0));
     854             :     // cerr << "Pol0: " << polPlane0.shape() << " " << max(polPlane0) << endl;
     855             :     // cerr << "Pol1: " << polPlane1.shape() << " " << max(polPlane1) << endl;
     856           0 :   }
     857             :   //
     858             :   //---------------------------------------------------------------
     859             :   //
     860           0 :   void nPBWProjectFT::normalizeAvgPB()
     861             :   {
     862           0 :     if (!pbNormalized)
     863             :       {
     864           0 :         pbPeaks.resize(avgPB.shape()(2),true);
     865           0 :         if (makingPSF) pbPeaks = 1.0;
     866           0 :         else pbPeaks /= (Float)noOfPASteps;
     867           0 :         pbPeaks = 1.0;
     868           0 :         logIO() << LogOrigin("nPBWProjectFT", "normalizeAvgPB")  
     869             :                 << "Normalizing the average PBs to " << 1.0
     870             :                 << LogIO::NORMAL
     871           0 :                 << LogIO::POST;
     872             :         
     873           0 :         IPosition avgPBShape(avgPB.shape()),ndx(4,0,0,0,0);
     874           0 :         Vector<Float> peak(avgPBShape(2));
     875             :         
     876             :         Bool isRefF;
     877           0 :         Array<Float> avgPBBuf;
     878           0 :         isRefF=avgPB.get(avgPBBuf);
     879             :         
     880           0 :         Float pbMax = max(avgPBBuf);
     881             : 
     882           0 :         ndx=0;
     883           0 :         for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     884           0 :           for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     885             :             {
     886           0 :               IPosition plane1(ndx);
     887           0 :               plane1=ndx;
     888           0 :               plane1(2)=1; // The other poln. plane
     889           0 :               avgPBBuf(ndx) = (avgPBBuf(ndx) + avgPBBuf(plane1))/2.0;
     890             :             }
     891           0 :         for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     892           0 :           for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     893             :             {
     894           0 :               IPosition plane1(ndx);
     895           0 :               plane1=ndx;
     896           0 :               plane1(2)=1; // The other poln. plane
     897           0 :               avgPBBuf(plane1) = avgPBBuf(ndx);
     898             :             }
     899           0 :         if (fabs(pbMax-1.0) > 1E-3)
     900             :           {
     901             :             //      avgPBBuf = avgPBBuf/noOfPASteps;
     902           0 :             for(ndx(3)=0;ndx(3)<avgPBShape(3);ndx(3)++)
     903           0 :               for(ndx(2)=0;ndx(2)<avgPBShape(2);ndx(2)++)
     904             :                 {
     905           0 :                   peak(ndx(2)) = 0;
     906           0 :                   for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     907           0 :                     for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     908           0 :                       if (abs(avgPBBuf(ndx)) > peak(ndx(2)))
     909           0 :                         peak(ndx(2)) = avgPBBuf(ndx);
     910             :               
     911           0 :                   for(ndx(1)=0;ndx(1)<avgPBShape(1);ndx(1)++)
     912           0 :                     for(ndx(0)=0;ndx(0)<avgPBShape(0);ndx(0)++)
     913           0 :                       avgPBBuf(ndx) *= (pbPeaks(ndx(2))/peak(ndx(2)));
     914             :                 }
     915           0 :             if (isRefF) avgPB.put(avgPBBuf);
     916             :           }
     917             :       }
     918           0 :     pbNormalized = true;
     919           0 :   }
     920             :   //
     921             :   //---------------------------------------------------------------
     922             :   //
     923           0 :   Bool nPBWProjectFT::makeAveragePB0(const VisBuffer& vb, 
     924             :                                      const ImageInterface<Complex>& image,
     925             :                                      Int& /*polInUse*/,
     926             :                                      //TempImage<Float>& thesquintPB,
     927             :                                      TempImage<Float>& theavgPB)
     928             :   {
     929           0 :     TempImage<Float> localPB;
     930             :     
     931           0 :     logIO() << LogOrigin("nPBWProjecFT","makeAveragePB")
     932           0 :             << LogIO::NORMAL;
     933             :     
     934           0 :     localPB.resize(image.shape()); localPB.setCoordinateInfo(image.coordinates());
     935           0 :     localPB.setMaximumCacheSize(cachesize);
     936             :     // cerr << "Max. cache size = " << localPB.maximumCacheSize() << " " << cachesize << endl;
     937             :     //
     938             :     // If this is the first time, resize the average PB
     939             :     //
     940           0 :     if (resetPBs)
     941             :       {
     942             :         logIO() << "Initializing the average PBs"
     943             :                 << LogIO::NORMAL
     944           0 :                 << LogIO::POST;
     945           0 :         theavgPB.resize(localPB.shape()); 
     946           0 :         theavgPB.setCoordinateInfo(localPB.coordinates());
     947           0 :         theavgPB.set(0.0);
     948           0 :         noOfPASteps = 0;
     949           0 :         pbPeaks.resize(theavgPB.shape()(2));
     950           0 :         pbPeaks.set(0.0);
     951           0 :         resetPBs=false;
     952             :       }
     953             :     //
     954             :     // Make the Stokes PB
     955             :     //
     956           0 :     localPB.set(1.0);
     957             : 
     958             :     // The following replaces the simple vlaPB.applyPB() call.
     959             :     // The functional interface of VLACalcIllumination was
     960             :     // modified to apply one polarization PB at a time.  As a
     961             :     // result, the co-ord. sys. of the image going to applyPB()
     962             :     // should have only one Poln. plane.
     963             :     //
     964             :     // Before this change, the localPB image was directly sent to
     965             :     // applyPB(). Now, in the code below, we go over the poln. planes
     966             :     // of this image, make a temp. image with one poln. planes of
     967             :     // localPB at a time, applyPB() on the temp. image, and copy the
     968             :     // result in the appropriate planes of the localPB image.  The rest
     969             :     // of the code therefore does not see a difference.
     970             :     {
     971           0 :       VLACalcIlluminationConvFunc vlaPB;
     972           0 :       if (bandID_p == -1) bandID_p=getVisParams(vb);
     973           0 :       CoordinateSystem coords=localPB.coordinates();
     974             :       //----------------------------------------------------------------------
     975           0 :       IPosition PolnPlane(4,0,0,0,0);
     976           0 :       CoordinateSystem singlePolCoords=coords;
     977           0 :       Int index, outNdx, whichPolPlane=0;
     978           0 :       Vector<Int> inStokes, outStokes(1);
     979           0 :       index = coords.findCoordinate(Coordinate::STOKES);
     980           0 :       inStokes = coords.stokesCoordinate(index).stokes();
     981           0 :       for (uInt i=0; i<inStokes.nelements(); i++)
     982             :         {
     983           0 :           outStokes(0)=inStokes(i);
     984             :           // Make a temp. image with a single Stokes along Pol. axis.
     985           0 :           StokesCoordinate polnCoord(outStokes);
     986           0 :           outNdx = singlePolCoords.findCoordinate(Coordinate::STOKES);
     987           0 :           singlePolCoords.replaceCoordinate(polnCoord, outNdx);
     988           0 :           IPosition singlePolShape = localPB.shape();
     989           0 :           singlePolShape(2)=1;
     990           0 :           Bool doSquint=false;
     991             :           {
     992           0 :             TempImage<Float> singlePolImg(singlePolShape, singlePolCoords);
     993             :             // Copy screen to the single pol. image.  Apply PB to it.  Copy 
     994             :             // the single pol. image plane to the twoDPB image.
     995           0 :             singlePolImg.set(1.0);
     996           0 :             Double pa=getPA(vb);
     997           0 :             Vector<Double> chanFreq = vb.frequency();
     998             :             //freqHi = max(chanFreq);
     999           0 :             Double Freq = max(chanFreq);
    1000             : 
    1001           0 :             vlaPB.applyPB(singlePolImg, pa, bandID_p, doSquint, Freq);
    1002           0 :             PolnPlane(2)=whichPolPlane;   localPB.putSlice(singlePolImg.get(), PolnPlane);
    1003             :           }
    1004           0 :           whichPolPlane++;
    1005             :         }
    1006             :       //----------------------------------------------------------------------
    1007             : 
    1008             :       //      vlaPB.applyPB(localPB, vb, bandID_p);
    1009             :     }
    1010             :     
    1011           0 :     IPosition twoDPBShape(localPB.shape());
    1012           0 :     TempImage<Complex> localTwoDPB(twoDPBShape,localPB.coordinates());
    1013           0 :     localTwoDPB.setMaximumCacheSize(cachesize);
    1014           0 :     Float peak=0;
    1015             :     Int NAnt;
    1016           0 :     noOfPASteps++;
    1017           0 :     NAnt=1;
    1018             :    
    1019             : //     logIO() << " Shape of localPB Cube : " << twoDPBShape << LogIO::POST;
    1020             : //     logIO() << " Shape of avgPB Cube : " << theavgPB.shape() << LogIO::POST;
    1021             : 
    1022           0 :     for(Int ant=0;ant<NAnt;ant++)
    1023             :       { //Ant loop
    1024             :         {
    1025           0 :           IPosition ndx(4,0,0,0,0);
    1026           0 :           for(ndx(0)=0; ndx(0)<twoDPBShape(0); ndx(0)++)
    1027           0 :             for(ndx(1)=0; ndx(1)<twoDPBShape(1); ndx(1)++)
    1028           0 :               for(ndx(2)=0; ndx(2)<twoDPBShape(2); ndx(2)++)
    1029           0 :                for(ndx(3)=0; ndx(3)<twoDPBShape(3); ndx(3)++)
    1030           0 :                   localTwoDPB.putAt(Complex((localPB(ndx)),0.0),ndx);
    1031             :         }
    1032             :         //
    1033             :         // If antenna pointing errors are not applied, no shifting
    1034             :         // (which can be expensive) is required.
    1035             :         //
    1036             :         //
    1037             :         // Accumulate the shifted PBs
    1038             :         //
    1039             :         {
    1040             :           Bool isRefF;
    1041           0 :           Array<Float> fbuf;
    1042           0 :           Array<Complex> cbuf;
    1043           0 :           isRefF=theavgPB.get(fbuf);
    1044             :           //isRefC=
    1045           0 :           localTwoDPB.get(cbuf);
    1046             :           
    1047           0 :           IPosition fs(fbuf.shape());
    1048             :           {
    1049           0 :             IPosition ndx(4,0,0,0,0),avgNDX(4,0,0,0,0);
    1050           0 :             for(ndx(3)=0,avgNDX(3)=0;ndx(3)<fs(3);ndx(3)++,avgNDX(3)++)
    1051             :             {
    1052           0 :             for(ndx(2)=0,avgNDX(2)=0;ndx(2)<twoDPBShape(2);ndx(2)++,avgNDX(2)++)
    1053             :               {
    1054           0 :                 for(ndx(0)=0,avgNDX(0)=0;ndx(0)<fs(0);ndx(0)++,avgNDX(0)++)
    1055           0 :                   for(ndx(1)=0,avgNDX(1)=0;ndx(1)<fs(1);ndx(1)++,avgNDX(1)++)
    1056             :                     {
    1057             :                       Float val;
    1058           0 :                       val = real(cbuf(ndx));
    1059           0 :                       fbuf(avgNDX) += val;
    1060           0 :                       if (fbuf(avgNDX) > peak) peak=fbuf(avgNDX);
    1061             :                     }
    1062             :               }
    1063             :             }
    1064             :           }
    1065           0 :           if (!isRefF) theavgPB.put(fbuf);
    1066           0 :           pbPeaks += peak;
    1067             :         }
    1068             :       }
    1069           0 :     theavgPB.setCoordinateInfo(localPB.coordinates());
    1070           0 :     return true; // i.e., an average PB was made and is in the mem. cache
    1071             :   }
    1072             :   //
    1073             :   //---------------------------------------------------------------
    1074             :   //
    1075             :   //
    1076             :   //---------------------------------------------------------------
    1077             :   //
    1078             :   // Locate a convlution function in either mem. or disk cache.  
    1079             :   // Return 1 if found in the disk cache.
    1080             :   //        2 if found in the mem. cache.
    1081             :   //       <0 if not found in either cache.  In this case, absolute of
    1082             :   //          the return value corresponds to the index in the list of
    1083             :   //          conv. funcs. where this conv. func. should be filled
    1084             :   //
    1085           0 :   Int nPBWProjectFT::locateConvFunction(Int Nw, Int /*polInUse*/,  
    1086             :                                         const VisBuffer& vb, Float &pa)
    1087             :   {
    1088             :     Int i; Bool found;
    1089             :     // Commented out to prevent compiler warning
    1090             :     // Float dPA = paChangeDetector.getParAngleTolerance().getValue("rad");
    1091           0 :     found = cfCache.searchConvFunction(vb,paChangeDetector,i,pa);
    1092           0 :     if (found)
    1093             :       {
    1094           0 :         Vector<Float> sampling;
    1095           0 :         PAIndex=i;
    1096             :         //      CoordinateSystem csys;
    1097           0 :         if (cfCache.loadConvFunction(i,Nw,convFuncCache,convSupport,sampling,
    1098           0 :                                      cfRefFreq_p,convFuncCS_p))
    1099             :           {
    1100           0 :             convSampling = (Int)sampling[0];
    1101           0 :             convFunc.reference(*convFuncCache[PAIndex]);
    1102           0 :             cfCache.loadConvFunction(i,Nw,convWeightsCache,convSupport,sampling,cfRefFreq_p,
    1103           0 :                                      convFuncCS_p, "/CFWT");
    1104           0 :             convWeights.reference(*convWeightsCache[PAIndex]);
    1105           0 :             if (PAIndex < (Int)convFuncCache.nelements())
    1106             :               logIO() << "Loaded from disk cache: Conv. func. # "
    1107           0 :                       << PAIndex << LogIO::POST;
    1108           0 :             return 1;
    1109             :           }
    1110           0 :         convFunc.reference(*convFuncCache[PAIndex]);
    1111           0 :         convWeights.reference(*convWeightsCache[PAIndex]);
    1112           0 :         return 2;
    1113             :       }
    1114           0 :     return i;
    1115             :   }
    1116           0 :   void nPBWProjectFT::makeCFPolMap(const VisBuffer& vb, Vector<Int>& polM)
    1117             :   {
    1118           0 :     Vector<Int> msStokes = vb.corrType();
    1119           0 :     Int nPol = msStokes.nelements();
    1120           0 :     polM.resize(polMap.shape());
    1121           0 :     polM = -1;
    1122             : 
    1123           0 :     for(Int i=0;i<nPol;i++)
    1124           0 :       for(uInt j=0;j<cfStokes.nelements();j++)
    1125           0 :         if (cfStokes(j) == msStokes(i))
    1126           0 :             {polM(i) = j;break;}
    1127           0 :   }
    1128             :   //
    1129             :   //---------------------------------------------------------------
    1130             :   //
    1131             :   // Given a polMap (mapping of which Visibility polarization is
    1132             :   // gridded onto which grid plane), make a map of the conjugate
    1133             :   // planes of the grid E.g, for Stokes-I and -V imaging, the two
    1134             :   // planes of the uv-grid are [LL,RR].  For input VisBuffer
    1135             :   // visibilites in order [RR,RL,LR,LL], polMap = [1,-1,-1,0].  The
    1136             :   // conjugate map will be [0,-1,-1,1].
    1137             :   //
    1138           0 :   void nPBWProjectFT::makeConjPolMap(const VisBuffer& vb, 
    1139             :                                      const Vector<Int> cfPolMap, 
    1140             :                                      Vector<Int>& conjPolMap)
    1141             :   {
    1142             :     //
    1143             :     // All the Natak (Drama) below with slicers etc. is to extract the
    1144             :     // Poln. info. for the first IF only (not much "information
    1145             :     // hiding" for the code to slice arrays in a general fashion).
    1146             :     //
    1147             :     // Extract the shape of the array to be sliced.
    1148             :     //
    1149           0 :     Array<Int> stokesForAllIFs = vb.msColumns().polarization().corrType().getColumn();
    1150           0 :     IPosition stokesShape(stokesForAllIFs.shape());
    1151           0 :     IPosition firstIFStart(stokesShape),firstIFLength(stokesShape);
    1152             :     //
    1153             :     // Set up the start and length IPositions to extract only the
    1154             :     // first column of the array.  The following is required since the
    1155             :     // array could have only one column as well.
    1156             :     //
    1157           0 :     firstIFStart(0)=0;firstIFLength(0)=stokesShape(0);
    1158           0 :     for(uInt i=1;i<stokesShape.nelements();i++) {firstIFStart(i)=0;firstIFLength(i)=1;}
    1159             :     //
    1160             :     // Construct the slicer and produce the slice.  .nonDegenerate
    1161             :     // required to ensure the result of slice is a pure vector.
    1162             :     //
    1163           0 :     Vector<Int> visStokes = stokesForAllIFs(Slicer(firstIFStart,firstIFLength)).nonDegenerate();
    1164             : 
    1165           0 :     conjPolMap = cfPolMap;
    1166             :     
    1167           0 :     Int i,j,N = cfPolMap.nelements();
    1168           0 :     for(i=0;i<N;i++)
    1169           0 :       if (cfPolMap[i] > -1)
    1170             :         {
    1171           0 :         if      (visStokes[i] == Stokes::RR) 
    1172             :           {
    1173           0 :             conjPolMap[i]=-1;
    1174           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LL) break; 
    1175           0 :             conjPolMap[i]=cfPolMap[j];
    1176             :           }
    1177           0 :         else if (visStokes[i] == Stokes::LL) 
    1178             :           {
    1179           0 :             conjPolMap[i]=-1;
    1180           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RR) break; 
    1181           0 :             conjPolMap[i]=cfPolMap[j];
    1182             :           }
    1183           0 :         else if (visStokes[i] == Stokes::LR) 
    1184             :           {
    1185           0 :             conjPolMap[i]=-1;
    1186           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::RL) break; 
    1187           0 :             conjPolMap[i]=cfPolMap[j];
    1188             :           }
    1189           0 :         else if (visStokes[i] == Stokes::RL) 
    1190             :           {
    1191           0 :             conjPolMap[i]=-1;
    1192           0 :             for(j=0;j<N;j++) if (visStokes[j] == Stokes::LR) break; 
    1193           0 :             conjPolMap[i]=cfPolMap[j];
    1194             :           }
    1195             :         }
    1196           0 :   }
    1197             :   //
    1198             :   //---------------------------------------------------------------
    1199             :   //
    1200           0 :   void nPBWProjectFT::findConvFunction(const ImageInterface<Complex>& image,
    1201             :                                        const VisBuffer& vb)
    1202             :   {
    1203           0 :     if (!paChangeDetector.changed(vb,0)) return;
    1204             : 
    1205           0 :     logIO() << LogOrigin("nPBWProjectFT", "findConvFunction")  << LogIO::NORMAL;
    1206             :     
    1207           0 :     ok();
    1208             :     
    1209             :     
    1210           0 :     CoordinateSystem coords(image.coordinates());
    1211             :     
    1212             :     //
    1213             :     // Make a two dimensional image to calculate auto-correlation of
    1214             :     // the ideal illumination pattern. We want this on a fine grid in
    1215             :     // the UV plane
    1216             :     //
    1217           0 :     Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
    1218           0 :     AlwaysAssert(directionIndex>=0, AipsError);
    1219           0 :     DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
    1220           0 :     directionCoord=coords.directionCoordinate(directionIndex);
    1221           0 :     Vector<Double> sampling;
    1222           0 :     sampling = dc.increment();
    1223           0 :     sampling*=Double(convSampling);
    1224           0 :     sampling*=Double(nx)/Double(convSize);
    1225           0 :     dc.setIncrement(sampling);
    1226             :     
    1227             :     
    1228           0 :     Vector<Double> unitVec(2);
    1229           0 :     unitVec=convSize/2;
    1230           0 :     dc.setReferencePixel(unitVec);
    1231             :     
    1232             :     // Set the reference value to that of the image
    1233           0 :     coords.replaceCoordinate(dc, directionIndex);
    1234             :     
    1235             :     //
    1236             :     // Make an image with circular polarization axis.  Return the
    1237             :     // no. of vis. poln. planes that will be used in making the user
    1238             :     // defined Stokes image.
    1239             :     //
    1240           0 :     polInUse=makePBPolnCoords(coords,vb);
    1241             :     
    1242             :     Float pa;
    1243           0 :     Int cfSource=locateConvFunction(wConvSize, polInUse, vb, pa);
    1244             :     // cerr << "CFS: " << cfSource << " " << PAIndex << " " 
    1245             :     //   << convFuncCache.nelements() << " " 
    1246             :     //   << convWeightsCache.nelements() << " " 
    1247             :     //   << endl;
    1248           0 :     lastPAUsedForWtImg = currentCFPA = pa;
    1249             :     
    1250           0 :     Bool pbMade=false;
    1251           0 :     if (cfSource==1) // CF found and loaded from the disk cache
    1252             :       {
    1253             :         //      cout << "### New CFPA = " << currentCFPA << endl;
    1254           0 :         polInUse = convFunc.shape()(3);
    1255           0 :         wConvSize = convFunc.shape()(2);
    1256             :         try
    1257             :           {
    1258           0 :             cfCache.loadAvgPB(avgPB);
    1259           0 :             avgPBReady=true;
    1260             :           }
    1261           0 :         catch (AipsError& err)
    1262             :           {
    1263             :             logIO() << "Average PB does not exist in the cache.  A fresh one will be made."
    1264           0 :                     << LogIO::NORMAL << LogIO::POST;
    1265           0 :             pbMade=makeAveragePB0(vb, image, polInUse, avgPB);
    1266           0 :             pbNormalized=false; normalizeAvgPB(); pbNormalized=true;
    1267             :           }
    1268             :       }
    1269           0 :     else if (cfSource==2)  // CF found in the mem. cache
    1270             :       {
    1271             :       }
    1272             :     else                     // CF not found in either cache
    1273             :       {
    1274             :         //
    1275             :         // Make the CF, update the average PB and update the CF and
    1276             :         // the avgPB disk cache
    1277             :         //
    1278           0 :         PAIndex = abs(cfSource);
    1279             :         //
    1280             :         // Load the average PB from the disk since it's going to be
    1281             :         // updated in memory and on the disk.  Without loading it from
    1282             :         // the disk (from a potentially more complete existing cache),
    1283             :         // the average PB can get inconsistant with the rest of the
    1284             :         // cache.
    1285             :         //
    1286             : //      logIO() << LogOrigin("nPBWProjectFT::findConvFunction()","") 
    1287             : //              << "Making the convolution function for PA=" << pa << "deg."
    1288             : //              << LogIO::NORMAL 
    1289             : //              << LogIO::POST;
    1290           0 :         makeConvFunction(image,vb,pa);
    1291             :         try
    1292             :           {
    1293           0 :             cfCache.loadAvgPB(avgPB);
    1294           0 :             resetPBs = false;
    1295           0 :             avgPBReady=true;
    1296             :           }
    1297           0 :         catch(SynthesisFTMachineError &err)
    1298             :           {
    1299           0 :             logIO() << LogOrigin("nPBWProjectFT::findConvFunction()","") 
    1300             :                     << "Average PB does not exist in the cache.  A fresh one will be made." 
    1301             :                     << LogIO::NORMAL 
    1302           0 :                     << LogIO::POST;
    1303           0 :             pbMade=makeAveragePB0(vb, image, polInUse,avgPB);
    1304             :           }
    1305             : 
    1306             :         //      makeAveragePB(vb, image, polInUse,avgPB);
    1307           0 :         pbNormalized=false; 
    1308           0 :         normalizeAvgPB();
    1309           0 :         pbNormalized=true;
    1310           0 :         Int index=coords.findCoordinate(Coordinate::SPECTRAL);
    1311           0 :         SpectralCoordinate spCS = coords.spectralCoordinate(index);
    1312           0 :         Vector<Double> refValue; refValue.resize(1);refValue(0)=cfRefFreq_p;
    1313           0 :         spCS.setReferenceValue(refValue);
    1314           0 :         coords.replaceCoordinate(spCS,index);
    1315           0 :         cfCache.cacheConvFunction(PAIndex, pa, convFunc, coords, convFuncCS_p, 
    1316           0 :                                   convSize, convSupport,convSampling);
    1317           0 :         Cube<Int> convWtSize=convSupport*CONVWTSIZEFACTOR;
    1318           0 :         cfCache.cacheConvFunction(PAIndex, pa, convWeights, coords, convFuncCS_p,
    1319           0 :                                   convSize, convWtSize,convSampling,"WT",false);
    1320           0 :         cfCache.finalize(); // Write the aux info file
    1321           0 :         if (pbMade) cfCache.finalize(avgPB); // Save the AVG PB and write the aux info.
    1322             :       }
    1323             : 
    1324           0 :     verifyShapes(avgPB.shape(), image.shape());
    1325             : 
    1326           0 :     Int lastPASlot = PAIndex;
    1327             : 
    1328           0 :     if (paChangeDetector.changed(vb,0)) paChangeDetector.update(vb,0);
    1329             :     //
    1330             :     // If mem. cache not yet ready and the latest CF was loaded from
    1331             :     // the disk cache, compute and give some user useful info.
    1332             :     //
    1333           0 :     if ((!convFuncCacheReady) && (cfSource != 2))
    1334             :       {
    1335             :         //
    1336             :         // Compute the aggregate memory used by the cached convolution
    1337             :         // functions.
    1338             :         //
    1339           0 :         Int maxMemoryMB=HostInfo::memoryTotal(true)/1024;
    1340           0 :         Float memoryKB=0;
    1341           0 :         String unit(" KB");
    1342           0 :         for(uInt iPA=0;iPA<convFuncCache.nelements();iPA++)
    1343             :           {
    1344           0 :             Int volume=1;
    1345           0 :             if (convFuncCache[iPA] != NULL)
    1346             :               {
    1347           0 :                 IPosition shape=(*convFuncCache[iPA]).shape();
    1348           0 :                 volume=1;
    1349           0 :                 for(uInt i=0;i<shape.nelements();i++)
    1350           0 :                   volume*=shape(i);
    1351           0 :                 memoryKB += volume;
    1352             :               }
    1353             :           }
    1354             : 
    1355             :         
    1356           0 :         memoryKB = Int(memoryKB*sizeof(Complex)*2/1024.0+0.5);
    1357           0 :         if (memoryKB > 1024) {memoryKB /=1024; unit=" MB";}
    1358             :         
    1359             :         logIO() << "Memory used in gridding functions = "
    1360           0 :                 << (Int)(memoryKB+0.5) << unit << " out of a maximum of "
    1361           0 :                 << maxMemoryMB << " MB" << LogIO::POST;
    1362             :         
    1363             :         //
    1364             :         // Show the list of support sizes along the w-axis for the current PA.
    1365             :         //
    1366           0 :         IPosition sliceStart(3,0,0,lastPASlot),
    1367           0 :           sliceLength(3,wConvSize,1,1);
    1368             :         logIO() << "Convolution support [CF#= " << lastPASlot 
    1369           0 :                 << ", PA=" << pa*180.0/M_PI << "deg"
    1370             :                 <<"] = "
    1371           0 :                 << convSupport(Slicer(sliceStart,sliceLength)).nonDegenerate()
    1372             :                 << " pixels in Fourier plane"
    1373           0 :                 << LogIO::POST;
    1374             :       }
    1375             : 
    1376           0 :     IPosition shp(convFunc.shape());
    1377           0 :     IPosition ndx(shp);
    1378           0 :     ndx =0;
    1379           0 :     Area.resize(Area.nelements()+1,true);
    1380           0 :     Area(lastPASlot)=0;
    1381             : 
    1382           0 :     for(ndx(0)=0;ndx(0)<shp(0);ndx(0)++)
    1383           0 :       for(ndx(1)=0;ndx(1)<shp(1);ndx(1)++)
    1384           0 :         Area(lastPASlot)+=convFunc(ndx);
    1385             :   }
    1386             :   //
    1387             :   //---------------------------------------------------------------
    1388             :   //
    1389           0 :   void nPBWProjectFT::makeConvFunction(const ImageInterface<Complex>& image,
    1390             :                                        const VisBuffer& vb,Float pa)
    1391             :   {
    1392           0 :     if (bandID_p == -1) bandID_p=getVisParams(vb);
    1393           0 :     Int NNN=0;
    1394           0 :     logIO() << LogOrigin("nPBWProjectFT", "makeConvFunction") 
    1395             :             << "Making a new convolution function for PA="
    1396           0 :             << pa*(180/C::pi) << "deg"
    1397             :             << LogIO::NORMAL 
    1398           0 :             << LogIO::POST;
    1399             : 
    1400           0 :     if(wConvSize>NNN) {
    1401           0 :       logIO() << "Using " << wConvSize << " planes for W-projection" << LogIO::POST;
    1402             :       Double maxUVW;
    1403           0 :       maxUVW=0.25/abs(image.coordinates().increment()(0));
    1404             :       logIO() << "Estimating maximum possible W = " << maxUVW
    1405           0 :               << " (wavelengths)" << LogIO::POST;
    1406             :       
    1407           0 :       Double invLambdaC=vb.frequency()(0)/C::c;
    1408             : //       logIO() << "Typical wavelength = " << 1.0/invLambdaC
    1409             : //            << " (m)" << LogIO::POST;
    1410           0 :       Double invMinL = vb.frequency()((vb.frequency().nelements())-1)/C::c;
    1411             :       logIO() << "wavelength range = " << 1.0/invLambdaC << " (m) to " 
    1412           0 :               << 1.0/invMinL << " (m)" << LogIO::POST;
    1413           0 :       if (wConvSize > 1)
    1414             :         {
    1415           0 :           uvScale(2)=Float((wConvSize-1)*(wConvSize-1))/maxUVW;
    1416           0 :           logIO() << "Scaling in W (at maximum W) = " << 1.0/uvScale(2)
    1417           0 :                   << " wavelengths per pixel" << LogIO::POST;
    1418             :         }
    1419             :     }
    1420             :     //  
    1421             :     // Get the coordinate system
    1422             :     //
    1423           0 :     CoordinateSystem coords(image.coordinates());
    1424             :     
    1425             :     //
    1426             :     // Set up the convolution function. 
    1427             :     //
    1428           0 :     if(wConvSize>NNN) 
    1429             :       {
    1430           0 :         if(wConvSize>256) 
    1431             :           {
    1432           0 :             convSampling=4;
    1433           0 :             convSize=min(nx,512);
    1434             :           }
    1435             :         else 
    1436             :           {
    1437           0 :             convSampling=4;
    1438           0 :             convSize=min(nx,2048);
    1439             :           }
    1440             :       }
    1441             :     else 
    1442             :       {
    1443           0 :         convSampling=4;
    1444           0 :         convSize=nx;
    1445             :       }
    1446           0 :     convSampling=OVERSAMPLING;
    1447           0 :     convSize=CONVSIZE;
    1448             :     //
    1449             :     // Make a two dimensional image to calculate auto-correlation of
    1450             :     // the ideal illumination pattern. We want this on a fine grid in
    1451             :     // the UV plane
    1452             :     //
    1453           0 :     Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
    1454           0 :     AlwaysAssert(directionIndex>=0, AipsError);
    1455           0 :     DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
    1456           0 :     directionCoord=coords.directionCoordinate(directionIndex);
    1457           0 :     Vector<Double> sampling;
    1458           0 :     sampling = dc.increment();
    1459             :     //    sampling /= Double(2.0);
    1460             : 
    1461           0 :     sampling*=Double(convSampling);
    1462           0 :     sampling*=Double(nx)/Double(convSize);
    1463             : 
    1464             :     // cerr << "Sampling on the sky = " << dc.increment() << " " << nx << "x" << ny << endl;
    1465             :     // cerr << "Sampling on the PB  = " << sampling << " " << convSize << "x" << convSize << endl;
    1466           0 :     dc.setIncrement(sampling);
    1467             :     
    1468           0 :     Vector<Double> unitVec(2);
    1469           0 :     unitVec=convSize/2;
    1470           0 :     dc.setReferencePixel(unitVec);
    1471             :     
    1472             :     // Set the reference value to that of the image
    1473           0 :     coords.replaceCoordinate(dc, directionIndex);
    1474             :     
    1475             :     //
    1476             :     // Make an image with circular polarization axis.  Return the
    1477             :     // no. of vis. poln. planes that will be used in making the user
    1478             :     // defined Stokes image.
    1479             :     //
    1480           0 :     polInUse=makePBPolnCoords(coords,vb);
    1481           0 :     convSupport.resize(wConvSize,polInUse,PAIndex+1,true);
    1482           0 :     Int N=convFuncCache.nelements();
    1483           0 :     convFuncCache.resize(PAIndex+1,true);
    1484           0 :     for(Int i=N;i<PAIndex;i++) convFuncCache[i]=NULL;
    1485           0 :     convWeightsCache.resize(PAIndex+1,true);
    1486           0 :     for(Int i=N;i<PAIndex;i++) convWeightsCache[i]=NULL;
    1487             :     //------------------------------------------------------------------
    1488             :     //
    1489             :     // Make the sky Stokes PB.  This will be used in the gridding
    1490             :     // correction
    1491             :     //
    1492             :     //------------------------------------------------------------------
    1493           0 :     IPosition pbShape(4, convSize, convSize, polInUse, 1);
    1494           0 :     TempImage<Complex> twoDPB(pbShape, coords);
    1495             : 
    1496           0 :     IPosition pbSqShp(pbShape);
    1497             :     //    pbSqShp[0] *= 2;    pbSqShp[1] *= 2;
    1498             : 
    1499           0 :     unitVec=pbSqShp[0]/2;
    1500           0 :     dc.setReferencePixel(unitVec);
    1501             :     // sampling *= Double(2.0);
    1502             :     // dc.setIncrement(sampling);
    1503           0 :     coords.replaceCoordinate(dc, directionIndex);
    1504             : 
    1505           0 :     TempImage<Complex> twoDPBSq(pbSqShp,coords);
    1506           0 :     twoDPB.setMaximumCacheSize(cachesize);
    1507           0 :     twoDPB.set(Complex(1.0,0.0));
    1508           0 :     twoDPBSq.setMaximumCacheSize(cachesize);
    1509           0 :     twoDPBSq.set(Complex(1.0,0.0));
    1510             :     //
    1511             :     // Accumulate the various terms that constitute the gridding
    1512             :     // convolution function.
    1513             :     //
    1514             :     //------------------------------------------------------------------
    1515             :     
    1516           0 :     Int inner=convSize/convSampling;
    1517             :     //    inner = convSize/2;
    1518             : 
    1519           0 :     Vector<Double> cfUVScale(3,0),cfUVOffset(3,0);
    1520             : 
    1521           0 :     cfUVScale(0)=Float(twoDPB.shape()(0))*sampling(0);
    1522           0 :     cfUVScale(1)=Float(twoDPB.shape()(1))*sampling(1);
    1523           0 :     cfUVOffset(0)=Float(twoDPB.shape()(0))/2;
    1524           0 :     cfUVOffset(1)=Float(twoDPB.shape()(1))/2;
    1525             :     // cerr << uvScale << " " << cfUVScale << endl;
    1526             :     // cerr << uvOffset << " " << cfUVOffset << endl;
    1527             :     ConvolveGridder<Double, Complex>
    1528             :       //      ggridder(IPosition(2, inner, inner), cfUVScale, cfUVOffset, "SF");
    1529           0 :       ggridder(IPosition(2, inner, inner), uvScale, uvOffset, "SF");
    1530             :     
    1531             :     // convFuncCache[PAIndex] = new Array<Complex>(IPosition(4,convSize/2,convSize/2,
    1532             :     //                                                    wConvSize,polInUse));
    1533             :     // convWeightsCache[PAIndex] = new Array<Complex>(IPosition(4,convSize/2,convSize/2,
    1534             :     //                                                       wConvSize,polInUse));
    1535           0 :     convFuncCache[PAIndex] = new Array<Complex>(IPosition(4,convSize,convSize,
    1536           0 :                                                           wConvSize,polInUse));
    1537           0 :     convWeightsCache[PAIndex] = new Array<Complex>(IPosition(4,convSize,convSize,
    1538           0 :                                                              wConvSize,polInUse));
    1539           0 :     convFunc.reference(*convFuncCache[PAIndex]);
    1540           0 :     convWeights.reference(*convWeightsCache[PAIndex]);
    1541           0 :     convFunc=0.0;
    1542           0 :     convWeights=0.0;
    1543             :     
    1544           0 :     IPosition start(4, 0, 0, 0, 0);
    1545           0 :     IPosition pbSlice(4, convSize, convSize, 1, 1);
    1546             :     
    1547           0 :     Matrix<Complex> screen(convSize, convSize);
    1548           0 :     if (paChangeDetector.changed(vb,0)) paChangeDetector.update(vb,0);
    1549           0 :     VLACalcIlluminationConvFunc vlaPB;
    1550           0 :     vlaPB.setMaximumCacheSize(cachesize);
    1551             : 
    1552           0 :     for (Int iw=0;iw<wConvSize;iw++) 
    1553             :       {
    1554           0 :         screen = 1.0;
    1555             : 
    1556             :         /*
    1557             :         screen=0.0;
    1558             :         // First the spheroidal function
    1559             :         //
    1560             :         //      inner=convSize/2;
    1561             :         //      screen = 0.0;
    1562             :         Vector<Complex> correction(inner);
    1563             :         for (Int iy=-inner/2;iy<inner/2;iy++) 
    1564             :           {
    1565             :             ggridder.correctX1D(correction, iy+inner/2);
    1566             :             for (Int ix=-inner/2;ix<inner/2;ix++) 
    1567             :               screen(ix+convSize/2,iy+convSize/2)=correction(ix+inner/2);
    1568             :             // if (iy==0)
    1569             :             //   for (Int ii=0;ii<inner;ii++)
    1570             :             //  cout << ii << " " << correction(ii) << endl;
    1571             :           }
    1572             :         */
    1573             :         //
    1574             :         // Now the w term
    1575             :         //
    1576           0 :         if(wConvSize>1) 
    1577             :           {
    1578           0 :             logIO() << LogOrigin("nPBWProjectFT", "")
    1579           0 :                     << "Computing WPlane " << iw  << LogIO::POST;
    1580             :             
    1581           0 :             Double twoPiW=2.0*C::pi*Double(iw*iw)/uvScale(2);
    1582             :             
    1583           0 :             for (Int iy=-inner/2;iy<inner/2;iy++) 
    1584             :               {
    1585           0 :                 Double m=sampling(1)*Double(iy);
    1586           0 :                 Double msq=m*m;
    1587           0 :                 for (Int ix=-inner/2;ix<inner/2;ix++) 
    1588             :                   {
    1589           0 :                     Double l=sampling(0)*Double(ix);
    1590           0 :                     Double rsq=l*l+msq;
    1591           0 :                     if(rsq<1.0) 
    1592             :                       {
    1593           0 :                         Double phase=twoPiW*(sqrt(1.0-rsq)-1.0);
    1594           0 :                         screen(ix+convSize/2,iy+convSize/2)*=Complex(cos(phase),sin(phase));
    1595             :                       }
    1596             :                   }
    1597             :               }
    1598             :           }
    1599             :         
    1600             :         //
    1601             :         // Fill the complex image with the w-term...
    1602             :         //
    1603           0 :         IPosition PolnPlane(4,0,0,0,0);
    1604           0 :         IPosition ndx(4,0,0,0,0);
    1605             :         
    1606           0 :         for(Int i=0;i<polInUse;i++)
    1607             :           {
    1608           0 :             PolnPlane(2)=i;
    1609           0 :             twoDPB.putSlice(screen, PolnPlane);
    1610           0 :             twoDPBSq.putSlice(screen, PolnPlane);
    1611             :           }
    1612             :         // {
    1613             :         //   Vector<IPosition> posMax(twoDPB.shape()(2));
    1614             :         //   posMax(0)(0)=pbShape(0)/2;
    1615             :         //   posMax(0)(1)=pbShape(1)/2;
    1616             :         //   posMax(1)(0)=pbShape(0)/2;
    1617             :         //   posMax(1)(1)=pbShape(1)/2;
    1618             :         //   getVisParams(vb);
    1619             :         //   applyAntiAliasingOp(twoDPB,posMax,0);
    1620             :         // }
    1621             :         //
    1622             :         // Apply the PB...
    1623             :         //
    1624             : 
    1625             :         // The following replaces the simple vlaPB.applyPB() call.
    1626             :         // The functional interface of VLACalcIllumination was
    1627             :         // modified to apply one polarization PB at a time.  As a
    1628             :         // result, the co-ord. sys. of the image going to applyPB()
    1629             :         // should have only one Poln. plane.
    1630             :         //
    1631             :         // Before this change, the twoDPB and twoDPBSq images were
    1632             :         // directly sent to applyPB(). Now, in the code below, we go
    1633             :         // over the poln. planes of these images, make a temp. image
    1634             :         // with the poln. planes of these images, applyPB() on the
    1635             :         // temp. image, and copy the result in the appropriate planes
    1636             :         // of the twoD* images.  The rest of the code therefore does
    1637             :         // not see a difference.
    1638             :         {
    1639           0 :           CoordinateSystem singlePolCoords=coords;
    1640           0 :           Int index, outNdx, whichPolPlane=0;
    1641           0 :           Vector<Int> inStokes, outStokes(1);
    1642           0 :           index = coords.findCoordinate(Coordinate::STOKES);
    1643           0 :           inStokes = coords.stokesCoordinate(index).stokes();
    1644           0 :           for (uInt i=0; i<inStokes.nelements(); i++)
    1645             :             {
    1646           0 :               outStokes(0)=inStokes(i);
    1647             :               // Make a temp. image with a single Stokes along Pol. axis.
    1648           0 :               StokesCoordinate polnCoord(outStokes);
    1649           0 :               outNdx = singlePolCoords.findCoordinate(Coordinate::STOKES);
    1650           0 :               singlePolCoords.replaceCoordinate(polnCoord, outNdx);
    1651           0 :               IPosition singlePolShape = pbSqShp;
    1652           0 :               singlePolShape(2)=1;
    1653           0 :               Bool doSquint=true;
    1654           0 :               Double pa=getPA(vb);
    1655           0 :               Vector<Double> chanFreq = vb.frequency();
    1656             :               //freqHi = max(chanFreq);
    1657           0 :               Double Freq = max(chanFreq);
    1658             :               {
    1659           0 :                 TempImage<Complex> singlePolImg(singlePolShape, singlePolCoords);
    1660             :                 // Copy screen to the single pol. image.  Apply PB to it.  Copy 
    1661             :                 // the single pol. image plane to the twoDPB image.
    1662           0 :                 doSquint=true;
    1663           0 :                 PolnPlane(2)=0;               singlePolImg.putSlice(screen, PolnPlane);
    1664           0 :                 vlaPB.applyPB(singlePolImg, pa, doSquint,bandID_p, 0, Freq);
    1665           0 :                 PolnPlane(2)=whichPolPlane;   twoDPB.putSlice(singlePolImg.get(), PolnPlane);
    1666             :               }
    1667             :               {
    1668           0 :                 TempImage<Complex> singlePolImg(singlePolShape, singlePolCoords);
    1669             :                 // Copy screen to the single pol. image.  Apply PB to it.  Copy 
    1670             :                 // the single pol. image plane to the twoDPBSq image.
    1671           0 :                 doSquint = false;
    1672           0 :                 PolnPlane(2)=0;               singlePolImg.putSlice(screen, PolnPlane);
    1673             :                 //vlaPB.applyPBSq(twoDPBSq, vb, bandID_p, doSquint);
    1674           0 :                 vlaPB.applyPB(singlePolImg, pa, doSquint, bandID_p, 0, Freq);
    1675           0 :                 PolnPlane(2)=whichPolPlane;   twoDPBSq.putSlice(singlePolImg.get(), PolnPlane);
    1676             :               }
    1677             : 
    1678           0 :               whichPolPlane++;
    1679             :             }
    1680             :         }
    1681             :         /*
    1682             : //      twoDPB.put(abs(twoDPB.get()));
    1683             : //      twoDPBSq.put(abs(twoDPBSq.get()));
    1684             :         */
    1685             : 
    1686             :         // {
    1687             :         //   String name("twoDPB.before.im");
    1688             :         //   storeImg(name,twoDPB);
    1689             :         // }
    1690             :         // {
    1691             :         //   //
    1692             :         //   // Apply (multiply) by the Spheroidal functions
    1693             :         //   //
    1694             :         //   Vector<Float> maxVal(twoDPB.shape()(2));
    1695             :         //   Vector<IPosition> posMax(twoDPB.shape()(2));
    1696             :           
    1697             :         //   SynthesisUtils::findLatticeMax(twoDPB,maxVal,posMax); 
    1698             :         //   posMax(0)(0)+=1;
    1699             :         //   posMax(0)(1)+=1;
    1700             :         //   posMax(1)(0)+=1;
    1701             :         //   posMax(1)(1)+=1;
    1702             :         //   //   applyAntiAliasingOp(twoDPB,posMax,1);
    1703             : 
    1704             :         //   SynthesisUtils::findLatticeMax(twoDPBSq,maxVal,posMax); 
    1705             :         //   posMax(0)(0)+=1;
    1706             :         //   posMax(0)(1)+=1;
    1707             :         //   posMax(1)(0)+=1;
    1708             :         //   posMax(1)(1)+=1;
    1709             :         //   //   applyAntiAliasingOp(twoDPBSq,posMax,1,true);
    1710             :         // }
    1711             : 
    1712           0 :         Complex cpeak=max(twoDPB.get());
    1713           0 :         twoDPB.put(twoDPB.get()/cpeak);
    1714           0 :         cpeak=max(twoDPBSq.get());
    1715           0 :         twoDPBSq.put(twoDPBSq.get()/cpeak);
    1716             :         //      twoDPBSq.set(1.0);
    1717             :         // {
    1718             :         //   String name("twoDPB.im");
    1719             :         //   storeImg(name,twoDPB);
    1720             :         // }
    1721             : 
    1722           0 :         CoordinateSystem cs=twoDPB.coordinates();
    1723           0 :         Int index= twoDPB.coordinates().findCoordinate(Coordinate::SPECTRAL);
    1724           0 :         SpectralCoordinate SpCS = twoDPB.coordinates().spectralCoordinate(index);
    1725             : 
    1726           0 :         cfRefFreq_p=SpCS.referenceValue()(0);
    1727             :         //
    1728             :         // Now FFT and get the result back
    1729             :         //
    1730             :         // {
    1731             :         //   String name("twoDPB.im");
    1732             :         //   storeImg(name,twoDPB);
    1733             :         // }
    1734           0 :         LatticeFFT::cfft2d(twoDPB);
    1735           0 :         LatticeFFT::cfft2d(twoDPBSq);
    1736             :         // {
    1737             :         //   String name("twoDPBFT.im");
    1738             :         //   storeImg(name,twoDPB);
    1739             :         // }
    1740             :         //
    1741             :         // Fill the convolution function planes with the result.
    1742             :         //
    1743             :         {
    1744             :           // IPosition start(4, convSize/4, convSize/4, 0, 0),
    1745             :           //   pbSlice(4, convSize/2-1, convSize/2-1, polInUse, 1);
    1746             :           // IPosition sliceStart(4,0,0,iw,0), 
    1747             :           //   sliceLength(4,convSize/2-1,convSize/2-1,1,polInUse);
    1748             :           
    1749           0 :           IPosition start(4, 0, 0, 0, 0),
    1750           0 :             pbSlice(4, twoDPB.shape()[0]-1, twoDPB.shape()[1]-1, polInUse, 1);
    1751           0 :           IPosition sliceStart(4,0,0,iw,0), 
    1752           0 :             sliceLength(4,convFunc.shape()[0]-1,convFunc.shape()[1]-1,1,polInUse);
    1753             :           
    1754           0 :           convFunc(Slicer(sliceStart,sliceLength)).nonDegenerate()
    1755           0 :             =(twoDPB.getSlice(start, pbSlice, true));
    1756             : 
    1757           0 :           IPosition shp(twoDPBSq.shape());
    1758             :           
    1759             :           //UNUSED: Int bufSize=convWeights.shape()[0], Org=shp[0]/2;
    1760             :           // IPosition sqStart(4, Org-bufSize/2, Org-bufSize/2, 0, 0),
    1761             :           //   pbSqSlice(4, bufSize-1, bufSize-1, polInUse, 1);
    1762             :           // IPosition sqSliceStart(4,0,0,iw,0), 
    1763             :           //   sqSliceLength(4,bufSize-1,bufSize-1,1,polInUse);
    1764             : 
    1765           0 :           IPosition sqStart(4, 0, 0, 0, 0),
    1766           0 :             pbSqSlice(4, shp[0]-1, shp[1]-1, polInUse, 1);
    1767           0 :           IPosition sqSliceStart(4,0,0,iw,0), 
    1768           0 :             sqSliceLength(4,shp[0]-1,shp[1]-1,1,polInUse);
    1769             :           
    1770           0 :           convWeights(Slicer(sqSliceStart,sqSliceLength)).nonDegenerate()
    1771           0 :             =(twoDPBSq.getSlice(sqStart, pbSqSlice, true));
    1772             : 
    1773             :         }
    1774             :       }
    1775             :     
    1776             :     {
    1777           0 :       Complex cpeak = max(convFunc);
    1778           0 :       convFunc/=cpeak;
    1779             :       //      cout << "#### max(convFunc) = " << cpeak << endl;
    1780           0 :       cpeak=max(convWeights);
    1781             :       //      cout << "#### max(convWeights) = " << cpeak << endl;
    1782           0 :       convWeights/=cpeak;
    1783             :       //      cout << "#### max(convWeights) = " << max(convWeights) << endl;
    1784             :     }
    1785             :     //
    1786             :     // Find the convolution function support size.  No assumption
    1787             :     // about the symmetry of the conv. func. can be made (except that
    1788             :     // they are same for all poln. planes).
    1789             :     //
    1790           0 :     Int lastPASlot=PAIndex;
    1791           0 :     for(Int iw=0;iw<wConvSize;iw++)
    1792           0 :       for(Int ipol=0;ipol<polInUse;ipol++)
    1793           0 :         convSupport(iw,ipol,lastPASlot)=-1;
    1794             :     //
    1795             :     // !!!Caution: This assumes that the support size at each Poln. is
    1796             :     // the same, starting from the center pixel (in pixel
    1797             :     // co-ordinates).  For large pointing offsets, this might not be
    1798             :     // true.
    1799             :     //
    1800             :     //    Int ConvFuncOrigin=convSize/4;  // Conv. Func. is half that size of convSize
    1801           0 :     Int ConvFuncOrigin=convFunc.shape()[0]/2;  // Conv. Func. is half that size of convSize
    1802           0 :     IPosition ndx(4,ConvFuncOrigin,0,0,0);
    1803             :     //    Cube<Int> convWtSupport(convSupport.shape());
    1804           0 :     convWtSupport.resize(convSupport.shape(),true);
    1805           0 :     Int maxConvWtSupport=0, supportBuffer;
    1806           0 :     for (Int iw=0;iw<wConvSize;iw++)
    1807             :       {
    1808           0 :         Bool found=false;
    1809             :         Float threshold;
    1810             :         Int R;
    1811           0 :         ndx(2) = iw;
    1812             :         
    1813           0 :         ndx(0)=ndx(1)=ConvFuncOrigin;
    1814           0 :         ndx(2) = iw;
    1815             :         //      Complex maxVal = max(convFunc);
    1816           0 :         threshold = abs(convFunc(ndx))*THRESHOLD;
    1817             :         //
    1818             :         // Find the support size of the conv. function in pixels
    1819             :         //
    1820             :         Int wtR;
    1821           0 :         found =findSupport(convWeights,threshold,ConvFuncOrigin,wtR);
    1822           0 :         found = findSupport(convFunc,threshold,ConvFuncOrigin,R);
    1823             :         
    1824             :         //      R *=2.5;
    1825             :         //
    1826             :         // Set the support size for each W-plane and for all
    1827             :         // Pol-planes.  Assuming that support size for all Pol-planes
    1828             :         // is same.
    1829             :         //
    1830           0 :         if(found) 
    1831             :           {
    1832             :             //      Int maxR=R;//max(ndx(0),ndx(1));
    1833           0 :             for(Int ipol=0;ipol<polInUse;ipol++)
    1834             :               {
    1835           0 :                 convSupport(iw,ipol,lastPASlot)=Int(R/Float(convSampling));
    1836           0 :                 convSupport(iw,ipol,lastPASlot)=Int(0.5+Float(R)/Float(convSampling))+1;
    1837             :                 //              convSupport(iw,ipol,lastPASlot) += (convSupport(iw,ipol,lastPASlot)+1)%2;
    1838           0 :                 convWtSupport(iw,ipol,lastPASlot)=Int(R*CONVWTSIZEFACTOR/Float(convSampling));
    1839           0 :                 convWtSupport(iw,ipol,lastPASlot)=Int(0.5+Float(R)*CONVWTSIZEFACTOR/Float(convSampling))+1;
    1840             :                 //              convWtSupport(iw,ipol,lastPASlot)=Int(wtR/Float(convSampling));
    1841             :                 //              convWtSupport(iw,ipol,lastPASlot) += (convWtSupport(iw,ipol,lastPASlot)+1)%2;
    1842           0 :                 if ((lastPASlot == 0) || (maxConvSupport == -1))
    1843           0 :                   if (convSupport(iw,ipol,lastPASlot) > maxConvSupport)
    1844           0 :                     maxConvSupport = convSupport(iw,ipol,lastPASlot);
    1845           0 :                 maxConvWtSupport=convWtSupport(iw,ipol,lastPASlot);
    1846             :               }
    1847             :           }
    1848             :       }
    1849             : 
    1850           0 :     if(convSupport(0,0,lastPASlot)<1) 
    1851             :       logIO() << "Convolution function is misbehaved - support seems to be zero"
    1852           0 :               << LogIO::EXCEPTION;
    1853             :     
    1854           0 :     logIO() << LogOrigin("nPBWProjectFT", "makeConvFunction")
    1855             :             << "Re-sizing the convolution functions"
    1856           0 :             << LogIO::POST;
    1857             :     
    1858             :     {
    1859           0 :       supportBuffer = OVERSAMPLING;
    1860           0 :       Int bot=ConvFuncOrigin-convSampling*maxConvSupport-supportBuffer,//-convSampling/2, 
    1861           0 :       top=ConvFuncOrigin+convSampling*maxConvSupport+supportBuffer;//+convSampling/2;
    1862           0 :       bot = max(0,bot);
    1863           0 :       top = min(top, convFunc.shape()(0)-1);
    1864             :       {
    1865           0 :         Array<Complex> tmp;
    1866           0 :         IPosition blc(4,bot,bot,0,0), trc(4,top,top,wConvSize-1,polInUse-1);
    1867             :       
    1868           0 :         tmp = convFunc(blc,trc);
    1869           0 :         (*convFuncCache[lastPASlot]).resize(tmp.shape());
    1870           0 :         (*convFuncCache[lastPASlot]) = tmp; 
    1871           0 :         convFunc.reference(*convFuncCache[lastPASlot]);
    1872             :       }
    1873             :       
    1874           0 :       supportBuffer = (Int)(OVERSAMPLING*CONVWTSIZEFACTOR);
    1875           0 :       bot=ConvFuncOrigin-convSampling*maxConvWtSupport-supportBuffer;
    1876           0 :       top=ConvFuncOrigin+convSampling*maxConvWtSupport+supportBuffer;
    1877           0 :       bot=max(0,bot);
    1878           0 :       top=min(top,convWeights.shape()(0)-1);
    1879             :       {
    1880           0 :         Array<Complex> tmp;
    1881           0 :         IPosition blc(4,bot,bot,0,0), trc(4,top,top,wConvSize-1,polInUse-1);
    1882             : 
    1883           0 :         tmp = convWeights(blc,trc);
    1884           0 :         (*convWeightsCache[lastPASlot]).resize(tmp.shape());
    1885           0 :         (*convWeightsCache[lastPASlot]) = tmp; 
    1886           0 :         convWeights.reference(*convWeightsCache[lastPASlot]);
    1887             :       }
    1888             :     }    
    1889             :     
    1890             :     //
    1891             :     // Normalize such that plane 0 sums to 1 (when jumping in steps of
    1892             :     // convSampling).  This is really not necessary here since we do
    1893             :     // the normalizing by the area more accurately in the gridder
    1894             :     // (fpbwproj.f).
    1895             :     //
    1896           0 :     ndx(2)=ndx(3)=0;
    1897             :     
    1898             :     
    1899           0 :     Complex pbSum=0.0;
    1900           0 :     IPosition peakPix(ndx);
    1901             :     
    1902           0 :     Int Nx = convFunc.shape()(0), Ny=convFunc.shape()(1);
    1903             :               
    1904           0 :     for(Int nw=0;nw<wConvSize;nw++)
    1905           0 :       for(Int np=0;np<polInUse;np++)
    1906             :         {
    1907           0 :           ndx(2) = nw; ndx(3)=np;
    1908             :           {
    1909             :             //
    1910             :             // Locate the pixel with the peak value.  That's the
    1911             :             // origin in pixel co-ordinates.
    1912             :             //
    1913           0 :             Float peak=0;
    1914           0 :             peakPix = 0;
    1915           0 :             for(ndx(1)=0;ndx(1)<convFunc.shape()(1);ndx(1)++)
    1916           0 :               for(ndx(0)=0;ndx(0)<convFunc.shape()(0);ndx(0)++)
    1917           0 :                 if (abs(convFunc(ndx)) > peak) {peakPix = ndx;peak=abs(convFunc(ndx));}
    1918             :           }
    1919             :            
    1920           0 :           ConvFuncOrigin = peakPix(0);
    1921             :          //       ConvFuncOrigin = convFunc.shape()(0)/2+1;
    1922             :           //      Int thisConvSupport=convSampling*convSupport(nw,np,lastPASlot);
    1923           0 :           Int thisConvSupport=convSupport(nw,np,lastPASlot);
    1924           0 :           pbSum=0.0;
    1925             : 
    1926           0 :           for(Int iy=-thisConvSupport;iy<thisConvSupport;iy++)
    1927           0 :             for(Int ix=-thisConvSupport;ix<thisConvSupport;ix++)
    1928             :               {
    1929           0 :                 ndx(0)=ix*convSampling+ConvFuncOrigin;
    1930           0 :                 ndx(1)=iy*convSampling+ConvFuncOrigin;
    1931           0 :                 pbSum += real(convFunc(ndx));
    1932             :               }
    1933             :           /*
    1934             :           for(Int iy=0;iy<Ny;iy++)
    1935             :             for(Int ix=0;ix<Nx;ix++)
    1936             :               {
    1937             :                 ndx(0)=ix;ndx(1)=iy;
    1938             :                 pbSum += convFunc(ndx);
    1939             :               }
    1940             :           */
    1941           0 :           if(pbSum>0.0)  
    1942             :             {
    1943             :               //
    1944             :               // Normalize each Poln. plane by the area under its convfunc.
    1945             :               //
    1946           0 :               Nx = convFunc.shape()(0), Ny = convFunc.shape()(1);
    1947           0 :               for (ndx(1)=0;ndx(1)<Ny;ndx(1)++) 
    1948           0 :                 for (ndx(0)=0;ndx(0)<Nx;ndx(0)++) 
    1949             :                   {
    1950           0 :                     convFunc(ndx) /= pbSum;
    1951             :                   }
    1952             : 
    1953           0 :               Nx = convWeights.shape()(0); Ny = convWeights.shape()(1);
    1954           0 :               for (ndx(1)=0;  ndx(1)<Ny;  ndx(1)++) 
    1955           0 :                 for (ndx(0)=0;  ndx(0)<Nx;  ndx(0)++) 
    1956             :                   {
    1957           0 :                     convWeights(ndx) /= pbSum*pbSum;
    1958             :                     // if ((ndx(0)==Nx/2+1) && (ndx(1)==Ny/2+1))
    1959             :                     //   {
    1960             :                     //  convWeights(ndx)=1.0;   
    1961             :                     //  cout << ndx << " " << convWeights(ndx) << endl;
    1962             :                     //   }
    1963             :                     // else
    1964             :                     //   convWeights(ndx)=0.0;
    1965             :                   }
    1966             :             }
    1967             :           else 
    1968           0 :             throw(SynthesisFTMachineError("Convolution function integral is not positive"));
    1969             : 
    1970           0 :           Vector<Float> maxVal(convWeights.shape()(2));
    1971           0 :           Vector<IPosition> posMax(convWeights.shape()(2));
    1972           0 :           SynthesisUtils::findLatticeMax(convWeights,maxVal,posMax); 
    1973             :           //      cout << "convWeights: " << maxVal << " " << posMax << endl;
    1974             :         }
    1975             : 
    1976           0 :   }
    1977             :   //
    1978             :   //------------------------------------------------------------------------------
    1979             :   //
    1980           0 :   void nPBWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    1981             :                                      const VisBuffer& vb)
    1982             :   {
    1983           0 :     image=&iimage;
    1984             :     
    1985           0 :     ok();
    1986             :     
    1987           0 :     init();
    1988           0 :     makingPSF = false;
    1989           0 :     initMaps(vb);
    1990             :     
    1991           0 :     findConvFunction(*image, vb);
    1992             :     //  
    1993             :     // Initialize the maps for polarization and channel. These maps
    1994             :     // translate visibility indices into image indices
    1995             :     //
    1996             : 
    1997           0 :     nx    = image->shape()(0);
    1998           0 :     ny    = image->shape()(1);
    1999           0 :     npol  = image->shape()(2);
    2000           0 :     nchan = image->shape()(3);
    2001             :     
    2002           0 :     if(image->shape().product()>cachesize) isTiled=true;
    2003           0 :     else isTiled=false;
    2004             :     //
    2005             :     // If we are memory-based then read the image in and create an
    2006             :     // ArrayLattice otherwise just use the PagedImage
    2007             :     //
    2008             : 
    2009           0 :     isTiled=false;
    2010             : 
    2011           0 :     if(isTiled){
    2012           0 :         lattice=CountedPtr<Lattice<Complex> > (image, false);
    2013             :     }
    2014             :     else 
    2015             :       {
    2016           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    2017           0 :         griddedData.resize(gridShape);
    2018           0 :         griddedData=Complex(0.0);
    2019             :         
    2020           0 :         IPosition stride(4, 1);
    2021           0 :         IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    2022           0 :                       (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    2023           0 :         IPosition trc(blc+image->shape()-stride);
    2024             :         
    2025           0 :         IPosition start(4, 0);
    2026           0 :         griddedData(blc, trc) = image->getSlice(start, image->shape());
    2027             :         
    2028           0 :         arrayLattice = new ArrayLattice<Complex>(griddedData);
    2029           0 :         lattice=arrayLattice;
    2030             :       }
    2031             : 
    2032             :     //AlwaysAssert(lattice, AipsError);
    2033             :     
    2034           0 :     logIO() << LogIO::DEBUGGING << "Starting FFT of image" << LogIO::POST;
    2035             :     
    2036           0 :     Vector<Float> sincConv(nx);
    2037           0 :     Float centerX=nx/2;
    2038           0 :     for (Int ix=0;ix<nx;ix++) 
    2039             :       {
    2040           0 :         Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    2041           0 :         if(ix==centerX) sincConv(ix)=1.0;
    2042           0 :         else            sincConv(ix)=sin(x)/x;
    2043             :       }
    2044             :     
    2045           0 :     Vector<Complex> correction(nx);
    2046             :     //
    2047             :     // Do the Grid-correction
    2048             :     //
    2049             :     {
    2050           0 :       normalizeAvgPB();
    2051             :       
    2052           0 :       IPosition cursorShape(4, nx, 1, 1, 1);
    2053           0 :       IPosition axisPath(4, 0, 1, 2, 3);
    2054           0 :       LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    2055           0 :       LatticeIterator<Complex> lix(*lattice, lsx);
    2056             :           
    2057           0 :       verifyShapes(avgPB.shape(), image->shape());
    2058           0 :       Array<Float> avgBuf; avgPB.get(avgBuf);
    2059           0 :       if (max(avgBuf) < 1e-04)
    2060             :         throw(AipsError("Normalization by PB requested but either PB not found in the cache "
    2061           0 :                         "or is ill-formed."));
    2062             : 
    2063           0 :       LatticeStepper lpb(avgPB.shape(),cursorShape,axisPath);
    2064           0 :       LatticeIterator<Float> lipb(avgPB, lpb);
    2065             : 
    2066           0 :       Vector<Complex> griddedVis;
    2067             :       //
    2068             :       // Grid correct in anticipation of the convolution by the
    2069             :       // convFunc.  Each polarization plane is corrected by the
    2070             :       // appropraite primary beam.
    2071             :       //
    2072           0 :       for(lix.reset(),lipb.reset();!lix.atEnd();lix++,lipb++) 
    2073             :         {
    2074           0 :           Int iy=lix.position()(1);
    2075           0 :           gridder->correctX1D(correction,iy);
    2076           0 :           griddedVis = lix.rwVectorCursor();
    2077             :           
    2078           0 :           Vector<Float> PBCorrection(lipb.rwVectorCursor().shape());
    2079           0 :           PBCorrection = lipb.rwVectorCursor();
    2080           0 :           for(int ix=0;ix<nx;ix++) 
    2081             :             {
    2082             :               // PBCorrection(ix) = (FUNC(PBCorrection(ix)))/(sincConv(ix)*sincConv(iy));
    2083             :               
    2084             :               //
    2085             :               // This is with PS functions included
    2086             :               //
    2087             :               // if (doPBCorrection)
    2088             :               //        {
    2089             :               //          PBCorrection(ix) = FUNC(PBCorrection(ix))/(sincConv(ix)*sincConv(iy));
    2090             :               //          //PBCorrection(ix) = FUNC(PBCorrection(ix))*(sincConv(ix)*sincConv(iy));
    2091             :               //          if ((abs(PBCorrection(ix)*correction(ix))) >= pbLimit_p)
    2092             :               //            {lix.rwVectorCursor()(ix) /= (PBCorrection(ix))*correction(ix);}
    2093             :               //          else
    2094             :               //            {lix.rwVectorCursor()(ix) *= (sincConv(ix)*sincConv(iy));}
    2095             :               //        }
    2096             :               // else 
    2097             :               //        lix.rwVectorCursor()(ix) /= (correction(ix)/(sincConv(ix)*sincConv(iy)));
    2098             :               //
    2099             :               // This without the PS functions
    2100             :               //
    2101           0 :               if (doPBCorrection)
    2102             :                 {
    2103             :                   // PBCorrection(ix) = FUNC(PBCorrection(ix))/(sincConv(ix)*sincConv(iy));
    2104           0 :                   PBCorrection(ix) = FUNC(PBCorrection(ix))*(sincConv(ix)*sincConv(iy));
    2105             : //                PBCorrection(ix) = (PBCorrection(ix))*(sincConv(ix)*sincConv(iy));
    2106           0 :                   if ((abs(PBCorrection(ix))) >= pbLimit_p)
    2107           0 :                     {lix.rwVectorCursor()(ix) /= (PBCorrection(ix));}
    2108             :                   else
    2109           0 :                     {lix.rwVectorCursor()(ix) *= (sincConv(ix)*sincConv(iy));}
    2110             :                 }
    2111             :               else 
    2112           0 :                 lix.rwVectorCursor()(ix) /= (1.0/(sincConv(ix)*sincConv(iy)));
    2113             :             }
    2114             :         }
    2115             :     }
    2116             :     // {
    2117             :     //   ostringstream name;
    2118             :     //   cout << image->shape() << endl;
    2119             :     //   name << "theModel.im";
    2120             :     //   PagedImage<Float> tmp(image->shape(), image->coordinates(), name);
    2121             :     //   Array<Complex> buf;
    2122             :     //   Bool isRef = lattice->get(buf);
    2123             :     //   cout << "The model max. = " << max(buf) << endl;
    2124             :     //   LatticeExpr<Float> le(abs((*lattice)));
    2125             :     //   tmp.copyData(le);
    2126             :     // }
    2127             :     //
    2128             :     // Now do the FFT2D in place
    2129             :     //
    2130             : //     {
    2131             : //       Array<Complex> buf;
    2132             : //       Bool isRef = lattice->get(buf);
    2133             : //     }
    2134           0 :     LatticeFFT::cfft2d(*lattice);
    2135             : 
    2136           0 :     logIO() << LogIO::DEBUGGING << "Finished FFT" << LogIO::POST;
    2137           0 :   }
    2138             :   //
    2139             :   //---------------------------------------------------------------
    2140             :   //
    2141           0 :   void nPBWProjectFT::initializeToVis(ImageInterface<Complex>& iimage,
    2142             :                                      const VisBuffer& vb,
    2143             :                                      Array<Complex>& griddedVis,
    2144             :                                      Vector<Double>& uvscale)
    2145             :   {
    2146           0 :     initializeToVis(iimage, vb);
    2147           0 :     griddedVis.assign(griddedData); //using the copy for storage
    2148           0 :     uvscale.assign(uvScale);
    2149           0 :   }
    2150             :   //
    2151             :   //---------------------------------------------------------------
    2152             :   //
    2153           0 :   void nPBWProjectFT::finalizeToVis()
    2154             :   {
    2155           0 :     logIO() << "##########finalizeToVis()###########" << LogIO::DEBUGGING << LogIO::POST;
    2156           0 :     if(isTiled) 
    2157             :       {
    2158           0 :         logIO() << LogOrigin("nPBWProjectFT", "finalizeToVis")  << LogIO::NORMAL;
    2159             :         
    2160           0 :         AlwaysAssert(imageCache, AipsError);
    2161           0 :         AlwaysAssert(image, AipsError);
    2162           0 :         ostringstream o;
    2163           0 :         imageCache->flush();
    2164           0 :         imageCache->showCacheStatistics(o);
    2165           0 :         logIO() << o.str() << LogIO::POST;
    2166             :       }
    2167           0 :     if(pointingToImage) delete pointingToImage; pointingToImage=0;
    2168           0 :   }
    2169             :   //
    2170             :   //---------------------------------------------------------------
    2171             :   //
    2172             :   // Initialize the FFT to the Sky. Here we have to setup and
    2173             :   // initialize the grid.
    2174             :   //
    2175           0 :   void nPBWProjectFT::initializeToSky(ImageInterface<Complex>& iimage,
    2176             :                                      Matrix<Float>& weight,
    2177             :                                      const VisBuffer& vb)
    2178             :   {
    2179           0 :     logIO() << "#########initializeToSky()##########" << LogIO::DEBUGGING << LogIO::POST;
    2180             :     
    2181             :     // image always points to the image
    2182           0 :     image=&iimage;
    2183             :     
    2184           0 :     init();
    2185           0 :     initMaps(vb);
    2186             :     
    2187             :     // Initialize the maps for polarization and channel. These maps
    2188             :     // translate visibility indices into image indices
    2189             :     
    2190           0 :     nx    = image->shape()(0);
    2191           0 :     ny    = image->shape()(1);
    2192           0 :     npol  = image->shape()(2);
    2193           0 :     nchan = image->shape()(3);
    2194             :     
    2195           0 :     if(image->shape().product()>cachesize) isTiled=true;
    2196           0 :     else                                   isTiled=false;
    2197             :     
    2198             :     
    2199           0 :     sumWeight=0.0;
    2200           0 :     weight.resize(sumWeight.shape());
    2201           0 :     weight=0.0;
    2202             :     //
    2203             :     // Initialize for in memory or to disk gridding. lattice will
    2204             :     // point to the appropriate Lattice, either the ArrayLattice for
    2205             :     // in memory gridding or to the image for to disk gridding.
    2206             :     //
    2207           0 :     if(isTiled) 
    2208             :       {
    2209           0 :         imageCache->flush();
    2210           0 :         image->set(Complex(0.0));
    2211           0 :         lattice=CountedPtr<Lattice<Complex> > (image, false);
    2212             :       }
    2213             :     else 
    2214             :       {
    2215           0 :         IPosition gridShape(4, nx, ny, npol, nchan);
    2216           0 :         griddedData.resize(gridShape);
    2217           0 :         griddedData=Complex(0.0);
    2218           0 :         arrayLattice = new ArrayLattice<Complex>(griddedData);
    2219           0 :         lattice=arrayLattice;
    2220             :       }
    2221           0 :     PAIndex = -1;
    2222           0 :   }
    2223             :   //
    2224             :   //---------------------------------------------------------------
    2225             :   //
    2226           0 :   void nPBWProjectFT::finalizeToSky()
    2227             :   {
    2228             :     //
    2229             :     // Now we flush the cache and report statistics For memory based,
    2230             :     // we don't write anything out yet.
    2231             :     //
    2232           0 :     logIO() << "#########finalizeToSky()#########" << LogIO::DEBUGGING << LogIO::POST;
    2233           0 :     if(isTiled) 
    2234             :       {
    2235           0 :         logIO() << LogOrigin("nPBWProjectFT", "finalizeToSky")  << LogIO::NORMAL;
    2236             :         
    2237           0 :         AlwaysAssert(image, AipsError);
    2238           0 :         AlwaysAssert(imageCache, AipsError);
    2239           0 :         imageCache->flush();
    2240           0 :         ostringstream o;
    2241           0 :         imageCache->showCacheStatistics(o);
    2242           0 :         logIO() << o.str() << LogIO::POST;
    2243             :       }
    2244           0 :     if(pointingToImage) delete pointingToImage; pointingToImage=0;
    2245           0 :     PAIndex = -1;
    2246             : 
    2247           0 :     paChangeDetector.reset();
    2248           0 :     cfCache.finalize();
    2249           0 :     convFuncCacheReady=true;
    2250           0 :   }
    2251             :   //
    2252             :   //---------------------------------------------------------------
    2253             :   //
    2254           0 :   Array<Complex>* nPBWProjectFT::getDataPointer(const IPosition& centerLoc2D,
    2255             :                                                Bool readonly) 
    2256             :   {
    2257             :     Array<Complex>* result;
    2258             :     // Is tiled: get tiles and set up offsets
    2259           0 :     centerLoc(0)=centerLoc2D(0);
    2260           0 :     centerLoc(1)=centerLoc2D(1);
    2261           0 :     result=&imageCache->tile(offsetLoc, centerLoc, readonly);
    2262           0 :     gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    2263           0 :     return result;
    2264             :   }
    2265             :   
    2266             : #define NEED_UNDERSCORES
    2267             : #if defined(NEED_UNDERSCORES)
    2268             : #define gpbwproj gpbwproj_
    2269             : #define dpbwproj dpbwproj_
    2270             : #define dpbwgrad dpbwgrad_
    2271             : #endif
    2272             :   
    2273             :   extern "C" { 
    2274             :     void gpbwproj(Double *uvw,
    2275             :                   Double *dphase,
    2276             :                   const Complex *values,
    2277             :                   Int *nvispol,
    2278             :                   Int *nvischan,
    2279             :                   Int *dopsf,
    2280             :                   const Int *flag,
    2281             :                   const Int *rflag,
    2282             :                   const Float *weight,
    2283             :                   Int *nrow,
    2284             :                   Int *rownum,
    2285             :                   Double *scale,
    2286             :                   Double *offset,
    2287             :                   Complex *grid,
    2288             :                   Int *nx,
    2289             :                   Int *ny,
    2290             :                   Int *npol,
    2291             :                   Int *nchan,
    2292             :                   const Double *freq,
    2293             :                   const Double *c,
    2294             :                   Int *support,
    2295             :                   Int *convsize,
    2296             :                   Int *sampling,
    2297             :                   Int *wconvsize,
    2298             :                   Complex *convfunc,
    2299             :                   Int *chanmap,
    2300             :                   Int *polmap,
    2301             :                   Int *polused,
    2302             :                   Double *sumwt,
    2303             :                   Int *ant1,
    2304             :                   Int *ant2,
    2305             :                   Int *nant,
    2306             :                   Int *scanno,
    2307             :                   Double *sigma,
    2308             :                   Float *raoff,
    2309             :                   Float *decoff,
    2310             :                   Double *area,
    2311             :                   Int *doGrad,
    2312             :                   Int *doPointingCorrection,
    2313             :                   Int *nPA,
    2314             :                   Int *paIndex,
    2315             :                   Int *CFMap,
    2316             :                   Int *ConjCFMap,
    2317             :                   Double *currentCFPA, Double *actualPA,Double *cfRefFreq_p);
    2318             :     void dpbwproj(Double *uvw,
    2319             :                   Double *dphase,
    2320             :                   Complex *values,
    2321             :                   Int *nvispol,
    2322             :                   Int *nvischan,
    2323             :                   const Int *flag,
    2324             :                   const Int *rflag,
    2325             :                   Int *nrow,
    2326             :                   Int *rownum,
    2327             :                   Double *scale,
    2328             :                   Double *offset,
    2329             :                   const Complex *grid,
    2330             :                   Int *nx,
    2331             :                   Int *ny,
    2332             :                   Int *npol,
    2333             :                   Int *nchan,
    2334             :                   const Double *freq,
    2335             :                   const Double *c,
    2336             :                   Int *support,
    2337             :                   Int *convsize,
    2338             :                   Int *sampling,
    2339             :                   Int *wconvsize,
    2340             :                   Complex *convfunc,
    2341             :                   Int *chanmap,
    2342             :                   Int *polmap,
    2343             :                   Int *polused,
    2344             :                   Int *ant1, 
    2345             :                   Int *ant2, 
    2346             :                   Int *nant, 
    2347             :                   Int *scanno,
    2348             :                   Double *sigma, 
    2349             :                   Float *raoff, Float *decoff,
    2350             :                   Double *area, 
    2351             :                   Int *dograd,
    2352             :                   Int *doPointingCorrection,
    2353             :                   Int *nPA,
    2354             :                   Int *paIndex,
    2355             :                   Int *CFMap,
    2356             :                   Int *ConjCFMap,
    2357             :                   Double *currentCFPA, Double *actualPA, Double *cfRefFreq_p);
    2358             :     void dpbwgrad(Double *uvw,
    2359             :                   Double *dphase,
    2360             :                   Complex *values,
    2361             :                   Int *nvispol,
    2362             :                   Int *nvischan,
    2363             :                   Complex *gazvalues,
    2364             :                   Complex *gelvalues,
    2365             :                   Int *doconj,
    2366             :                   const Int *flag,
    2367             :                   const Int *rflag,
    2368             :                   Int *nrow,
    2369             :                   Int *rownum,
    2370             :                   Double *scale,
    2371             :                   Double *offset,
    2372             :                   const Complex *grid,
    2373             :                   Int *nx,
    2374             :                   Int *ny,
    2375             :                   Int *npol,
    2376             :                   Int *nchan,
    2377             :                   const Double *freq,
    2378             :                   const Double *c,
    2379             :                   Int *support,
    2380             :                   Int *convsize,
    2381             :                   Int *sampling,
    2382             :                   Int *wconvsize,
    2383             :                   Complex *convfunc,
    2384             :                   Int *chanmap,
    2385             :                   Int *polmap,
    2386             :                   Int *polused,
    2387             :                   Int *ant1, 
    2388             :                   Int *ant2, 
    2389             :                   Int *nant, 
    2390             :                   Int *scanno,
    2391             :                   Double *sigma, 
    2392             :                   Float *raoff, Float *decoff,
    2393             :                   Double *area, 
    2394             :                   Int *dograd,
    2395             :                   Int *doPointingCorrection,
    2396             :                   Int *nPA,
    2397             :                   Int *paIndex,
    2398             :                   Int *CFMap,
    2399             :                   Int *ConjCFMap,
    2400             :                   Double *currentCFPA, Double *actualPA, Double *cfRefFreq_p);
    2401             :   }
    2402             :   //
    2403             :   //----------------------------------------------------------------------
    2404             :   //
    2405           0 :   void nPBWProjectFT::runFortranGet(Matrix<Double>& uvw,Vector<Double>& dphase,
    2406             :                                    Cube<Complex>& visdata,
    2407             :                                    IPosition& s,
    2408             :                                    //                           Cube<Complex>& gradVisAzData,
    2409             :                                    //                           Cube<Complex>& gradVisElData,
    2410             :                                    //                           IPosition& gradS,
    2411             :                                     Int& /*Conj*/,
    2412             :                                    Cube<Int>& flags,Vector<Int>& rowFlags,
    2413             :                                    Int& rownr,Vector<Double>& actualOffset,
    2414             :                                    Array<Complex>* dataPtr,
    2415             :                                    Int& aNx, Int& aNy, Int& npol, Int& nchan,
    2416             :                                    VisBuffer& vb,Int& Nant_p, Int& scanNo,
    2417             :                                    Double& sigma,
    2418             :                                    Array<Float>& l_off,
    2419             :                                    Array<Float>& m_off,
    2420             :                                    Double area,
    2421             :                                    Int& doGrad,
    2422             :                                    Int paIndex)
    2423             :   {
    2424             :     enum whichGetStorage {RAOFF,DECOFF,UVW,DPHASE,VISDATA,GRADVISAZ,GRADVISEL,
    2425             :                           FLAGS,ROWFLAGS,UVSCALE,ACTUALOFFSET,DATAPTR,VBFREQ,
    2426             :                           CONVSUPPORT,CONVFUNC,CHANMAP,POLMAP,VBANT1,VBANT2,CONJCFMAP,CFMAP};
    2427           0 :     Vector<Bool> deleteThem(21);
    2428             :     
    2429             :     Double *uvw_p, *dphase_p, *actualOffset_p, *vb_freq_p, *uvScale_p;
    2430             :     Complex *visdata_p, *dataPtr_p, *f_convFunc_p;
    2431             :     Int *flags_p, *rowFlags_p, *chanMap_p, *polMap_p, *convSupport_p, *vb_ant1_p, *vb_ant2_p,
    2432             :       *ConjCFMap_p, *CFMap_p;
    2433             :     Float *l_off_p, *m_off_p;
    2434             :     Double actualPA;
    2435             :     
    2436           0 :     Vector<Int> ConjCFMap, CFMap;
    2437             :     /*
    2438             :       ConjCFMap = CFMap = polMap;
    2439             :       CFMap = makeConjPolMap(vb);
    2440             :     */
    2441             :     Int N;
    2442           0 :     actualPA = getVBPA(vb);
    2443             : 
    2444           0 :     N=polMap.nelements();
    2445           0 :     CFMap = polMap; ConjCFMap = polMap;
    2446           0 :     for(Int i=0;i<N;i++) CFMap[i] = polMap[N-i-1];
    2447             :     
    2448           0 :     Array<Complex> rotatedConvFunc;
    2449             : //     SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2450             : //                                     rotatedConvFunc,(currentCFPA-actualPA),"CUBIC");
    2451           0 :     SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2452             :                                        rotatedConvFunc,0.0,"LINEAR");
    2453             :     // SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2454             :     //                                 rotatedConvFunc,(currentCFPA-actualPA),"LINEAR");
    2455             : 
    2456           0 :     ConjCFMap = polMap;
    2457           0 :     makeCFPolMap(vb,CFMap);
    2458           0 :     makeConjPolMap(vb,CFMap,ConjCFMap);
    2459             : 
    2460             :     
    2461           0 :     ConjCFMap_p     = ConjCFMap.getStorage(deleteThem(CONJCFMAP));
    2462           0 :     CFMap_p         = CFMap.getStorage(deleteThem(CFMAP));
    2463             :     
    2464           0 :     uvw_p           = uvw.getStorage(deleteThem(UVW));
    2465           0 :     dphase_p        = dphase.getStorage(deleteThem(DPHASE));
    2466           0 :     visdata_p       = visdata.getStorage(deleteThem(VISDATA));
    2467             :     //  gradVisAzData_p = gradVisAzData.getStorage(deleteThem(GRADVISAZ));
    2468             :     //  gradVisElData_p = gradVisElData.getStorage(deleteThem(GRADVISEL));
    2469           0 :     flags_p         = flags.getStorage(deleteThem(FLAGS));
    2470           0 :     rowFlags_p      = rowFlags.getStorage(deleteThem(ROWFLAGS));
    2471           0 :     uvScale_p       = uvScale.getStorage(deleteThem(UVSCALE));
    2472           0 :     actualOffset_p  = actualOffset.getStorage(deleteThem(ACTUALOFFSET));
    2473           0 :     dataPtr_p       = dataPtr->getStorage(deleteThem(DATAPTR));
    2474           0 :     vb_freq_p       = vb.frequency().getStorage(deleteThem(VBFREQ));
    2475           0 :     convSupport_p   = convSupport.getStorage(deleteThem(CONVSUPPORT));
    2476             :     //    f_convFunc_p      = convFunc.getStorage(deleteThem(CONVFUNC));
    2477           0 :     f_convFunc_p      = rotatedConvFunc.getStorage(deleteThem(CONVFUNC));
    2478           0 :     chanMap_p       = chanMap.getStorage(deleteThem(CHANMAP));
    2479           0 :     polMap_p        = polMap.getStorage(deleteThem(POLMAP));
    2480           0 :     vb_ant1_p       = vb.antenna1().getStorage(deleteThem(VBANT1));
    2481           0 :     vb_ant2_p       = vb.antenna2().getStorage(deleteThem(VBANT2));
    2482           0 :     l_off_p     = l_off.getStorage(deleteThem(RAOFF));
    2483           0 :     m_off_p    = m_off.getStorage(deleteThem(DECOFF));
    2484             :     
    2485           0 :     Int npa=convSupport.shape()(2),actualConvSize;
    2486           0 :     Int paIndex_Fortran = paIndex;
    2487           0 :     actualConvSize = convFunc.shape()(0);
    2488             :     
    2489           0 :     IPosition shp=convSupport.shape();
    2490             :     
    2491           0 :     dpbwproj(uvw_p,
    2492             :              dphase_p,
    2493             :              //           vb.modelVisCube().getStorage(del),
    2494             :              visdata_p,
    2495           0 :              &s.asVector()(0),
    2496           0 :              &s.asVector()(1),
    2497             :              //    gradVisAzData_p,
    2498             :              //    gradVisElData_p,
    2499             :              //     &gradS(0),
    2500             :              //     &gradS(1),
    2501             :              //    &Conj,
    2502             :              flags_p,
    2503             :              rowFlags_p,
    2504           0 :              &s.asVector()(2),
    2505             :              &rownr,
    2506             :              uvScale_p,
    2507             :              actualOffset_p,
    2508             :              dataPtr_p,
    2509             :              &aNx,
    2510             :              &aNy,
    2511             :              &npol,
    2512             :              &nchan,
    2513             :              vb_freq_p,
    2514             :              &C::c,
    2515             :              convSupport_p,
    2516             :              &actualConvSize,
    2517             :              &convSampling,
    2518             :              &wConvSize,
    2519             :              f_convFunc_p,
    2520             :              chanMap_p,
    2521             :              polMap_p,
    2522             :              &polInUse,
    2523             :              vb_ant1_p,
    2524             :              vb_ant2_p,
    2525             :              &Nant_p,
    2526             :              &scanNo,
    2527             :              &sigma,
    2528             :              l_off_p, m_off_p,
    2529             :              &area,
    2530             :              &doGrad,
    2531             :              &doPointing,
    2532             :              &npa,
    2533             :              &paIndex_Fortran,
    2534             :              CFMap_p,
    2535             :              ConjCFMap_p,
    2536             :              &currentCFPA
    2537             :              ,&actualPA,&cfRefFreq_p
    2538             :              );
    2539             :     
    2540           0 :     ConjCFMap.freeStorage((const Int *&)ConjCFMap_p,deleteThem(CONJCFMAP));
    2541           0 :     CFMap.freeStorage((const Int *&)CFMap_p,deleteThem(CFMAP));
    2542             :     
    2543           0 :     l_off.freeStorage((const Float*&)l_off_p,deleteThem(RAOFF));
    2544           0 :     m_off.freeStorage((const Float*&)m_off_p,deleteThem(DECOFF));
    2545           0 :     uvw.freeStorage((const Double*&)uvw_p,deleteThem(UVW));
    2546           0 :     dphase.freeStorage((const Double*&)dphase_p,deleteThem(DPHASE));
    2547           0 :     visdata.putStorage(visdata_p,deleteThem(VISDATA));
    2548           0 :     flags.freeStorage((const Int*&) flags_p,deleteThem(FLAGS));
    2549           0 :     rowFlags.freeStorage((const Int *&)rowFlags_p,deleteThem(ROWFLAGS));
    2550           0 :     actualOffset.freeStorage((const Double*&)actualOffset_p,deleteThem(ACTUALOFFSET));
    2551           0 :     dataPtr->freeStorage((const Complex *&)dataPtr_p,deleteThem(DATAPTR));
    2552           0 :     uvScale.freeStorage((const Double*&) uvScale_p,deleteThem(UVSCALE));
    2553           0 :     vb.frequency().freeStorage((const Double*&)vb_freq_p,deleteThem(VBFREQ));
    2554           0 :     convSupport.freeStorage((const Int*&)convSupport_p,deleteThem(CONVSUPPORT));
    2555           0 :     convFunc.freeStorage((const Complex *&)f_convFunc_p,deleteThem(CONVFUNC));
    2556           0 :     chanMap.freeStorage((const Int*&)chanMap_p,deleteThem(CHANMAP));
    2557           0 :     polMap.freeStorage((const Int*&) polMap_p,deleteThem(POLMAP));
    2558           0 :     vb.antenna1().freeStorage((const Int*&) vb_ant1_p,deleteThem(VBANT1));
    2559           0 :     vb.antenna2().freeStorage((const Int*&) vb_ant2_p,deleteThem(VBANT2));
    2560           0 :   }
    2561             :   //
    2562             :   //----------------------------------------------------------------------
    2563             :   //
    2564           0 :   void nPBWProjectFT::runFortranGetGrad(Matrix<Double>& uvw,Vector<Double>& dphase,
    2565             :                                        Cube<Complex>& visdata,
    2566             :                                        IPosition& s,
    2567             :                                        Cube<Complex>& gradVisAzData,
    2568             :                                        Cube<Complex>& gradVisElData,
    2569             :                                        //                                    IPosition& gradS,
    2570             :                                        Int& Conj,
    2571             :                                        Cube<Int>& flags,Vector<Int>& rowFlags,
    2572             :                                        Int& rownr,Vector<Double>& actualOffset,
    2573             :                                        Array<Complex>* dataPtr,
    2574             :                                        Int& aNx, Int& aNy, Int& npol, Int& nchan,
    2575             :                                        VisBuffer& vb,Int& Nant_p, Int& scanNo,
    2576             :                                        Double& sigma,
    2577             :                                        Array<Float>& l_off,
    2578             :                                        Array<Float>& m_off,
    2579             :                                        Double area,
    2580             :                                        Int& doGrad,
    2581             :                                        Int paIndex)
    2582             :   {
    2583             :     enum whichGetStorage {RAOFF,DECOFF,UVW,DPHASE,VISDATA,GRADVISAZ,GRADVISEL,
    2584             :                           FLAGS,ROWFLAGS,UVSCALE,ACTUALOFFSET,DATAPTR,VBFREQ,
    2585             :                           CONVSUPPORT,CONVFUNC,CHANMAP,POLMAP,VBANT1,VBANT2,CONJCFMAP,CFMAP};
    2586           0 :     Vector<Bool> deleteThem(21);
    2587             :     
    2588             :     Double *uvw_p, *dphase_p, *actualOffset_p, *vb_freq_p, *uvScale_p;
    2589             :     Complex *visdata_p, *dataPtr_p, *f_convFunc_p;
    2590             :     Complex *gradVisAzData_p, *gradVisElData_p;
    2591             :     Int *flags_p, *rowFlags_p, *chanMap_p, *polMap_p, *convSupport_p, *vb_ant1_p, *vb_ant2_p,
    2592             :       *ConjCFMap_p, *CFMap_p;
    2593             :     Float *l_off_p, *m_off_p;
    2594             :     Double actualPA;
    2595             : 
    2596           0 :     Vector<Int> ConjCFMap, CFMap;
    2597           0 :     actualPA = getVBPA(vb);
    2598           0 :     ConjCFMap = polMap;
    2599           0 :     makeCFPolMap(vb,CFMap);
    2600           0 :     makeConjPolMap(vb,CFMap,ConjCFMap);
    2601             : 
    2602           0 :     Array<Complex> rotatedConvFunc;
    2603             : //     SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2604             : //                                     rotatedConvFunc,(currentCFPA-actualPA),"LINEAR");
    2605           0 :     SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2606             :                                        rotatedConvFunc,0.0);
    2607             :     // SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2608             :     //                                 rotatedConvFunc,(currentCFPA-actualPA),"LINEAR");
    2609             : 
    2610           0 :     ConjCFMap_p     = ConjCFMap.getStorage(deleteThem(CONJCFMAP));
    2611           0 :     CFMap_p         = CFMap.getStorage(deleteThem(CFMAP));
    2612             :     
    2613           0 :     uvw_p           = uvw.getStorage(deleteThem(UVW));
    2614           0 :     dphase_p        = dphase.getStorage(deleteThem(DPHASE));
    2615           0 :     visdata_p       = visdata.getStorage(deleteThem(VISDATA));
    2616           0 :     gradVisAzData_p = gradVisAzData.getStorage(deleteThem(GRADVISAZ));
    2617           0 :     gradVisElData_p = gradVisElData.getStorage(deleteThem(GRADVISEL));
    2618           0 :     flags_p         = flags.getStorage(deleteThem(FLAGS));
    2619           0 :     rowFlags_p      = rowFlags.getStorage(deleteThem(ROWFLAGS));
    2620           0 :     uvScale_p       = uvScale.getStorage(deleteThem(UVSCALE));
    2621           0 :     actualOffset_p  = actualOffset.getStorage(deleteThem(ACTUALOFFSET));
    2622           0 :     dataPtr_p       = dataPtr->getStorage(deleteThem(DATAPTR));
    2623           0 :     vb_freq_p       = vb.frequency().getStorage(deleteThem(VBFREQ));
    2624           0 :     convSupport_p   = convSupport.getStorage(deleteThem(CONVSUPPORT));
    2625             :     //    f_convFunc_p      = convFunc.getStorage(deleteThem(CONVFUNC));
    2626           0 :     f_convFunc_p      = rotatedConvFunc.getStorage(deleteThem(CONVFUNC));
    2627           0 :     chanMap_p       = chanMap.getStorage(deleteThem(CHANMAP));
    2628           0 :     polMap_p        = polMap.getStorage(deleteThem(POLMAP));
    2629           0 :     vb_ant1_p       = vb.antenna1().getStorage(deleteThem(VBANT1));
    2630           0 :     vb_ant2_p       = vb.antenna2().getStorage(deleteThem(VBANT2));
    2631           0 :     l_off_p     = l_off.getStorage(deleteThem(RAOFF));
    2632           0 :     m_off_p    = m_off.getStorage(deleteThem(DECOFF));
    2633             :     
    2634           0 :     Int npa=convSupport.shape()(2),actualConvSize;
    2635           0 :     Int paIndex_Fortran = paIndex;
    2636           0 :     actualConvSize = convFunc.shape()(0);
    2637             :     
    2638           0 :     IPosition shp=convSupport.shape();
    2639             : 
    2640           0 :     dpbwgrad(uvw_p,
    2641             :              dphase_p,
    2642             :              //           vb.modelVisCube().getStorage(del),
    2643             :              visdata_p,
    2644           0 :              &s.asVector()(0),
    2645           0 :              &s.asVector()(1),
    2646             :              gradVisAzData_p,
    2647             :              gradVisElData_p,
    2648             :              //     &gradS(0),
    2649             :              //     &gradS(1),
    2650             :              &Conj,
    2651             :              flags_p,
    2652             :              rowFlags_p,
    2653           0 :              &s.asVector()(2),
    2654             :              &rownr,
    2655             :              uvScale_p,
    2656             :              actualOffset_p,
    2657             :              dataPtr_p,
    2658             :              &aNx,
    2659             :              &aNy,
    2660             :              &npol,
    2661             :              &nchan,
    2662             :              vb_freq_p,
    2663             :              &C::c,
    2664             :              convSupport_p,
    2665             :              &actualConvSize,
    2666             :              &convSampling,
    2667             :              &wConvSize,
    2668             :              f_convFunc_p,
    2669             :              chanMap_p,
    2670             :              polMap_p,
    2671             :              &polInUse,
    2672             :              vb_ant1_p,
    2673             :              vb_ant2_p,
    2674             :              &Nant_p,
    2675             :              &scanNo,
    2676             :              &sigma,
    2677             :              l_off_p, m_off_p,
    2678             :              &area,
    2679             :              &doGrad,
    2680             :              &doPointing,
    2681             :              &npa,
    2682             :              &paIndex_Fortran,
    2683             :              CFMap_p,
    2684             :              ConjCFMap_p,
    2685             :              &currentCFPA
    2686             :              ,&actualPA,&cfRefFreq_p
    2687             :              );
    2688             : 
    2689           0 :     ConjCFMap.freeStorage((const Int *&)ConjCFMap_p,deleteThem(CONJCFMAP));
    2690           0 :     CFMap.freeStorage((const Int *&)CFMap_p,deleteThem(CFMAP));
    2691             :     
    2692           0 :     l_off.freeStorage((const Float*&)l_off_p,deleteThem(RAOFF));
    2693           0 :     m_off.freeStorage((const Float*&)m_off_p,deleteThem(DECOFF));
    2694           0 :     uvw.freeStorage((const Double*&)uvw_p,deleteThem(UVW));
    2695           0 :     dphase.freeStorage((const Double*&)dphase_p,deleteThem(DPHASE));
    2696           0 :     visdata.putStorage(visdata_p,deleteThem(VISDATA));
    2697           0 :     gradVisAzData.putStorage(gradVisAzData_p,deleteThem(GRADVISAZ));
    2698           0 :     gradVisElData.putStorage(gradVisElData_p,deleteThem(GRADVISEL));
    2699           0 :     flags.freeStorage((const Int*&) flags_p,deleteThem(FLAGS));
    2700           0 :     rowFlags.freeStorage((const Int *&)rowFlags_p,deleteThem(ROWFLAGS));
    2701           0 :     actualOffset.freeStorage((const Double*&)actualOffset_p,deleteThem(ACTUALOFFSET));
    2702           0 :     dataPtr->freeStorage((const Complex *&)dataPtr_p,deleteThem(DATAPTR));
    2703           0 :     uvScale.freeStorage((const Double*&) uvScale_p,deleteThem(UVSCALE));
    2704           0 :     vb.frequency().freeStorage((const Double*&)vb_freq_p,deleteThem(VBFREQ));
    2705           0 :     convSupport.freeStorage((const Int*&)convSupport_p,deleteThem(CONVSUPPORT));
    2706           0 :     convFunc.freeStorage((const Complex *&)f_convFunc_p,deleteThem(CONVFUNC));
    2707           0 :     chanMap.freeStorage((const Int*&)chanMap_p,deleteThem(CHANMAP));
    2708           0 :     polMap.freeStorage((const Int*&) polMap_p,deleteThem(POLMAP));
    2709           0 :     vb.antenna1().freeStorage((const Int*&) vb_ant1_p,deleteThem(VBANT1));
    2710           0 :     vb.antenna2().freeStorage((const Int*&) vb_ant2_p,deleteThem(VBANT2));
    2711           0 :   }
    2712             :   //
    2713             :   //----------------------------------------------------------------------
    2714             :   //
    2715           0 :   void nPBWProjectFT::runFortranPut(Matrix<Double>& uvw,Vector<Double>& dphase,
    2716             :                                    const Complex& visdata,
    2717             :                                    IPosition& s,
    2718             :                                    //                           Cube<Complex>& gradVisAzData,
    2719             :                                    //                           Cube<Complex>& gradVisElData,
    2720             :                                    //                           IPosition& gradS,
    2721             :                                     Int& /*Conj*/,
    2722             :                                    Cube<Int>& flags,Vector<Int>& rowFlags,
    2723             :                                    const Matrix<Float>& weight,
    2724             :                                    Int& rownr,Vector<Double>& actualOffset,
    2725             :                                    Array<Complex>& dataPtr,
    2726             :                                    Int& aNx, Int& aNy, Int& npol, Int& nchan,
    2727             :                                    const VisBuffer& vb,Int& Nant_p, Int& scanNo,
    2728             :                                    Double& sigma,
    2729             :                                    Array<Float>& l_off,
    2730             :                                    Array<Float>& m_off,
    2731             :                                    Matrix<Double>& sumWeight,
    2732             :                                    Double& area,
    2733             :                                    Int& doGrad,
    2734             :                                    Int& doPSF,
    2735             :                                    Int paIndex)
    2736             :   {
    2737             :     enum whichGetStorage {RAOFF,DECOFF,UVW,DPHASE,VISDATA,GRADVISAZ,GRADVISEL,
    2738             :                           FLAGS,ROWFLAGS,UVSCALE,ACTUALOFFSET,DATAPTR,VBFREQ,
    2739             :                           CONVSUPPORT,CONVFUNC,CHANMAP,POLMAP,VBANT1,VBANT2,WEIGHT,
    2740             :                           SUMWEIGHT,CONJCFMAP,CFMAP};
    2741           0 :     Vector<Bool> deleteThem(23);
    2742             :     
    2743             :     Double *uvw_p, *dphase_p, *actualOffset_p, *vb_freq_p, *uvScale_p;
    2744             :     Complex *dataPtr_p, *f_convFunc_p;
    2745             :     //  Complex *gradVisAzData_p, *gradVisElData_p;
    2746             :     Int *flags_p, *rowFlags_p, *chanMap_p, *polMap_p, *convSupport_p, *vb_ant1_p, *vb_ant2_p,
    2747             :       *ConjCFMap_p, *CFMap_p;
    2748             :     Float *l_off_p, *m_off_p;
    2749             :     Float *weight_p;Double *sumwt_p;
    2750             :     Double actualPA;
    2751           0 :     const Complex *visdata_p=&visdata;
    2752             :     
    2753           0 :     Vector<Int> ConjCFMap, CFMap;
    2754           0 :     actualPA = getVBPA(vb);
    2755           0 :     ConjCFMap = polMap;
    2756             : 
    2757           0 :     Array<Complex> rotatedConvFunc;
    2758             : //    SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2759             : //                                     rotatedConvFunc,(currentCFPA-actualPA),"LINEAR");
    2760           0 :      SynthesisUtils::rotateComplexArray(logIO(), convFunc, convFuncCS_p, 
    2761             :                                        rotatedConvFunc,0.0,"LINEAR");
    2762             : 
    2763             :     /*
    2764             :     CFMap = polMap; ConjCFMap = polMap;
    2765             :     CFMap = makeConjPolMap(vb);
    2766             :     */
    2767           0 :      makeCFPolMap(vb,CFMap);
    2768           0 :     makeConjPolMap(vb,CFMap,ConjCFMap);
    2769             : 
    2770           0 :     ConjCFMap_p     = ConjCFMap.getStorage(deleteThem(CONJCFMAP));
    2771           0 :     CFMap_p         = CFMap.getStorage(deleteThem(CFMAP));
    2772             :     
    2773           0 :     uvw_p           = uvw.getStorage(deleteThem(UVW));
    2774           0 :     dphase_p        = dphase.getStorage(deleteThem(DPHASE));
    2775             :     //  visdata_p       = visdata.getStorage(deleteThem(VISDATA));
    2776             :     //  gradVisAzData_p = gradVisAzData.getStorage(deleteThem(GRADVISAZ));
    2777             :     //  gradVisElData_p = gradVisElData.getStorage(deleteThem(GRADVISEL));
    2778           0 :     flags_p         = flags.getStorage(deleteThem(FLAGS));
    2779           0 :     rowFlags_p      = rowFlags.getStorage(deleteThem(ROWFLAGS));
    2780           0 :     uvScale_p       = uvScale.getStorage(deleteThem(UVSCALE));
    2781           0 :     actualOffset_p  = actualOffset.getStorage(deleteThem(ACTUALOFFSET));
    2782           0 :     dataPtr_p       = dataPtr.getStorage(deleteThem(DATAPTR));
    2783           0 :     vb_freq_p       = (Double *)(vb.frequency().getStorage(deleteThem(VBFREQ)));
    2784           0 :     convSupport_p   = convSupport.getStorage(deleteThem(CONVSUPPORT));
    2785             :     //    f_convFunc_p      = convFunc.getStorage(deleteThem(CONVFUNC));
    2786           0 :     f_convFunc_p      = rotatedConvFunc.getStorage(deleteThem(CONVFUNC));
    2787           0 :     chanMap_p       = chanMap.getStorage(deleteThem(CHANMAP));
    2788           0 :     polMap_p        = polMap.getStorage(deleteThem(POLMAP));
    2789           0 :     vb_ant1_p       = (Int *)(vb.antenna1().getStorage(deleteThem(VBANT1)));
    2790           0 :     vb_ant2_p       = (Int *)(vb.antenna2().getStorage(deleteThem(VBANT2)));
    2791           0 :     l_off_p     = l_off.getStorage(deleteThem(RAOFF));
    2792           0 :     m_off_p    = m_off.getStorage(deleteThem(DECOFF));
    2793           0 :     weight_p        = (Float *)(weight.getStorage(deleteThem(WEIGHT)));
    2794           0 :     sumwt_p         = sumWeight.getStorage(deleteThem(SUMWEIGHT));
    2795             :     
    2796             :     
    2797           0 :     Int npa=convSupport.shape()(2),actualConvSize;
    2798           0 :     Int paIndex_Fortran = paIndex; 
    2799           0 :     actualConvSize = convFunc.shape()(0);
    2800             :     
    2801           0 :     IPosition shp=convSupport.shape();
    2802             :     
    2803           0 :     gpbwproj(uvw_p,
    2804             :              dphase_p,
    2805             :              //           vb.modelVisCube().getStorage(del),
    2806             :              visdata_p,
    2807           0 :              &s.asVector()(0),
    2808           0 :              &s.asVector()(1),
    2809             :              //    gradVisAzData_p,
    2810             :              //    gradVisElData_p,
    2811             :              //     &gradS(0),
    2812             :              //     &gradS(1),
    2813             :              //    &Conj,
    2814             :              &doPSF,
    2815             :              flags_p,
    2816             :              rowFlags_p,
    2817             :              weight_p,
    2818           0 :              &s.asVector()(2),
    2819             :              &rownr,
    2820             :              uvScale_p,
    2821             :              actualOffset_p,
    2822             :              dataPtr_p,
    2823             :              &aNx,
    2824             :              &aNy,
    2825             :              &npol,
    2826             :              &nchan,
    2827             :              vb_freq_p,
    2828             :              &C::c,
    2829             :              convSupport_p,
    2830             :              &actualConvSize,
    2831             :              &convSampling,
    2832             :              &wConvSize,
    2833             :              f_convFunc_p,
    2834             :              chanMap_p,
    2835             :              polMap_p,
    2836             :              &polInUse,
    2837             :              sumwt_p,
    2838             :              vb_ant1_p,
    2839             :              vb_ant2_p,
    2840             :              &Nant_p,
    2841             :              &scanNo,
    2842             :              &sigma,
    2843             :              l_off_p, m_off_p,
    2844             :              &area,
    2845             :              &doGrad,
    2846             :              &doPointing,
    2847             :              &npa,
    2848             :              &paIndex_Fortran,
    2849             :              CFMap_p,
    2850             :              ConjCFMap_p,
    2851             :              &currentCFPA
    2852             :              ,&actualPA,&cfRefFreq_p
    2853             :              );
    2854             :     
    2855           0 :     ConjCFMap.freeStorage((const Int *&)ConjCFMap_p,deleteThem(CONJCFMAP));
    2856           0 :     CFMap.freeStorage((const Int *&)CFMap_p,deleteThem(CFMAP));
    2857             :     
    2858           0 :     l_off.freeStorage((const Float*&)l_off_p,deleteThem(RAOFF));
    2859           0 :     m_off.freeStorage((const Float*&)m_off_p,deleteThem(DECOFF));
    2860           0 :     uvw.freeStorage((const Double*&)uvw_p,deleteThem(UVW));
    2861           0 :     dphase.freeStorage((const Double*&)dphase_p,deleteThem(DPHASE));
    2862             :     //  visdata.putStorage(visdata_p,deleteThem(VISDATA));
    2863             :     //  gradVisAzData.putStorage(gradVisAzData_p,deleteThem(GRADVISAZ));
    2864             :     //  gradVisElData.putStorage(gradVisElData_p,deleteThem(GRADVISEL));
    2865           0 :     flags.freeStorage((const Int*&) flags_p,deleteThem(FLAGS));
    2866           0 :     rowFlags.freeStorage((const Int *&)rowFlags_p,deleteThem(ROWFLAGS));
    2867           0 :     actualOffset.freeStorage((const Double*&)actualOffset_p,deleteThem(ACTUALOFFSET));
    2868           0 :     dataPtr.freeStorage((const Complex *&)dataPtr_p,deleteThem(DATAPTR));
    2869           0 :     uvScale.freeStorage((const Double*&) uvScale_p,deleteThem(UVSCALE));
    2870           0 :     vb.frequency().freeStorage((const Double*&)vb_freq_p,deleteThem(VBFREQ));
    2871           0 :     convSupport.freeStorage((const Int*&)convSupport_p,deleteThem(CONVSUPPORT));
    2872           0 :     convFunc.freeStorage((const Complex *&)f_convFunc_p,deleteThem(CONVFUNC));
    2873           0 :     chanMap.freeStorage((const Int*&)chanMap_p,deleteThem(CHANMAP));
    2874           0 :     polMap.freeStorage((const Int*&) polMap_p,deleteThem(POLMAP));
    2875           0 :     vb.antenna1().freeStorage((const Int*&) vb_ant1_p,deleteThem(VBANT1));
    2876           0 :     vb.antenna2().freeStorage((const Int*&) vb_ant2_p,deleteThem(VBANT2));
    2877           0 :     weight.freeStorage((const Float*&)weight_p,deleteThem(WEIGHT));
    2878           0 :     sumWeight.putStorage(sumwt_p,deleteThem(SUMWEIGHT));
    2879           0 :   }
    2880             :   //
    2881             :   //---------------------------------------------------------------
    2882             :   //
    2883           0 :   void nPBWProjectFT::put(const VisBuffer& vb, Int row, Bool dopsf,
    2884             :                           FTMachine::Type type)
    2885             :   {
    2886             :     // Take care of translation of Bools to Integer
    2887           0 :     makingPSF=dopsf;
    2888             :     
    2889           0 :     findConvFunction(*image, vb);
    2890             :     
    2891             : 
    2892             :     const Matrix<Float> *imagingweight;
    2893           0 :     imagingweight=&(vb.imagingWeight());
    2894             : 
    2895             :     const Cube<Complex> *data;
    2896           0 :     if(type==FTMachine::MODEL)
    2897           0 :       data=&(vb.modelVisCube());
    2898           0 :     else if(type==FTMachine::CORRECTED)
    2899           0 :       data=&(vb.correctedVisCube());
    2900             :     else
    2901           0 :       data=&(vb.visCube());
    2902             :     
    2903             :     Bool isCopy;
    2904           0 :     const casacore::Complex *datStorage=data->getStorage(isCopy);
    2905           0 :     Int NAnt = 0;
    2906             : 
    2907           0 :     if (doPointing) NAnt = findPointingOffsets(vb,l_offsets,m_offsets,true);
    2908             :     
    2909             :     //
    2910             :     // If row is -1 then we pass through all rows
    2911             :     //
    2912             :     Int startRow, endRow, nRow;
    2913           0 :     if (row==-1) 
    2914             :       {
    2915           0 :         nRow=vb.nRow();
    2916           0 :         startRow=0;
    2917           0 :         endRow=nRow-1;
    2918             :       } 
    2919             :     else 
    2920             :       {
    2921           0 :         nRow=1;
    2922           0 :         startRow=row;
    2923           0 :         endRow=row;
    2924             :       }
    2925             :     //    
    2926             :     // Get the uvws in a form that Fortran can use and do that
    2927             :     // necessary phase rotation. On a Pentium Pro 200 MHz when null,
    2928             :     // this step takes about 50us per uvw point. This is just barely
    2929             :     // noticeable for Stokes I continuum and irrelevant for other
    2930             :     // cases.
    2931             :     //
    2932           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    2933           0 :     uvw=0.0;
    2934           0 :     Vector<Double> dphase(vb.uvw().nelements());
    2935           0 :     dphase=0.0;
    2936             :     //NEGATING to correct for an image inversion problem
    2937           0 :     for (Int i=startRow;i<=endRow;i++) 
    2938             :       {
    2939           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    2940           0 :         uvw(2,i)=vb.uvw()(i)(2);
    2941             :       }
    2942             :     
    2943           0 :     rotateUVW(uvw, dphase, vb);
    2944           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    2945             :     
    2946             :     // This is the convention for dphase
    2947           0 :     dphase*=-1.0;
    2948             :     
    2949           0 :     Cube<Int> flags(vb.flagCube().shape());
    2950           0 :     flags=0;
    2951           0 :     flags(vb.flagCube())=true;
    2952             :     
    2953           0 :     Vector<Int> rowFlags(vb.nRow());
    2954           0 :     rowFlags=0;
    2955           0 :     rowFlags(vb.flagRow())=true;
    2956           0 :     if(!usezero_p) 
    2957           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2958           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    2959             :     //Check if ms has changed then cache new spw and chan selection
    2960           0 :     if(vb.newMS())
    2961           0 :       matchAllSpwChans(vb);  
    2962             :     
    2963             :     //Here we redo the match or use previous match
    2964             :     
    2965             :     //Channel matching for the actual spectral window of buffer
    2966           0 :     if(doConversion_p[vb.spectralWindow()])
    2967           0 :       matchChannel(vb.spectralWindow(), vb);
    2968             :     else
    2969             :       {
    2970           0 :         chanMap.resize();
    2971           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    2972             :       }
    2973             :     
    2974           0 :     if(isTiled) 
    2975             :       {// Tiled Version
    2976           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    2977           0 :         Vector<Double> uvLambda(2);
    2978           0 :         Vector<Int> centerLoc2D(2);
    2979           0 :         centerLoc2D=0;
    2980             :         //
    2981             :         // Loop over all rows
    2982             :         //
    2983           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    2984             :           {
    2985             :             // Calculate uvw for this row at the center frequency
    2986           0 :             uvLambda(0)=uvw(0,rownr)*invLambdaC;
    2987           0 :             uvLambda(1)=uvw(1,rownr)*invLambdaC;
    2988           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    2989             :             //
    2990             :             // Is this point on the grid?
    2991             :             //
    2992           0 :             if(gridder->onGrid(centerLoc2D)) 
    2993             :               {
    2994             :                 // Get the tile
    2995           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, false);
    2996           0 :                 Int aNx=dataPtr->shape()(0);
    2997           0 :                 Int aNy=dataPtr->shape()(1);
    2998             :                 //
    2999             :                 // Now use FORTRAN to do the gridding. Remember to 
    3000             :                 // ensure that the shape and offsets of the tile are 
    3001             :                 // accounted for.
    3002             :                 //
    3003           0 :                 Vector<Double> actualOffset(3);
    3004           0 :                 for (Int i=0;i<2;i++) actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    3005             :                 
    3006           0 :                 actualOffset(2)=uvOffset(2);
    3007           0 :                 IPosition s(flags.shape());
    3008             :                 //
    3009             :                 // Now pass all the information down to a FORTRAN routine to
    3010             :                 // do the work
    3011             :                 //
    3012           0 :                 Int Conj=0,doPSF;
    3013           0 :                 Int ScanNo=0,doGrad=0;
    3014           0 :                 Double area=1.0;
    3015             :                 
    3016           0 :                 Int tmpPAI=PAIndex+1;
    3017           0 :                 if (dopsf) doPSF=1; else doPSF=0;
    3018           0 :                 runFortranPut(uvw,dphase,*datStorage,s,Conj,flags,rowFlags,
    3019             :                               *imagingweight,rownr,actualOffset,
    3020           0 :                               *dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    3021           0 :                               l_offsets,m_offsets,sumWeight,area,doGrad,doPSF,tmpPAI);
    3022             :               }
    3023             :           }
    3024             :       }
    3025             :     else 
    3026             :       {//Non-tiled version
    3027           0 :         IPosition s(flags.shape());
    3028             :         
    3029           0 :         Int Conj=0,doPSF=0;
    3030           0 :         Int ScanNo=0,doGrad=0;Double area=1.0;
    3031             :         
    3032           0 :         if (dopsf) doPSF=1;
    3033             :         
    3034           0 :         Int tmpPAI=PAIndex+1;
    3035           0 :         runFortranPut(uvw,dphase,*datStorage,s,Conj,flags,rowFlags,
    3036             :                       *imagingweight,
    3037           0 :                       row,uvOffset,
    3038           0 :                       griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3039           0 :                       l_offsets,m_offsets,sumWeight,area,doGrad,doPSF,tmpPAI);
    3040             :       }
    3041             :     
    3042           0 :     data->freeStorage(datStorage, isCopy);
    3043           0 :   }
    3044             :   //
    3045             :   //----------------------------------------------------------------------
    3046             :   //
    3047           0 :   void nPBWProjectFT::initVisBuffer(VisBuffer& vb, Type whichVBColumn)
    3048             :   {
    3049           0 :     if (whichVBColumn      == FTMachine::MODEL)    vb.modelVisCube()=Complex(0.0,0.0);
    3050           0 :     else if (whichVBColumn == FTMachine::OBSERVED) vb.visCube()=Complex(0.0,0.0);
    3051           0 :   }
    3052             :   //
    3053             :   //----------------------------------------------------------------------
    3054             :   //
    3055           0 :   void nPBWProjectFT::initVisBuffer(VisBuffer& vb, Type whichVBColumn, Int row)
    3056             :   {
    3057           0 :     if (whichVBColumn == FTMachine::MODEL)
    3058           0 :       vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
    3059           0 :     else if (whichVBColumn == FTMachine::OBSERVED)
    3060           0 :       vb.visCube().xyPlane(row)=Complex(0.0,0.0);
    3061           0 :   }
    3062             :   //
    3063             :   //---------------------------------------------------------------
    3064             :   //
    3065             :   // Predict the coherences as well as their derivatives w.r.t. the
    3066             :   // pointing offsets.
    3067             :   //
    3068           0 :   void nPBWProjectFT::nget(VisBuffer& vb,
    3069             :                           // These offsets should be appropriate for the VB
    3070             :                           Array<Float>& l_off, Array<Float>& m_off,
    3071             :                           Cube<Complex>& Mout,
    3072             :                           Cube<Complex>& dMout1,
    3073             :                           Cube<Complex>& dMout2,
    3074             :                           Int Conj, Int doGrad)
    3075             :   {
    3076             :     Int startRow, endRow, nRow;
    3077           0 :     nRow=vb.nRow();
    3078           0 :     startRow=0;
    3079           0 :     endRow=nRow-1;
    3080             : 
    3081           0 :     Mout = dMout1 = dMout2 = Complex(0,0);
    3082             : 
    3083           0 :     findConvFunction(*image, vb);
    3084           0 :     Int NAnt=0;
    3085           0 :     if (bandID_p == -1) bandID_p=getVisParams(vb);
    3086           0 :     if (doPointing)   
    3087           0 :       NAnt = findPointingOffsets(vb,l_offsets,m_offsets,false);
    3088             : 
    3089           0 :     l_offsets=l_off;
    3090           0 :     m_offsets=m_off;
    3091           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    3092           0 :     uvw=0.0;
    3093           0 :     Vector<Double> dphase(vb.uvw().nelements());
    3094           0 :     dphase=0.0;
    3095             :     //NEGATING to correct for an image inversion problem
    3096           0 :     for (Int i=startRow;i<=endRow;i++) 
    3097             :       {
    3098           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    3099           0 :         uvw(2,i)=vb.uvw()(i)(2);
    3100             :       }
    3101             :     
    3102           0 :     rotateUVW(uvw, dphase, vb);
    3103           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    3104             :     
    3105             :     // This is the convention for dphase
    3106           0 :     dphase*=-1.0;
    3107             : 
    3108           0 :     Cube<Int> flags(vb.flagCube().shape());
    3109           0 :     flags=0;
    3110           0 :     flags(vb.flagCube())=true;
    3111             :     
    3112             :     //Check if ms has changed then cache new spw and chan selection
    3113           0 :     if(vb.newMS())
    3114           0 :       matchAllSpwChans(vb);
    3115             :     
    3116             :     //Here we redo the match or use previous match
    3117             :     //
    3118             :     //Channel matching for the actual spectral window of buffer
    3119             :     //
    3120           0 :     if(doConversion_p[vb.spectralWindow()])
    3121           0 :       matchChannel(vb.spectralWindow(), vb);
    3122             :     else
    3123             :       {
    3124           0 :         chanMap.resize();
    3125           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    3126             :       }
    3127             :     
    3128           0 :     Vector<Int> rowFlags(vb.nRow());
    3129           0 :     rowFlags=0;
    3130           0 :     rowFlags(vb.flagRow())=true;
    3131           0 :     if(!usezero_p) 
    3132           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3133           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    3134             :     
    3135           0 :     IPosition s,gradS;
    3136           0 :     Cube<Complex> visdata,gradVisAzData,gradVisElData;
    3137             :     //
    3138             :     // visdata now references the Mout data structure rather than to the internal VB storeage.
    3139             :     //
    3140           0 :     visdata.reference(Mout);
    3141             : 
    3142           0 :     if (doGrad)
    3143             :       {
    3144             :         // The following should reference some slice of dMout?
    3145           0 :         gradVisAzData.reference(dMout1);
    3146           0 :         gradVisElData.reference(dMout2);
    3147             :       }
    3148             :     //
    3149             :     // Begin the actual de-gridding.
    3150             :     //
    3151           0 :     if(isTiled) 
    3152             :       {
    3153           0 :         logIO() << "nPBWProjectFT::nget(): The sky model is tiled" << LogIO::NORMAL << LogIO::POST;
    3154           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    3155           0 :         Vector<Double> uvLambda(2);
    3156           0 :         Vector<Int> centerLoc2D(2);
    3157           0 :         centerLoc2D=0;
    3158             :         
    3159             :         // Loop over all rows
    3160           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3161             :           {
    3162             :             
    3163             :             // Calculate uvw for this row at the center frequency
    3164           0 :             uvLambda(0)=uvw(0, rownr)*invLambdaC;
    3165           0 :             uvLambda(1)=uvw(1, rownr)*invLambdaC;
    3166           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    3167             :             
    3168             :             // Is this point on the grid?
    3169           0 :             if(gridder->onGrid(centerLoc2D)) 
    3170             :               {
    3171             :                 
    3172             :                 // Get the tile
    3173           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    3174           0 :                 gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    3175           0 :                 Int aNx=dataPtr->shape()(0);
    3176           0 :                 Int aNy=dataPtr->shape()(1);
    3177             :                 
    3178             :                 // Now use FORTRAN to do the gridding. Remember to 
    3179             :                 // ensure that the shape and offsets of the tile are 
    3180             :                 // accounted for.
    3181             :                 
    3182           0 :                 Vector<Double> actualOffset(3);
    3183           0 :                 for (Int i=0;i<2;i++) 
    3184           0 :                   actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    3185             :                 
    3186           0 :                 actualOffset(2)=uvOffset(2);
    3187           0 :                 IPosition s(vb.modelVisCube().shape());
    3188             :                 
    3189           0 :                 Int ScanNo=0, tmpPAI;
    3190           0 :                 Double area=1.0;
    3191           0 :                 tmpPAI = PAIndex+1;
    3192           0 :                 runFortranGetGrad(uvw,dphase,visdata,s,
    3193             :                                   gradVisAzData,gradVisElData,
    3194             :                                   Conj,flags,rowFlags,rownr,
    3195           0 :                                   actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    3196           0 :                                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    3197             :               }
    3198             :           }
    3199             :       }
    3200             :     else 
    3201             :       {
    3202           0 :         IPosition s(vb.modelVisCube().shape());
    3203           0 :         Int ScanNo=0, tmpPAI, trow=-1;
    3204           0 :         Double area=1.0;
    3205           0 :         tmpPAI = PAIndex+1;
    3206           0 :         runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    3207             :                           gradVisAzData, gradVisElData,
    3208             :                           Conj,flags,rowFlags,trow,
    3209           0 :                           uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3210           0 :                           l_offsets,m_offsets,area,doGrad,tmpPAI);
    3211             :       }
    3212             :     
    3213           0 :   }
    3214           0 :   void nPBWProjectFT::get(VisBuffer& vb,       
    3215             :                          VisBuffer& gradVBAz,
    3216             :                          VisBuffer& gradVBEl,
    3217             :                          Cube<Float>& pointingOffsets,
    3218             :                          Int row,  // default row=-1 
    3219             :                          Type whichVBColumn, // default whichVBColumn = FTMachine::MODEL
    3220             :                          Type whichGradVBColumn,// default whichGradVBColumn = FTMachine::MODEL
    3221             :                          Int Conj, Int doGrad) // default Conj=0, doGrad=1
    3222             :   {
    3223             :     // If row is -1 then we pass through all rows
    3224             :     Int startRow, endRow, nRow;
    3225           0 :     if (row==-1) 
    3226             :       {
    3227           0 :         nRow=vb.nRow();
    3228           0 :         startRow=0;
    3229           0 :         endRow=nRow-1;
    3230           0 :         initVisBuffer(vb,whichVBColumn);
    3231           0 :         if (doGrad)
    3232             :           {
    3233           0 :             initVisBuffer(gradVBAz, whichGradVBColumn);
    3234           0 :             initVisBuffer(gradVBEl, whichGradVBColumn);
    3235             :           }
    3236             :       }
    3237             :     else 
    3238             :       {
    3239           0 :         nRow=1;
    3240           0 :         startRow=row;
    3241           0 :         endRow=row;
    3242           0 :         initVisBuffer(vb,whichVBColumn,row);
    3243           0 :         if (doGrad)
    3244             :           {
    3245           0 :             initVisBuffer(gradVBAz, whichGradVBColumn,row);
    3246           0 :             initVisBuffer(gradVBEl, whichGradVBColumn,row);
    3247             :           }
    3248             :       }
    3249             :     
    3250           0 :     findConvFunction(*image, vb);
    3251             : 
    3252           0 :     if (bandID_p == -1) bandID_p=getVisParams(vb);
    3253           0 :     Int NAnt=0;
    3254           0 :     if (doPointing)   
    3255           0 :       NAnt = findPointingOffsets(vb,pointingOffsets,l_offsets,m_offsets,false);
    3256             : 
    3257           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    3258           0 :     uvw=0.0;
    3259           0 :     Vector<Double> dphase(vb.uvw().nelements());
    3260           0 :     dphase=0.0;
    3261             :     //NEGATING to correct for an image inversion problem
    3262           0 :     for (Int i=startRow;i<=endRow;i++) 
    3263             :       {
    3264           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    3265           0 :         uvw(2,i)=vb.uvw()(i)(2);
    3266             :       }
    3267             :     
    3268           0 :     rotateUVW(uvw, dphase, vb);
    3269           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    3270             :     
    3271             :     // This is the convention for dphase
    3272           0 :     dphase*=-1.0;
    3273             :     
    3274             :     
    3275           0 :     Cube<Int> flags(vb.flagCube().shape());
    3276           0 :     flags=0;
    3277           0 :     flags(vb.flagCube())=true;
    3278             :     //    
    3279             :     //Check if ms has changed then cache new spw and chan selection
    3280             :     //
    3281           0 :     if(vb.newMS()) matchAllSpwChans(vb);
    3282             :     
    3283             :     //Here we redo the match or use previous match
    3284             :     //
    3285             :     //Channel matching for the actual spectral window of buffer
    3286             :     //
    3287           0 :     if(doConversion_p[vb.spectralWindow()])
    3288           0 :       matchChannel(vb.spectralWindow(), vb);
    3289             :     else
    3290             :       {
    3291           0 :         chanMap.resize();
    3292           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    3293             :       }
    3294             :     
    3295           0 :     Vector<Int> rowFlags(vb.nRow());
    3296           0 :     rowFlags=0;
    3297           0 :     rowFlags(vb.flagRow())=true;
    3298           0 :     if(!usezero_p) 
    3299           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3300           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    3301             :         
    3302           0 :     for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3303           0 :       if (vb.antenna1()(rownr) != vb.antenna2()(rownr)) 
    3304           0 :         rowFlags(rownr) = (vb.flagRow()(rownr)==true);
    3305             :     
    3306           0 :     IPosition s,gradS;
    3307           0 :     Cube<Complex> visdata,gradVisAzData,gradVisElData;
    3308           0 :     if (whichVBColumn == FTMachine::MODEL) 
    3309             :       {
    3310           0 :         s = vb.modelVisCube().shape();
    3311           0 :         visdata.reference(vb.modelVisCube());
    3312             :       }
    3313           0 :     else if (whichVBColumn == FTMachine::OBSERVED)  
    3314             :       {
    3315           0 :         s = vb.visCube().shape();
    3316           0 :         visdata.reference(vb.visCube());
    3317             :       }
    3318             :     
    3319           0 :     if (doGrad)
    3320             :       {
    3321           0 :         if (whichGradVBColumn == FTMachine::MODEL) 
    3322             :           {
    3323             :             //      gradS = gradVBAz.modelVisCube().shape();
    3324           0 :             gradVisAzData.reference(gradVBAz.modelVisCube());
    3325           0 :             gradVisElData.reference(gradVBEl.modelVisCube());
    3326             :           }
    3327           0 :         else if (whichGradVBColumn == FTMachine::OBSERVED)  
    3328             :           {
    3329             :             //      gradS = gradVBAz.visCube().shape();
    3330           0 :             gradVisAzData.reference(gradVBAz.visCube());
    3331           0 :             gradVisElData.reference(gradVBEl.visCube());
    3332             :           }
    3333             :       }
    3334             :     
    3335           0 :     if(isTiled) 
    3336             :       {
    3337           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    3338           0 :         Vector<Double> uvLambda(2);
    3339           0 :         Vector<Int> centerLoc2D(2);
    3340           0 :         centerLoc2D=0;
    3341             :         
    3342             :         // Loop over all rows
    3343           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3344             :           {
    3345             :             
    3346             :             // Calculate uvw for this row at the center frequency
    3347           0 :             uvLambda(0)=uvw(0, rownr)*invLambdaC;
    3348           0 :             uvLambda(1)=uvw(1, rownr)*invLambdaC;
    3349           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    3350             :             
    3351             :             // Is this point on the grid?
    3352           0 :             if(gridder->onGrid(centerLoc2D)) 
    3353             :               {
    3354             :                 
    3355             :                 // Get the tile
    3356           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    3357           0 :                 gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    3358           0 :                 Int aNx=dataPtr->shape()(0);
    3359           0 :                 Int aNy=dataPtr->shape()(1);
    3360             :                 
    3361             :                 // Now use FORTRAN to do the gridding. Remember to 
    3362             :                 // ensure that the shape and offsets of the tile are 
    3363             :                 // accounted for.
    3364             :                 
    3365           0 :                 Vector<Double> actualOffset(3);
    3366           0 :                 for (Int i=0;i<2;i++) 
    3367           0 :                   actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    3368             :                 
    3369           0 :                 actualOffset(2)=uvOffset(2);
    3370           0 :                 IPosition s(vb.modelVisCube().shape());
    3371             :                 
    3372           0 :                 Int ScanNo=0, tmpPAI;
    3373           0 :                 Double area=1.0;
    3374           0 :                 tmpPAI = PAIndex+1;
    3375           0 :                 runFortranGetGrad(uvw,dphase,visdata,s,
    3376             :                                   gradVisAzData,gradVisElData,
    3377             :                                   Conj,flags,rowFlags,rownr,
    3378           0 :                                   actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    3379           0 :                                   l_offsets,m_offsets,area,doGrad,tmpPAI);
    3380             :               }
    3381             :           }
    3382             :       }
    3383             :     else 
    3384             :       {
    3385             :         
    3386           0 :         IPosition s(vb.modelVisCube().shape());
    3387           0 :         Int ScanNo=0, tmpPAI;
    3388           0 :         Double area=1.0;
    3389             : 
    3390           0 :         tmpPAI = PAIndex+1;
    3391             : 
    3392           0 :         runFortranGetGrad(uvw,dphase,visdata/*vb.modelVisCube()*/,s,
    3393             :                           gradVisAzData, gradVisElData,
    3394             :                           Conj,flags,rowFlags,row,
    3395           0 :                           uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3396           0 :                           l_offsets,m_offsets,area,doGrad,tmpPAI);
    3397             : //      runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,row,
    3398             : //                    uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3399             : //                    l_offsets,m_offsets,area,doGrad,tmpPAI);
    3400             :       }
    3401           0 :   }
    3402             :   //
    3403             :   //---------------------------------------------------------------
    3404             :   //
    3405           0 :   void nPBWProjectFT::get(VisBuffer& vb, Int row)
    3406             :   {
    3407             :     // If row is -1 then we pass through all rows
    3408             :     Int startRow, endRow, nRow;
    3409           0 :     if (row==-1) 
    3410             :       {
    3411           0 :         nRow=vb.nRow();
    3412           0 :         startRow=0;
    3413           0 :         endRow=nRow-1;
    3414           0 :         vb.modelVisCube()=Complex(0.0,0.0);
    3415             :       }
    3416             :     else 
    3417             :       {
    3418           0 :         nRow=1;
    3419           0 :         startRow=row;
    3420           0 :         endRow=row;
    3421           0 :         vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
    3422             :       }
    3423             :     
    3424           0 :     findConvFunction(*image, vb);
    3425             :     
    3426           0 :     if (bandID_p == -1) bandID_p=getVisParams(vb);
    3427           0 :     Int NAnt=0;
    3428           0 :     if (doPointing)   NAnt = findPointingOffsets(vb,l_offsets,m_offsets,true);
    3429             :     
    3430             :     // Get the uvws in a form that Fortran can use
    3431           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    3432           0 :     uvw=0.0;
    3433           0 :     Vector<Double> dphase(vb.uvw().nelements());
    3434           0 :     dphase=0.0;
    3435             :     //NEGATING to correct for an image inversion problem
    3436           0 :     for (Int i=startRow;i<=endRow;i++) 
    3437             :       {
    3438           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    3439           0 :         uvw(2,i)=vb.uvw()(i)(2);
    3440             :       }
    3441             :     
    3442           0 :     rotateUVW(uvw, dphase, vb);
    3443           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    3444             :     
    3445             :     // This is the convention for dphase
    3446           0 :     dphase*=-1.0;
    3447             :     
    3448             :     
    3449           0 :     Cube<Int> flags(vb.flagCube().shape());
    3450           0 :     flags=0;
    3451           0 :     flags(vb.flagCube())=true;
    3452             :     
    3453             :     //Check if ms has changed then cache new spw and chan selection
    3454           0 :     if(vb.newMS())
    3455           0 :       matchAllSpwChans(vb);
    3456             :     
    3457             :     //Here we redo the match or use previous match
    3458             :     //
    3459             :     //Channel matching for the actual spectral window of buffer
    3460             :     //
    3461           0 :     if(doConversion_p[vb.spectralWindow()])
    3462           0 :       matchChannel(vb.spectralWindow(), vb);
    3463             :     else
    3464             :       {
    3465           0 :         chanMap.resize();
    3466           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    3467             :       }
    3468             :     
    3469           0 :     Vector<Int> rowFlags(vb.nRow());
    3470           0 :     rowFlags=0;
    3471           0 :     rowFlags(vb.flagRow())=true;
    3472             :     
    3473           0 :     if(!usezero_p) 
    3474           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3475           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    3476             :     
    3477           0 :     if(isTiled) 
    3478             :       {
    3479             :         
    3480           0 :         Double invLambdaC=vb.frequency()(0)/C::c;
    3481           0 :         Vector<Double> uvLambda(2);
    3482           0 :         Vector<Int> centerLoc2D(2);
    3483           0 :         centerLoc2D=0;
    3484             :         
    3485             :         // Loop over all rows
    3486           0 :         for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3487             :           {
    3488             :             
    3489             :             // Calculate uvw for this row at the center frequency
    3490           0 :             uvLambda(0)=uvw(0, rownr)*invLambdaC;
    3491           0 :             uvLambda(1)=uvw(1, rownr)*invLambdaC;
    3492           0 :             centerLoc2D=gridder->location(centerLoc2D, uvLambda);
    3493             :             
    3494             :             // Is this point on the grid?
    3495           0 :             if(gridder->onGrid(centerLoc2D)) 
    3496             :               {
    3497             :                 
    3498             :                 // Get the tile
    3499           0 :                 Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
    3500           0 :                 gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
    3501           0 :                 Int aNx=dataPtr->shape()(0);
    3502           0 :                 Int aNy=dataPtr->shape()(1);
    3503             :                 
    3504             :                 // Now use FORTRAN to do the gridding. Remember to 
    3505             :                 // ensure that the shape and offsets of the tile are 
    3506             :                 // accounted for.
    3507             :                 
    3508           0 :                 Vector<Double> actualOffset(3);
    3509           0 :                 for (Int i=0;i<2;i++) 
    3510           0 :                   actualOffset(i)=uvOffset(i)-Double(offsetLoc(i));
    3511             :                 
    3512           0 :                 actualOffset(2)=uvOffset(2);
    3513           0 :                 IPosition s(vb.modelVisCube().shape());
    3514             :                 
    3515           0 :                 Int Conj=0,doGrad=0,ScanNo=0;
    3516           0 :                 Double area=1.0;
    3517             :                 
    3518           0 :                 runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,rownr,
    3519           0 :                               actualOffset,dataPtr,aNx,aNy,npol,nchan,vb,NAnt,ScanNo,sigma,
    3520           0 :                               l_offsets,m_offsets,area,doGrad,PAIndex+1);
    3521             :               }
    3522             :           }
    3523             :       }
    3524             :     else 
    3525             :       {
    3526             :         
    3527           0 :         IPosition s(vb.modelVisCube().shape());
    3528           0 :         Int Conj=0,doGrad=0,ScanNo=0;
    3529           0 :         Double area=1.0;
    3530             :         
    3531           0 :         runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,row,
    3532           0 :                       uvOffset,&griddedData,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3533           0 :                       l_offsets,m_offsets,area,doGrad,PAIndex+1);
    3534             :         /*
    3535             :         static int junk=0;
    3536             :         if (junk==4)
    3537             :           {
    3538             :             cout << "Time = " << vb.time()/1e9 << endl;
    3539             :           for(Int i=0;i<vb.modelVisCube().shape()(2);i++)
    3540             :             cout << "PBWP: Residual: " << i 
    3541             :                  << " " << vb.modelVisCube()(0,0,i) 
    3542             :                  << " " << vb.modelVisCube()(3,0,i)
    3543             :                  << " " << vb.visCube()(0,0,i) 
    3544             :                  << " " << vb.visCube()(3,0,i)
    3545             :                  << " " << vb.flag()(0,i) 
    3546             :                  << " " << vb.antenna1()(i)<< "-" << vb.antenna2()(i) 
    3547             :                  << " " << vb.flagRow()(i) 
    3548             :                  << " " << vb.flagCube()(0,0,i) 
    3549             :                  << " " << vb.flagCube()(3,0,i) 
    3550             :                  << endl;
    3551             :           }
    3552             :         junk++;
    3553             :         */
    3554             :       }
    3555           0 :   }
    3556             :   //
    3557             :   //---------------------------------------------------------------
    3558             :   //
    3559           0 :   void nPBWProjectFT::get(VisBuffer& vb, Cube<Complex>& modelVis, 
    3560             :                           Array<Complex>& griddedVis, Vector<Double>& /*scale*/,
    3561             :                          Int row)
    3562             :   {
    3563           0 :     Int nX=griddedVis.shape()(0);
    3564           0 :     Int nY=griddedVis.shape()(1);
    3565           0 :     Vector<Double> offset(2);
    3566           0 :     offset(0)=Double(nX)/2.0;
    3567           0 :     offset(1)=Double(nY)/2.0;
    3568             :     // If row is -1 then we pass through all rows
    3569             :     Int startRow, endRow, nRow;
    3570           0 :     if (row==-1) 
    3571             :       {
    3572           0 :         nRow=vb.nRow();
    3573           0 :         startRow=0;
    3574           0 :         endRow=nRow-1;
    3575           0 :         modelVis.set(Complex(0.0,0.0));
    3576             :       } 
    3577             :     else 
    3578             :       {
    3579           0 :         nRow=1;
    3580           0 :         startRow=row;
    3581           0 :         endRow=row;
    3582           0 :         modelVis.xyPlane(row)=Complex(0.0,0.0);
    3583             :       }
    3584             :     
    3585           0 :     Int NAnt=0;
    3586             :     
    3587           0 :     if (doPointing) 
    3588           0 :       NAnt = findPointingOffsets(vb,l_offsets, m_offsets,true);
    3589             :     
    3590             :     
    3591             :     //  
    3592             :     // Get the uvws in a form that Fortran can use
    3593             :     //
    3594           0 :     Matrix<Double> uvw(3, vb.uvw().nelements());
    3595           0 :     uvw=0.0;
    3596           0 :     Vector<Double> dphase(vb.uvw().nelements());
    3597           0 :     dphase=0.0;
    3598             :     //
    3599             :     //NEGATING to correct for an image inversion problem
    3600             :     //
    3601           0 :     for (Int i=startRow;i<=endRow;i++) 
    3602             :       {
    3603           0 :         for (Int idim=0;idim<2;idim++) uvw(idim,i)=-vb.uvw()(i)(idim);
    3604           0 :         uvw(2,i)=vb.uvw()(i)(2);
    3605             :       }
    3606             :     
    3607           0 :     rotateUVW(uvw, dphase, vb);
    3608           0 :     refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    3609             :     
    3610             :     // This is the convention for dphase
    3611           0 :     dphase*=-1.0;
    3612             :     
    3613           0 :     Cube<Int> flags(vb.flagCube().shape());
    3614           0 :     flags=0;
    3615           0 :     flags(vb.flagCube())=true;
    3616             :     
    3617             :     //Check if ms has changed then cache new spw and chan selection
    3618           0 :     if(vb.newMS())
    3619           0 :       matchAllSpwChans(vb);
    3620             :     
    3621             :     //Channel matching for the actual spectral window of buffer
    3622           0 :     if(doConversion_p[vb.spectralWindow()])
    3623           0 :       matchChannel(vb.spectralWindow(), vb);
    3624             :     else
    3625             :       {
    3626           0 :         chanMap.resize();
    3627           0 :         chanMap=multiChanMap_p[vb.spectralWindow()];
    3628             :       }
    3629             :     
    3630           0 :     Vector<Int> rowFlags(vb.nRow());
    3631           0 :     rowFlags=0;
    3632           0 :     rowFlags(vb.flagRow())=true;
    3633           0 :     if(!usezero_p) 
    3634           0 :       for (Int rownr=startRow; rownr<=endRow; rownr++) 
    3635           0 :         if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    3636             :     
    3637           0 :     IPosition s(modelVis.shape());
    3638           0 :     Int Conj=0,doGrad=0,ScanNo=0;
    3639           0 :     Double area=1.0;
    3640             :     
    3641           0 :     runFortranGet(uvw,dphase,vb.modelVisCube(),s,Conj,flags,rowFlags,row,
    3642           0 :                   offset,&griddedVis,nx,ny,npol,nchan,vb,NAnt,ScanNo,sigma,
    3643           0 :                   l_offsets,m_offsets,area,doGrad,PAIndex+1);
    3644           0 :   }
    3645             :   //
    3646             :   //---------------------------------------------------------------
    3647             :   //
    3648             :   // Finalize the FFT to the Sky. Here we actually do the FFT and
    3649             :   // return the resulting image
    3650           0 :   ImageInterface<Complex>& nPBWProjectFT::getImage(Matrix<Float>& weights,
    3651             :                                                   Bool normalize) 
    3652             :   {
    3653             :     //AlwaysAssert(lattice, AipsError);
    3654           0 :     AlwaysAssert(image, AipsError);
    3655             :     
    3656           0 :     logIO() << "#########getimage########" << LogIO::DEBUGGING << LogIO::POST;
    3657             :     
    3658           0 :     logIO() << LogOrigin("nPBWProjectFT", "getImage") << LogIO::NORMAL;
    3659             :     
    3660           0 :     weights.resize(sumWeight.shape());
    3661             :     
    3662           0 :     convertArray(weights, sumWeight);
    3663             :     //  
    3664             :     // If the weights are all zero then we cannot normalize otherwise
    3665             :     // we don't care.
    3666             :     //
    3667           0 :     if(max(weights)==0.0) 
    3668             :       {
    3669           0 :         if(normalize) logIO() << LogIO::SEVERE
    3670             :                               << "No useful data in nPBWProjectFT: weights all zero"
    3671           0 :                               << LogIO::POST;
    3672             :         else logIO() << LogIO::WARN << "No useful data in nPBWProjectFT: weights all zero"
    3673           0 :                      << LogIO::POST;
    3674             :       }
    3675             :     else
    3676             :       {
    3677           0 :         const IPosition latticeShape = lattice->shape();
    3678             :         
    3679             :         logIO() << LogIO::DEBUGGING
    3680           0 :                 << "Starting FFT and scaling of image" << LogIO::POST;
    3681             :         //    
    3682             :         // x and y transforms (lattice has the gridded vis.  Make the
    3683             :         // dirty images)
    3684             :         //
    3685           0 :         LatticeFFT::cfft2d(*lattice,false);
    3686             :         
    3687             :         //
    3688             :         // Apply the gridding correction
    3689             :         //    
    3690             :         {
    3691           0 :           normalizeAvgPB();
    3692           0 :           Int inx = lattice->shape()(0);
    3693           0 :           Int iny = lattice->shape()(1);
    3694           0 :           Vector<Complex> correction(inx);
    3695             :           
    3696           0 :           Vector<Float> sincConv(nx);
    3697           0 :           Float centerX=nx/2;
    3698           0 :           for (Int ix=0;ix<nx;ix++) 
    3699             :             {
    3700           0 :               Float x=C::pi*Float(ix-centerX)/(Float(nx)*Float(convSampling));
    3701           0 :               if(ix==centerX) sincConv(ix)=1.0;
    3702           0 :               else          sincConv(ix)=sin(x)/x;
    3703             :             }
    3704             :           
    3705           0 :           IPosition cursorShape(4, inx, 1, 1, 1);
    3706           0 :           IPosition axisPath(4, 0, 1, 2, 3);
    3707           0 :           LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    3708           0 :           LatticeIterator<Complex> lix(*lattice, lsx);
    3709             :           
    3710           0 :           LatticeStepper lavgpb(avgPB.shape(),cursorShape,axisPath);
    3711           0 :           LatticeIterator<Float> liavgpb(avgPB, lavgpb);
    3712             :           
    3713           0 :           for(lix.reset(),liavgpb.reset();
    3714           0 :               !lix.atEnd();
    3715           0 :               lix++,liavgpb++) 
    3716             :             {
    3717           0 :               Int pol=lix.position()(2);
    3718           0 :               Int chan=lix.position()(3);
    3719             :               
    3720           0 :               if(weights(pol, chan)>0.0) 
    3721             :                 {
    3722             :                   /*
    3723             :                   Int iy=lix.position()(1);
    3724             :                   gridder->correctX1D(correction,iy);
    3725             :                   
    3726             :                   Vector<Float> PBCorrection(liavgpb.rwVectorCursor().shape()),
    3727             :                     avgPBVec(liavgpb.rwVectorCursor().shape());
    3728             :                   
    3729             :                   PBCorrection = liavgpb.rwVectorCursor();
    3730             :                   avgPBVec = liavgpb.rwVectorCursor();
    3731             : 
    3732             :                   for(int i=0;i<PBCorrection.shape();i++)
    3733             :                     {
    3734             :                       //
    3735             :                       // This with the PS functions
    3736             :                       //
    3737             :                       // PBCorrection(i)=FUNC(avgPBVec(i))*sincConv(i)*sincConv(iy);
    3738             :                       // if ((abs(PBCorrection(i)*correction(i))) >= pbLimit_p)
    3739             :                       //        lix.rwVectorCursor()(i) /= PBCorrection(i)*correction(i);
    3740             :                       // else if (!makingPSF)
    3741             :                       //        lix.rwVectorCursor()(i) /= correction(i)*sincConv(i)*sincConv(iy);
    3742             :                       //
    3743             :                       // This without the PS functions
    3744             :                       //
    3745             :                       PBCorrection(i)=FUNC(avgPBVec(i))*sincConv(i)*sincConv(iy);
    3746             :                       if ((abs(PBCorrection(i))) >= pbLimit_p)
    3747             :                         lix.rwVectorCursor()(i) /= PBCorrection(i);
    3748             :                       else if (!makingPSF)
    3749             :                         lix.rwVectorCursor()(i) /= sincConv(i)*sincConv(iy);
    3750             :                     }
    3751             :                   */
    3752           0 :                   if(normalize) 
    3753             :                     {
    3754           0 :                       Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan));
    3755           0 :                       lix.rwCursor()*=rnorm;
    3756             :                     }
    3757             :                   else 
    3758             :                     {
    3759           0 :                       Complex rnorm(Float(inx)*Float(iny));
    3760           0 :                       lix.rwCursor()*=rnorm;
    3761             :                     }
    3762             :                 }
    3763             :               else 
    3764           0 :                 lix.woCursor()=0.0;
    3765             :             }
    3766             :         }
    3767             : 
    3768             : 
    3769           0 :         if(!isTiled) 
    3770             :           {
    3771             :             //
    3772             :             // Check the section from the image BEFORE converting to a lattice 
    3773             :             //
    3774           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    3775           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    3776           0 :             IPosition stride(4, 1);
    3777           0 :             IPosition trc(blc+image->shape()-stride);
    3778             :             //
    3779             :             // Do the copy
    3780             :             //
    3781           0 :             image->put(griddedData(blc, trc));
    3782           0 :             griddedData.resize(IPosition(1,0));
    3783             :           }
    3784             :       }
    3785             :     
    3786           0 :     return *image;
    3787             :   }
    3788             :   //
    3789             :   //---------------------------------------------------------------
    3790             :   //
    3791             :   // Get weight image
    3792           0 :   void nPBWProjectFT::getWeightImage(ImageInterface<Float>& weightImage,
    3793             :                                     Matrix<Float>& weights) 
    3794             :   {
    3795             :     
    3796           0 :     logIO() << LogOrigin("nPBWProjectFT", "getWeightImage") << LogIO::NORMAL;
    3797             :     
    3798           0 :     weights.resize(sumWeight.shape());
    3799           0 :     convertArray(weights,sumWeight);
    3800             :     
    3801           0 :     const IPosition latticeShape = weightImage.shape();
    3802             :     
    3803           0 :     Int nx=latticeShape(0);
    3804           0 :     Int ny=latticeShape(1);
    3805             :     
    3806           0 :     IPosition loc(2, 0);
    3807           0 :     IPosition cursorShape(4, nx, ny, 1, 1);
    3808           0 :     IPosition axisPath(4, 0, 1, 2, 3);
    3809           0 :     LatticeStepper lsx(latticeShape, cursorShape, axisPath);
    3810           0 :     LatticeIterator<Float> lix(weightImage, lsx);
    3811           0 :     LatticeIterator<Float> liy(avgPB,lsx);
    3812           0 :     for(lix.reset();!lix.atEnd();lix++) 
    3813             :       {
    3814             :         // UNUSED  Int pol=lix.position()(2);
    3815             :         // UNUSED  Int chan=lix.position()(3);
    3816             :         //      lix.rwCursor()=weights(pol,chan);
    3817           0 :         lix.rwCursor()=liy.rwCursor();
    3818             :       }
    3819           0 :   }
    3820             :   //
    3821             :   //---------------------------------------------------------------
    3822             :   //
    3823           0 : Bool nPBWProjectFT::toRecord(String&, //error,
    3824             :                              RecordInterface& outRec, Bool withImage, const String diskimage) 
    3825             : {    
    3826             :     // Save the current nPBWProjectFT object to an output state record
    3827           0 :     Bool retval = true;
    3828           0 :     Double cacheVal=(Double) cachesize;
    3829           0 :     outRec.define("cache", cacheVal);
    3830           0 :     outRec.define("tile", tilesize);
    3831             :     
    3832           0 :     Vector<Double> phaseValue(2);
    3833           0 :     String phaseUnit;
    3834           0 :     phaseValue=mTangent_p.getAngle().getValue();
    3835           0 :     phaseUnit= mTangent_p.getAngle().getUnit();
    3836           0 :     outRec.define("phasevalue", phaseValue);
    3837           0 :     outRec.define("phaseunit", phaseUnit);
    3838             :     
    3839           0 :     Vector<Double> dirValue(3);
    3840           0 :     String dirUnit;
    3841           0 :     dirValue=mLocation_p.get("m").getValue();
    3842           0 :     dirUnit=mLocation_p.get("m").getUnit();
    3843           0 :     outRec.define("dirvalue", dirValue);
    3844           0 :     outRec.define("dirunit", dirUnit);
    3845             :     
    3846           0 :     outRec.define("padding", padding_p);
    3847           0 :     outRec.define("maxdataval", maxAbsData);
    3848             :     
    3849           0 :     Vector<Int> center_loc(4), offset_loc(4);
    3850           0 :     for (Int k=0; k<4 ; k++)
    3851             :       {
    3852           0 :         center_loc(k)=centerLoc(k);
    3853           0 :         offset_loc(k)=offsetLoc(k);
    3854             :       }
    3855           0 :     outRec.define("centerloc", center_loc);
    3856           0 :     outRec.define("offsetloc", offset_loc);
    3857           0 :     outRec.define("sumofweights", sumWeight);
    3858           0 :     if(withImage && image ){
    3859           0 :       if(diskimage==""){ 
    3860           0 :         ImageInterface<Complex>& tempimage(*image);
    3861           0 :         Record imageContainer;
    3862           0 :         String error;
    3863           0 :         retval = (retval || tempimage.toRecord(error, imageContainer));
    3864           0 :         outRec.defineRecord("image", imageContainer);
    3865             :       }
    3866             :       else{
    3867           0 :         PagedImage<Complex> tempImage(image->shape(), image->coordinates(), diskimage);
    3868           0 :         tempImage.copyData(*image);
    3869           0 :         outRec.define("diskimage", diskimage);
    3870             :       }
    3871             :     }
    3872             :     
    3873           0 :     return retval;
    3874             :     
    3875             :   //
    3876             : }
    3877             :   //---------------------------------------------------------------
    3878             :   //
    3879           0 : Bool nPBWProjectFT::fromRecord(String&, //error,
    3880             :                                const RecordInterface& inRec)
    3881             : {
    3882           0 :     Bool retval = true;
    3883           0 :     imageCache=0; lattice=0; arrayLattice=0;
    3884             :     Double cacheVal;
    3885           0 :     inRec.get("cache", cacheVal);
    3886           0 :     cachesize=(Long) cacheVal;
    3887           0 :     inRec.get("tile", tilesize);
    3888             :     
    3889           0 :     Vector<Double> phaseValue(2);
    3890           0 :     inRec.get("phasevalue",phaseValue);
    3891           0 :     String phaseUnit;
    3892           0 :     inRec.get("phaseunit",phaseUnit);
    3893           0 :     Quantity val1(phaseValue(0), phaseUnit);
    3894           0 :     Quantity val2(phaseValue(1), phaseUnit); 
    3895           0 :     MDirection phasecenter(val1, val2);
    3896             :     
    3897           0 :     mTangent_p=phasecenter;
    3898             :     // This should be passed down too but the tangent plane is 
    3899             :     // expected to be specified in all meaningful cases.
    3900           0 :     tangentSpecified_p=true;  
    3901           0 :     Vector<Double> dirValue(3);
    3902           0 :     String dirUnit;
    3903           0 :     inRec.get("dirvalue", dirValue);
    3904           0 :     inRec.get("dirunit", dirUnit);
    3905           0 :     MVPosition dummyMVPos(dirValue(0), dirValue(1), dirValue(2));
    3906           0 :     MPosition mLocation(dummyMVPos, MPosition::ITRF);
    3907           0 :     mLocation_p=mLocation;
    3908             :     
    3909           0 :     inRec.get("padding", padding_p);
    3910           0 :     inRec.get("maxdataval", maxAbsData);
    3911             :     
    3912           0 :     Vector<Int> center_loc(4), offset_loc(4);
    3913           0 :     inRec.get("centerloc", center_loc);
    3914           0 :     inRec.get("offsetloc", offset_loc);
    3915           0 :     uInt ndim4 = 4;
    3916           0 :     centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2), 
    3917           0 :                         center_loc(3));
    3918           0 :     offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2), 
    3919           0 :                         offset_loc(3));
    3920           0 :     inRec.get("sumofweights", sumWeight);
    3921           0 :     if(inRec.isDefined("image"))
    3922             :       {
    3923           0 :         Record imageAsRec=inRec.asRecord("image");
    3924           0 :         if(!image) image= new TempImage<Complex>(); 
    3925             :         
    3926           0 :         String error;
    3927           0 :         retval = (retval || image->fromRecord(error, imageAsRec));    
    3928             :         
    3929             :         // Might be changing the shape of sumWeight
    3930           0 :         init(); 
    3931             :         
    3932           0 :         if(isTiled) 
    3933           0 :           lattice=CountedPtr<Lattice<Complex> > (image, false);
    3934             :         else 
    3935             :           {
    3936             :             //
    3937             :             // Make the grid the correct shape and turn it into an
    3938             :             // array lattice Check the section from the image BEFORE
    3939             :             // converting to a lattice
    3940             :             //
    3941           0 :             IPosition gridShape(4, nx, ny, npol, nchan);
    3942           0 :             griddedData.resize(gridShape);
    3943           0 :             griddedData=Complex(0.0);
    3944           0 :             IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
    3945           0 :                           (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    3946           0 :             IPosition start(4, 0);
    3947           0 :             IPosition stride(4, 1);
    3948           0 :             IPosition trc(blc+image->shape()-stride);
    3949           0 :             griddedData(blc, trc) = image->getSlice(start, image->shape());
    3950             :             
    3951           0 :             arrayLattice = new ArrayLattice<Complex>(griddedData);
    3952           0 :             lattice=arrayLattice;
    3953             :           }
    3954             :         
    3955           0 :         AlwaysAssert(image, AipsError);
    3956             :       }
    3957           0 :     else if(inRec.isDefined("diskimage")){
    3958           0 :         String diskim;
    3959           0 :         inRec.get("diskimage", diskim);
    3960           0 :         image=new PagedImage<Complex>(diskim);
    3961             :     }
    3962             :     
    3963             :     
    3964           0 :     return retval;
    3965             :   }
    3966             :   //
    3967             :   //---------------------------------------------------------------
    3968             :   //
    3969           0 :   void nPBWProjectFT::ok() 
    3970             :   {
    3971           0 :     AlwaysAssert(image, AipsError);
    3972           0 :   }
    3973             :   //----------------------------------------------------------------------
    3974             :   //
    3975             :   // Make a plain straightforward honest-to-god image. This returns a
    3976             :   // complex image, without conversion to Stokes. The polarization
    3977             :   // representation is that required for the visibilities.
    3978             :   //
    3979           0 :   void nPBWProjectFT::makeImage(FTMachine::Type type, 
    3980             :                                VisSet& vs,
    3981             :                                ImageInterface<Complex>& theImage,
    3982             :                                Matrix<Float>& weight) 
    3983             :   {
    3984           0 :     logIO() << LogOrigin("nPBWProjectFT", "makeImage") << LogIO::NORMAL;
    3985             :     
    3986           0 :     if(type==FTMachine::COVERAGE) 
    3987             :       logIO() << "Type COVERAGE not defined for Fourier transforms"
    3988           0 :               << LogIO::EXCEPTION;
    3989             :     
    3990             :     
    3991             :     // Initialize the gradients
    3992           0 :     ROVisIter& vi(vs.iter());
    3993             :     
    3994             :     // Loop over all visibilities and pixels
    3995           0 :     VisBuffer vb(vi);
    3996             :     
    3997             :     // Initialize put (i.e. transform to Sky) for this model
    3998           0 :     vi.origin();
    3999             :     
    4000           0 :     if(vb.polFrame()==MSIter::Linear) 
    4001           0 :       StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::LINEAR);
    4002             :     else 
    4003           0 :       StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::CIRCULAR);
    4004             :     
    4005           0 :     initializeToSky(theImage,weight,vb);
    4006             : 
    4007             :     //    
    4008             :     // Loop over the visibilities, putting VisBuffers
    4009             :     //
    4010           0 :     paChangeDetector.reset();
    4011             : 
    4012           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) 
    4013             :       {
    4014           0 :         for (vi.origin(); vi.more(); vi++) 
    4015             :           {
    4016           0 :             if (type==FTMachine::PSF) makingPSF=true;
    4017           0 :             findConvFunction(theImage,vb);
    4018             :             
    4019           0 :             switch(type) 
    4020             :               {
    4021           0 :               case FTMachine::RESIDUAL:
    4022           0 :                 vb.visCube()=vb.correctedVisCube();
    4023           0 :                 vb.visCube()-=vb.modelVisCube();
    4024           0 :                 put(vb, -1, false);
    4025           0 :                 break;
    4026           0 :               case FTMachine::MODEL:
    4027           0 :                 vb.visCube()=vb.modelVisCube();
    4028           0 :                 put(vb, -1, false);
    4029           0 :                 break;
    4030           0 :               case FTMachine::CORRECTED:
    4031           0 :                 vb.visCube()=vb.correctedVisCube();
    4032           0 :                 put(vb, -1, false);
    4033           0 :                 break;
    4034           0 :               case FTMachine::PSF:
    4035           0 :                 vb.visCube()=Complex(1.0,0.0);
    4036           0 :                 makingPSF = true;
    4037           0 :                 put(vb, -1, true);
    4038           0 :                 break;
    4039           0 :               case FTMachine::OBSERVED:
    4040             :               default:
    4041           0 :                 put(vb, -1, false);
    4042           0 :                 break;
    4043             :               }
    4044             :           }
    4045             :       }
    4046           0 :     finalizeToSky();
    4047             :     // Normalize by dividing out weights, etc.
    4048           0 :     getImage(weight, true);
    4049           0 :   }
    4050             :   
    4051           0 :   void nPBWProjectFT::setPAIncrement(const Quantity& paIncrement)
    4052             :   {
    4053           0 :     paChangeDetector.setTolerance(paIncrement);
    4054           0 :     rotateAperture_p = true;
    4055           0 :     if (paIncrement.getValue("rad") < 0)
    4056           0 :       rotateAperture_p = false;
    4057           0 :     logIO() << "Setting PA increment to " << paIncrement.getValue("deg") << " deg" << endl;
    4058           0 :   }
    4059             : 
    4060           0 :   Bool nPBWProjectFT::verifyShapes(IPosition pbShape, IPosition skyShape)
    4061             :   {
    4062           0 :     if ((pbShape(0) != skyShape(0)) && // X-axis
    4063           0 :         (pbShape(1) != skyShape(1)) && // Y-axis
    4064           0 :         (pbShape(2) != skyShape(2)))   // Poln-axis
    4065             :       {
    4066             :         throw(AipsError("Sky and/or polarization shape of the avgPB "
    4067           0 :                         "and the sky model do not match."));
    4068             :         return false;
    4069             :       }
    4070           0 :     return true;
    4071             :     
    4072             :   }
    4073             :   //
    4074             :   // The functions are not azimuthally symmetric - so compute the
    4075             :   // support size carefully.  Collect every PixInc pixel along a
    4076             :   // quarter circle of radius R (four-fold azimuthal symmetry is
    4077             :   // assumed), and check if any pixel in this list is above the
    4078             :   // threshold. If TRUE, then R is the support radius.  Else decrease
    4079             :   // R and check again.
    4080             :   //
    4081             :   //
    4082           0 :   Bool nPBWProjectFT::findSupport(Array<Complex>& func, Float& threshold,Int& origin, Int& R)
    4083             :   {
    4084             :     Double NSteps;
    4085           0 :     Int PixInc=1;
    4086           0 :     Vector<Complex> vals;
    4087           0 :     IPosition ndx(4,origin,0,0,0);
    4088           0 :     Bool found=false;
    4089           0 :     IPosition cfShape=func.shape();
    4090           0 :     for(R=convSize/4;R>1;R--)
    4091             :       {
    4092           0 :         NSteps = 90*R/PixInc; //Check every PixInc pixel along a
    4093             :                               //circle of radious R
    4094           0 :         vals.resize((Int)(NSteps+0.5));
    4095           0 :         vals=0;
    4096           0 :         for(Int th=0;th<NSteps;th++)
    4097             :           {
    4098           0 :             ndx(0)=(int)(origin + R*sin(2.0*M_PI*th*PixInc/R));
    4099           0 :             ndx(1)=(int)(origin + R*cos(2.0*M_PI*th*PixInc/R));
    4100             :             
    4101           0 :             if ((ndx(0) < cfShape(0)) && (ndx(1) < cfShape(1)))
    4102           0 :               vals(th)=convFunc(ndx);
    4103             :           }
    4104           0 :         if (max(abs(vals)) > threshold)
    4105           0 :           {found=true;break;}
    4106             :       }
    4107           0 :     return found;
    4108             :   }
    4109             :   /*
    4110             :   void nPBWProjectFT::makeAveragePB(const VisBuffer& vb, 
    4111             :                                    const ImageInterface<Complex>& image,
    4112             :                                    Int& polInUse,
    4113             :                                    //TempImage<Float>& thesquintPB,
    4114             :                                    TempImage<Float>& theavgPB)
    4115             :   {
    4116             :     if (!resetPBs) return;
    4117             : 
    4118             :     Vector<Float> paList;
    4119             :     //
    4120             :     // Compute a list of PA present in the data with an increment of 10deg
    4121             :     // for PA-averaging of the average PB
    4122             :     //
    4123             :     {
    4124             :       Record time;
    4125             :       MSRange msr(*ms_p);
    4126             :       time = msr.range(MSS::TIMES);
    4127             :       Vector<Double> times=time.asArrayDouble("times");
    4128             : 
    4129             :       Float pa0=vb.feed_pa(times[0])[0],pa1, dpa;
    4130             :       paList.resize(1);
    4131             : 
    4132             :       paList[0]=pa0;
    4133             : 
    4134             :       for(uInt ipa=0;ipa<times.nelements();ipa++) 
    4135             :         {
    4136             :           pa1=vb.feed_pa(times[ipa])[0];
    4137             :           dpa = abs(pa1-pa0);
    4138             :           if (dpa >= 10.0/57.2956)
    4139             :             {
    4140             :               pa0=pa1;
    4141             :               paList.resize(paList.nelements()+1,true);
    4142             :               paList[paList.nelements()-1] = pa0;
    4143             :             }
    4144             :         }
    4145             : //        paList.resize(1);
    4146             : //        paList[0]=pa0;
    4147             :     }
    4148             :     TempImage<Float> localPB;
    4149             :     localPB.setMaximumCacheSize(cachesize);
    4150             :     logIO() << LogOrigin("nPBWProjecFT","makeAveragePB")
    4151             :             << LogIO::NORMAL;
    4152             :     
    4153             :     localPB.resize(image.shape()); localPB.setCoordinateInfo(image.coordinates());
    4154             :     //
    4155             :     // If this is the first time, resize the average PB
    4156             :     //
    4157             :     if (resetPBs)
    4158             :       {
    4159             :         logIO() << LogOrigin("nPBWProjectFT", "makeAveragePB")  
    4160             :                 << "Computing the PA-averaged PBs.  Averaging over "
    4161             :                 << paList.nelements() << " PA values."
    4162             :                 << LogIO::NORMAL
    4163             :                 << LogIO::POST;
    4164             :         theavgPB.resize(localPB.shape()); 
    4165             :         theavgPB.setCoordinateInfo(localPB.coordinates());
    4166             :         theavgPB.set(0.0);
    4167             :         noOfPASteps = 0;
    4168             :         pbPeaks.resize(theavgPB.shape()(2));
    4169             :         pbPeaks.set(0.0);
    4170             :         resetPBs=false;
    4171             :       }
    4172             :     ProgressMeter pm(1.0, Double(paList.nelements()),
    4173             :                      "Making average PB",
    4174             :                      "", "", "", true);
    4175             :     //
    4176             :     // Make the Stokes PB
    4177             :     //
    4178             :     for(Int iPA=0;iPA<paList.nelements();iPA++)
    4179             :       {
    4180             :         localPB.set(1.0);
    4181             :         //   vpSJ->applySquare(localPB,localPB,vb,1);  // This is Stokes PB (not squinted)
    4182             :         {
    4183             :           VLACalcIlluminationConvFunc vlaPB;
    4184             :           vlaPB.setMaximumCacheSize(cachesize);
    4185             :           Vector<Float> pa(1);
    4186             :           pa[0] = paList(iPA);
    4187             :           //      vlaPB.applyPB(localPB, vb, paList, bandID_p);
    4188             :           if (bandID_p == -1) bandID_p=getVisParams(vb);
    4189             :           vlaPB.applyPB(localPB, vb, pa, bandID_p);
    4190             :         }
    4191             :         
    4192             : //      IPosition twoDPBShape(localPB.shape());
    4193             :         IPosition twoDPBShape(localPB.shape());
    4194             : //      TempImage<Complex> localTwoDPB(twoDPBShape,localPB.coordinates());
    4195             : //      localTwoDPB.setMaximumCacheSize(cachesize);
    4196             :     
    4197             :         //   Array<Float> raoff,decoff;
    4198             :         Float peak=0;
    4199             :         Int NAnt;
    4200             :         //    NAnt=findPointingOffsets(vb,l_offsets,m_offsets,true);
    4201             :         //     if (doPointing)
    4202             :         //       NAnt=findPointingOffsets(vb,l_offsets,m_offsets,false);
    4203             :         //     else
    4204             :         //       NAnt = 1;
    4205             :     
    4206             : //      logIO() << LogOrigin("nPBWProjectFT", "makeAveragePB")  
    4207             : //              << "Updating average PB @ PA = " << paList(iPA)*57.2956 << "deg"
    4208             : //              << LogIO::NORMAL
    4209             : //              << LogIO::POST;
    4210             :         
    4211             :         noOfPASteps++;
    4212             :         if (!doPointing) NAnt=1;
    4213             :         //
    4214             :         // For now, disable the "jittering" of the avg. PB by antenna pointing offsets.
    4215             :         // May not be required even for the very deep imaging - but thinking is a bit 
    4216             :         // too clouded right now to delete the code below (SB)
    4217             :         //
    4218             :         NAnt=1; 
    4219             :         
    4220             :         for(Int ant=0;ant<NAnt;ant++)
    4221             :           { //Ant loop
    4222             : //          {
    4223             : //            IPosition ndx(4,0,0,0,0);
    4224             : //            for(ndx(0)=0; ndx(0)<twoDPBShape(0); ndx(0)++)
    4225             : //              for(ndx(1)=0; ndx(1)<twoDPBShape(1); ndx(1)++)
    4226             : //                //         for(ndx(2)=0; ndx(2)<polInUse; ndx(2)++)
    4227             : //                for(ndx(2)=0; ndx(2)<twoDPBShape(2); ndx(2)++)
    4228             : //                  localTwoDPB.putAt(Complex((localPB(ndx)),0.0),ndx);
    4229             : //          }
    4230             :             //
    4231             :             // If antenna pointing errors are not applied, no shifting
    4232             :             // (which can be expensive) is required.
    4233             :             //
    4234             :             //
    4235             :             // Accumulate the shifted PBs
    4236             :             //
    4237             :             {
    4238             :               Bool isRefF,isRefC;
    4239             :               Array<Float> fbuf,cbuf;
    4240             :               //              Array<Complex> cbuf;
    4241             :               isRefF=theavgPB.get(fbuf);
    4242             :               //              isRefC=localTwoDPB.get(cbuf);
    4243             :               isRefC=localPB.get(cbuf);
    4244             :               
    4245             :               //              Vector<Float> tmpPeaks(pbPeaks.nelements());
    4246             :               IPosition cs(cbuf.shape()),fs(fbuf.shape()),peakLoc(4,0,0,0,0);;
    4247             :               //         if (makingPSF)
    4248             :               {
    4249             :                 IPosition ndx(4,0,0,0,0),avgNDX(4,0,0,0,0);
    4250             :                 for(ndx(2)=0,avgNDX(2)=0;ndx(2)<twoDPBShape(2);ndx(2)++,avgNDX(2)++)
    4251             :                   {
    4252             :                     for(ndx(0)=0,avgNDX(0)=0;ndx(0)<fs(0);ndx(0)++,avgNDX(0)++)
    4253             :                       for(ndx(1)=0,avgNDX(1)=0;ndx(1)<fs(1);ndx(1)++,avgNDX(1)++)
    4254             :                         {
    4255             :                           Float val;
    4256             :                           val = real(cbuf(ndx));
    4257             :                           fbuf(avgNDX) += val;
    4258             :                           if (fbuf(avgNDX) > peak) peak=fbuf(avgNDX);
    4259             :                         }
    4260             :                   }
    4261             :               }
    4262             :               if (!isRefF) theavgPB.put(fbuf);
    4263             :               //              pbPeaks += tmpPeaks;
    4264             :               //              cout << "Current PB peak = " << peak << endl;
    4265             :             }
    4266             :           }
    4267             :         pm.update(Double(iPA+1));
    4268             :       }
    4269             :   }
    4270             :   */
    4271             : 
    4272           0 :   void nPBWProjectFT::makeAntiAliasingOp(Vector<Complex>& op, const Int nx_l)
    4273             :   {
    4274           0 :     MathFunc<Float> sf(SPHEROIDAL);
    4275           0 :     if (op.nelements() != (uInt)nx_l)
    4276             :       {
    4277           0 :         op.resize(nx_l);
    4278           0 :         Int inner=nx_l/2, center=nx_l/2;
    4279             :         //
    4280             :         // The "complicated" equation below is worthy of a comment (as
    4281             :         // notes are called in program text).
    4282             :         //
    4283             :         // uvScale/nx == Size of a pixel size in the image in radians.
    4284             :         // Lets call it dx.  HPBW is the HPBW for the antenna at the
    4285             :         // centre freq. in use.  HPBW/dx == Pixel where the PB will be
    4286             :         // ~0.5x its peak value.  ((2*N*HPBW)/dx) == the pixel where
    4287             :         // the N th. PB sidelobe will be (rougly speaking).  When this
    4288             :         // value is equal to 3.0, the Spheroidal implemtation goes to
    4289             :         // zero!
    4290             :         //
    4291           0 :         Float dx=uvScale(0)*convSampling/nx;
    4292           0 :         Float MaxSideLobeNum = 3.0;
    4293           0 :         Float S=1.0*dx/(MaxSideLobeNum*2*HPBW),cfScale;
    4294             :         
    4295           0 :         cout << "UVSCALE = " << uvScale(0) << " " << convSampling << endl;
    4296           0 :         cout << "HPBW = " << HPBW 
    4297           0 :              << " " << Diameter_p 
    4298           0 :              << " " << uvScale(0)/nx 
    4299           0 :              << " " << S 
    4300           0 :              << " " << dx 
    4301           0 :              << endl;
    4302             :         
    4303             : 
    4304           0 :         cfScale=S=6.0/inner;
    4305           0 :         for(Int ix=-inner;ix<inner;ix++)         op(ix+center)=sf.value(abs((ix)*cfScale));
    4306             :         // for(Int ix=-inner;ix<inner;ix++)
    4307             :         //   if (abs(op(ix+center)) > 1e-8) 
    4308             :         //          cout << "SF: " << ix 
    4309             :         //               << " " << (ix)*cfScale 
    4310             :         //               << " " << real(op(ix+center)) 
    4311             :         //               << " " << imag(op(ix+center))
    4312             :         //               << endl;
    4313             :       }
    4314           0 :   }
    4315             : 
    4316           0 :   void nPBWProjectFT::makeAntiAliasingCorrection(Vector<Complex>& correction, 
    4317             :                                                  const Vector<Complex>& op,
    4318             :                                                  const Int nx_l)
    4319             :   {
    4320           0 :     if (correction.nelements() != (uInt)nx_l)
    4321             :       {
    4322           0 :         correction.resize(nx_l);
    4323           0 :         correction=0.0;
    4324           0 :         Int opLen=op.nelements(), orig=nx_l/2;
    4325           0 :         for(Int i=-opLen;i<opLen;i++)
    4326             :           {
    4327           0 :             correction(i+orig) += op(abs(i));
    4328             :           }
    4329           0 :         ArrayLattice<Complex> tmp(correction);
    4330           0 :         LatticeFFT::cfft(tmp,false);
    4331           0 :         correction=tmp.get();
    4332             :       }
    4333             : //     for(uInt i=0;i<correction.nelements();i++)
    4334             : //       cout << "FTSF: " << real(correction(i)) << " " << imag(correction(i)) << endl;
    4335           0 :   }
    4336             : 
    4337           0 :   void nPBWProjectFT::correctAntiAliasing(Lattice<Complex>& image)
    4338             :   {
    4339             :     //  applyAntiAliasingOp(cf,2);
    4340           0 :     IPosition shape(image.shape());
    4341           0 :     IPosition ndx(shape);
    4342           0 :     ndx=0;
    4343           0 :     makeAntiAliasingCorrection(antiAliasingCorrection, 
    4344           0 :                                antiAliasingOp,shape(0));
    4345             : 
    4346           0 :     Complex tmp,val;
    4347           0 :     for(Int i=0;i<polInUse;i++)
    4348             :       {
    4349           0 :         ndx(2)=i;
    4350           0 :         for (Int iy=0;iy<shape(1);iy++) 
    4351             :           {
    4352           0 :             for (Int ix=0;ix<shape(0);ix++) 
    4353             :               {
    4354           0 :                 ndx(0)=ix;
    4355           0 :                 ndx(1)=iy;
    4356           0 :                 tmp = image.getAt(ndx);
    4357           0 :                 val=(antiAliasingCorrection(ix)*antiAliasingCorrection(iy));
    4358           0 :                 if (abs(val) > 1e-5) tmp = tmp/val; else tmp=0.0;
    4359           0 :                 image.putAt(tmp,ndx);
    4360             :               }
    4361             :           }
    4362             :       }
    4363           0 :   }
    4364             : 
    4365           0 :   void nPBWProjectFT::applyAntiAliasingOp(ImageInterface<Complex>& cf, 
    4366             :                                           Vector<IPosition>& maxPos,
    4367             :                                           Int op, 
    4368             :                                           Bool Square)
    4369             :   {
    4370             :     //
    4371             :     // First the spheroidal function
    4372             :     //
    4373           0 :     IPosition shape(cf.shape());
    4374           0 :     IPosition ndx(shape);
    4375           0 :     Vector<Double> refPixel=cf.coordinates().referencePixel();
    4376           0 :     ndx=0;
    4377           0 :     Int nx_l=shape(0),posX,posY;
    4378           0 :     makeAntiAliasingOp(antiAliasingOp, nx_l);
    4379             : 
    4380           0 :     Complex tmp,gain;
    4381             : 
    4382           0 :     for(Int i=0;i<polInUse;i++)
    4383             :       {
    4384           0 :         ndx(2)=i;
    4385           0 :         for (Int iy=-nx_l/2;iy<nx_l/2;iy++) 
    4386             :           {
    4387           0 :             for (Int ix=-nx_l/2;ix<nx_l/2;ix++) 
    4388             :               {
    4389           0 :                 ndx(0)=ix+nx_l/2;
    4390           0 :                 ndx(1)=iy+nx_l/2;
    4391           0 :                 tmp = cf.getAt(ndx);
    4392           0 :                 posX=ndx(0)+(Int)(refPixel(0)-maxPos(i)(0))+1;
    4393           0 :                 posY=ndx(1)+(Int)(refPixel(1)-maxPos(i)(1))+1;
    4394           0 :                 if ((posX > 0) && (posX < nx_l) &&
    4395           0 :                     (posY > 0) && (posY < nx_l))
    4396           0 :                   gain = antiAliasingOp(posX)*antiAliasingOp(posY);
    4397             :                 else
    4398           0 :                   if (op==2) gain = 1.0; else gain=0.0;
    4399           0 :                 if (Square) gain *= gain;
    4400           0 :                 switch (op)
    4401             :                   {
    4402           0 :                   case 0: tmp = tmp+gain;break;
    4403           0 :                   case 1: 
    4404             :                     {
    4405           0 :                       tmp = tmp*gain;
    4406           0 :                       break;
    4407             :                     }
    4408           0 :                   case 2: tmp = tmp/gain;break;
    4409             :                   }
    4410           0 :                 cf.putAt(tmp,ndx);
    4411             :               }
    4412             :           }
    4413             :       }
    4414           0 :   };
    4415           0 :   void nPBWProjectFT::applyAntiAliasingOp(ImageInterface<Float>& cf, 
    4416             :                                           Vector<IPosition>& maxPos,
    4417             :                                           Int op, 
    4418             :                                           Bool Square)
    4419             :   {
    4420             :     //
    4421             :     // First the spheroidal function
    4422             :     //
    4423           0 :     IPosition shape(cf.shape());
    4424           0 :     IPosition ndx(shape);
    4425           0 :     Vector<Double> refPixel=cf.coordinates().referencePixel();
    4426           0 :     ndx=0;
    4427           0 :     Int nx_l=shape(0),posX,posY;
    4428           0 :     makeAntiAliasingOp(antiAliasingOp, nx_l);
    4429             : 
    4430             :     Float tmp,gain;
    4431             : 
    4432           0 :     for(Int i=0;i<polInUse;i++)
    4433             :       {
    4434           0 :         ndx(2)=i;
    4435           0 :         for (Int iy=-nx_l/2;iy<nx_l/2;iy++) 
    4436             :           {
    4437           0 :             for (Int ix=-nx_l/2;ix<nx_l/2;ix++) 
    4438             :               {
    4439           0 :                 ndx(0)=ix+nx_l/2;
    4440           0 :                 ndx(1)=iy+nx_l/2;
    4441           0 :                 tmp = cf.getAt(ndx);
    4442           0 :                 posX=ndx(0)+(Int)(refPixel(0)-maxPos(i)(0))+1;
    4443           0 :                 posY=ndx(1)+(Int)(refPixel(1)-maxPos(i)(1))+1;
    4444           0 :                 if ((posX > 0) && (posX < nx_l) &&
    4445           0 :                     (posY > 0) && (posY < nx_l))
    4446           0 :                   gain = real(antiAliasingOp(posX)*antiAliasingOp(posY));
    4447             :                 else
    4448           0 :                   if (op==2) gain = 1.0; else gain=0.0;
    4449           0 :                 if (Square) gain *= gain;
    4450           0 :                 switch (op)
    4451             :                   {
    4452           0 :                   case 0: tmp = tmp+gain;break;
    4453           0 :                   case 1: 
    4454             :                     {
    4455           0 :                       tmp = tmp*gain;
    4456           0 :                       break;
    4457             :                     }
    4458           0 :                   case 2: tmp = tmp/gain;break;
    4459             :                   }
    4460           0 :                 cf.putAt(tmp,ndx);
    4461             :               }
    4462             :           }
    4463             :       }
    4464           0 :   };
    4465             : } //# NAMESPACE CASA - END
    4466             : 

Generated by: LCOV version 1.16