LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - AWProjectWBFT.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 203 315 64.4 %
Date: 2024-12-11 20:54:31 Functions: 11 19 57.9 %

          Line data    Source code
       1             : // -*- C++ -*-
       2             : //# AWProjectWBFT.cc: Implementation of AWProjectWBFT class
       3             : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
       4             : //# Associated Universities, Inc. Washington DC, USA.
       5             : //#
       6             : //# This library is free software; you can redistribute it and/or modify it
       7             : //# under the terms of the GNU Library General Public License as published by
       8             : //# the Free Software Foundation; either version 2 of the License, or (at your
       9             : //# option) any later version.
      10             : //#
      11             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      12             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      14             : //# License for more details.
      15             : //#
      16             : //# You should have received a copy of the GNU Library General Public License
      17             : //# along with this library; if not, write to the Free Software Foundation,
      18             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      19             : //#
      20             : //# Correspondence concerning AIPS++ should be addressed as follows:
      21             : //#        Internet email: casa-feedback@nrao.edu.
      22             : //#        Postal address: AIPS++ Project Office
      23             : //#                        National Radio Astronomy Observatory
      24             : //#                        520 Edgemont Road
      25             : //#                        Charlottesville, VA 22903-2475 USA
      26             : //#
      27             : //# $Id$
      28             : 
      29             : #include <synthesis/TransformMachines2/VB2CFBMap.h>
      30             : #include <synthesis/TransformMachines2/AWProjectWBFT.h>
      31             : #include <synthesis/TransformMachines2/AWVisResampler.h>
      32             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      33             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      34             : #include <casacore/scimath/Mathematics/FFTServer.h>
      35             : #include <casacore/scimath/Mathematics/Convolver.h>
      36             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      37             : #include <casacore/images/Images/ImageInterface.h>
      38             : #include <casacore/images/Images/PagedImage.h>
      39             : #include <msvis/MSVis/VisBuffer2.h>
      40             : #include <casacore/casa/Arrays/Vector.h>
      41             : #include <casacore/casa/Arrays/Slice.h>
      42             : #include <casacore/casa/Arrays/ArrayMath.h>
      43             : #include <casacore/casa/Arrays/Array.h>
      44             : #include <casacore/casa/OS/HostInfo.h>
      45             : #include <sstream>
      46             : #include <casacore/casa/Utilities/CompositeNumber.h>
      47             : 
      48             : using namespace casacore;
      49             : namespace casa { //# NAMESPACE CASA - BEGIN
      50             :   namespace refim{
      51             :     //==================================================================================================
      52             :     // Various template instantiations
      53             :     //
      54             :     template
      55             :     void AWProjectWBFT::ftWeightImage(Lattice<casacore::Complex>& wtImage, 
      56             :                                       const Matrix<Float>& sumWt,
      57             :                                       const Bool& doFFTNorm);
      58             :     template
      59             :     void AWProjectWBFT::makeWBSensitivityImage(Lattice<casacore::Complex>& wtImage,
      60             :                                                ImageInterface<Float>& sensitivityImage,
      61             :                                                const Matrix<Float>& sumWt,
      62             :                                                const Bool& doFFTNorm);
      63             :     //==================================================================================================
      64             :     template
      65             :     void AWProjectWBFT::ftWeightImage(Lattice<casacore::DComplex>& wtImage, 
      66             :                                       const Matrix<Float>& sumWt,
      67             :                                       const Bool& doFFTNorm);
      68             :     template
      69             :     void AWProjectWBFT::makeWBSensitivityImage(Lattice<casacore::DComplex>& wtImage,
      70             :                                                ImageInterface<Float>& sensitivityImage,
      71             :                                                const Matrix<Float>& sumWt,
      72             :                                                const Bool& doFFTNorm);
      73             :     //==================================================================================================
      74             :     template 
      75             :     void AWProjectWBFT::resampleCFToGrid(Array<casacore::Complex>& gwts, 
      76             :                                          VBStore& vbs, const VisBuffer2& vb);
      77             :     template 
      78             :     void AWProjectWBFT::resampleCFToGrid(Array<casacore::DComplex>& gwts, 
      79             :                                          VBStore& vbs, const VisBuffer2& vb);
      80             :     //==================================================================================================
      81             : 
      82             :   //
      83             :   //---------------------------------------------------------------
      84             :   //
      85          93 :   AWProjectWBFT::AWProjectWBFT(Int nWPlanes, Long icachesize, 
      86             :                                CountedPtr<CFCache>& cfcache,
      87             :                                CountedPtr<ConvolutionFunction>& cf,
      88             :                                CountedPtr<VisibilityResamplerBase>& visResampler,
      89             :                                Bool applyPointingOffset,
      90             :                                vector<float> pointingOffsetSigDev,
      91             :                                Bool doPBCorr,
      92             :                                Int itilesize, 
      93             :                                Float paSteps,
      94             :                                Float pbLimit,
      95             :                                Bool usezero,
      96             :                                Bool conjBeams,
      97          93 :                                Bool doublePrecGrid)
      98             :     : AWProjectFT(nWPlanes,icachesize,cfcache,cf,visResampler,applyPointingOffset,pointingOffsetSigDev,doPBCorr, itilesize,pbLimit,usezero,conjBeams,doublePrecGrid),
      99             :       //avgPBReady_p(false),
     100          93 :       resetPBs_p(true),wtImageFTDone_p(false),fieldIds_p(0),rotatedCFWts_p(),visResamplerWt_p(nullptr),oneTimeMessage_p(false)
     101             :   {
     102             :     (void)paSteps;
     103             :     //
     104             :     // Set the function pointer for FORTRAN call for GCF services.  
     105             :     // This is a pure C function pointer which FORTRAN can call.  
     106             :     // The function itself uses GCF object services.
     107             :     //
     108          93 :     paChangeDetector.reset();
     109          93 :     pbLimit_p=pbLimit;
     110          93 :     if (applyPointingOffset) doPointing=1; else doPointing=0;
     111          93 :     maxConvSupport=-1;  
     112             :     //
     113             :     // Set up the Conv. Func. disk cache manager object.
     114             :     //
     115             :     //use memory size defined in aipsrc if exists
     116          93 :     Long hostRAM = (HostInfo::memoryTotal(true)*1024); // In bytes
     117          93 :     hostRAM = hostRAM/(sizeof(Float)*2); // In complex pixels
     118          93 :     if (cachesize > hostRAM) cachesize=hostRAM;
     119             : 
     120          93 :     lastPAUsedForWtImg = MAGICPAVALUE;
     121          93 :   }
     122             :   //
     123             :   //---------------------------------------------------------------
     124             :   //
     125           0 :   AWProjectWBFT::AWProjectWBFT(const RecordInterface& stateRec)
     126           0 :     : AWProjectFT(stateRec), oneTimeMessage_p(false)
     127             :   {
     128           0 :     LogIO log_l(LogOrigin("AWProjectWBFT2", "AWProjectWBFT[R&D]"));
     129             :     // Construct from the input state record
     130             : 
     131           0 :     if (!fromRecord(stateRec)) 
     132           0 :       log_l << "Failed to create " << name() << " object." << LogIO::EXCEPTION;
     133             : 
     134           0 :     maxConvSupport=-1;
     135           0 :     visResampler_p->init(useDoubleGrid_p);
     136           0 :   }
     137             :   //
     138             :   //---------------------------------------------------------------
     139             :   //
     140         159 :   AWProjectWBFT& AWProjectWBFT::operator=(const AWProjectWBFT& other)
     141             :   {
     142         159 :     if(this!=&other) 
     143             :       {
     144         159 :         AWProjectFT::operator=(other);
     145         159 :         padding_p       =   other.padding_p;
     146         159 :         nWPlanes_p      =   other.nWPlanes_p;
     147         159 :         imageCache      =   other.imageCache;
     148         159 :         cachesize       =   other.cachesize;
     149         159 :         tilesize        =   other.tilesize;
     150         159 :         gridder         =   other.gridder;
     151         159 :         isTiled         =   other.isTiled;
     152         159 :         lattice         =   other.lattice;
     153         159 :         maxAbsData      =   other.maxAbsData;
     154         159 :         centerLoc       =   other.centerLoc;
     155         159 :         offsetLoc       =   other.offsetLoc;
     156         159 :         pointingToImage =   other.pointingToImage;
     157         159 :         usezero_p       =   other.usezero_p;
     158         159 :         doPBCorrection  =   other.doPBCorrection;
     159         159 :         maxConvSupport  =   other.maxConvSupport;
     160         159 :         resetPBs_p      =   other.resetPBs_p;
     161         159 :         wtImageFTDone_p =   other.wtImageFTDone_p;
     162         159 :         rotatedCFWts_p  =   other.rotatedCFWts_p;
     163         159 :         visResamplerWt_p=other.visResamplerWt_p; // Copy the counted pointer
     164         159 :         oneTimeMessage_p = other.oneTimeMessage_p;
     165             :     };
     166         159 :     return *this;
     167             :   };
     168             :   //
     169             :   //----------------------------------------------------------------------
     170             :   //
     171           0 :   Int AWProjectWBFT::findPointingOffsets(const VisBuffer2& vb, 
     172             :                                          Array<Float> &l_off,
     173             :                                          Array<Float> &m_off,
     174             :                                          Bool Evaluate)
     175             :   {
     176           0 :     LogIO log_l(LogOrigin("AWProjectWBFT2","findPointingOffsets[R&D]"));
     177           0 :     Int NAnt=0;
     178             :     //
     179             :     // This will return 0 if EPJ Table is not given.  Otherwise will
     180             :     // return the number of antennas it detected (from the EPJ table)
     181             :     // and the offsets in l_off and m_off.
     182             :     //
     183           0 :     NAnt = AWProjectFT::findPointingOffsets(vb,l_off,m_off,Evaluate);
     184             :     //
     185             :     // Resize the offset arrays if no pointing table was given.
     186             :     //
     187           0 :     if (NAnt <=0 )
     188             :       {
     189           0 :         NAnt=vb.subtableColumns().antenna().nrow();
     190           0 :         l_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     191           0 :         m_off.resize(IPosition(3,1,1,NAnt)); // Poln x NChan x NAnt 
     192           0 :         l_off = m_off = 0.0; 
     193             :       }
     194             :     //
     195             :     // Add field offsets to the pointing errors.
     196             :     //
     197             :     //
     198             :     // Convert the direction from image co-ordinate system and the VB
     199             :     // to MDirection.  Then convert the MDirection to Quantity so that
     200             :     // arithematic operation (subtraction) can be done.  Then use the
     201             :     // subtracted Quantity to construct another MDirection and use
     202             :     // *it's* getAngle().getValue() to extract the difference in the
     203             :     // sky direction (from image co-ordinate system) and the phase
     204             :     // center direction of the VB in radians!  
     205             :     //
     206             :     // If only VisBuffer, and DirectionCoordinate class could return
     207             :     // MDirection, and MDirection class had operator-(), the code
     208             :     // below could look more readable as:
     209             :     //  MDirection diff=vb.mDirection()-directionCoord.mDirection();
     210             :     // 
     211           0 :     CoordinateSystem coords(image->coordinates());
     212           0 :     Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
     213           0 :     AlwaysAssert(directionIndex>=0, AipsError);
     214           0 :     DirectionCoordinate directionCoord=coords.directionCoordinate(directionIndex);
     215           0 :     MDirection vbMDir(vb.direction1()(0)),skyMDir, diff;
     216           0 :     directionCoord.toWorld(skyMDir, directionCoord.referencePixel());
     217             : 
     218           0 :     diff = MDirection(skyMDir.getAngle()-vbMDir.getAngle());
     219           0 :     l_off = l_off - (Float)diff.getAngle().getValue()(0);
     220           0 :     m_off = m_off - (Float)diff.getAngle().getValue()(1);
     221             : 
     222             :     static int firstPass=0;
     223             :     //    static int fieldID=-1;
     224           0 :     static Vector<Float> offsets0,offsets1;
     225           0 :     if (firstPass==0)
     226             :       {
     227           0 :         offsets0.resize(NAnt);
     228           0 :         offsets1.resize(NAnt);
     229           0 :         offsets0 = offsets1 = 0.0;
     230             :       }
     231           0 :     for(Int i=0;i<NAnt;i++)
     232             :       {
     233           0 :         l_off(IPosition(3,0,0,i)) = l_off(IPosition(3,0,0,i)) + offsets0(i)/2.062642e+05;
     234           0 :         m_off(IPosition(3,0,0,i)) = m_off(IPosition(3,0,0,i)) + offsets1(i)/2.062642e+05;
     235             :       }
     236             : 
     237           0 :     if (firstPass==0) 
     238             :       {
     239             : //       cout << (Float)(directionCoord.referenceValue()(0)) << " "
     240             : //            << (Float)(directionCoord.referenceValue()(1)) << endl;
     241             : //       cout << vb.direction1()(0).getAngle().getValue()(0) << " "
     242             : //            << vb.direction1()(0).getAngle().getValue()(1) << endl;
     243             : //      cout << l_off << endl;
     244             : //      cout << m_off << endl;
     245             :        }
     246           0 :      firstPass++;
     247           0 :     return NAnt;
     248           0 :   }
     249             :   //
     250             :   //---------------------------------------------------------------
     251             :   //
     252             :   // void AWProjectWBFT::normalizeAvgPB()
     253             :   // {
     254             :   //   LogIO log_l(LogOrigin("AWProjectWBFT2","normalizeAvgPB[R&D]"));
     255             :   //   // We accumulated normalized PBs.  So don't normalize the average
     256             :   //   // PB.
     257             :   //   pbNormalized_p = false;
     258             :     
     259             :   // }
     260             :   //
     261             :   //---------------------------------------------------------------
     262             :   // For wide-band case, this just tells the user that the sensitivity
     263             :   // image will be computed during the first gridding cycle.
     264             :   //
     265             :   // Weights image (sum of convolution functions) is accumulated
     266             :   // during gridding.  At the end of the gridding cycle, the weight
     267             :   // image is FT'ed (using ftWeightImage()) and properly normalized
     268             :   // and converted to sensitivity image (using
     269             :   // makeSensitivityImage()).  These methods are triggred in the first
     270             :   // call to getImage().  In subsequent calls to getImage() these
     271             :   // calls are NoOps.
     272             :   //
     273          59 :   void AWProjectWBFT::makeSensitivityImage(const VisBuffer2&,
     274             :                                            const ImageInterface<Complex>& /*Complex imageTemplate*/,
     275             :                                            ImageInterface<Float>& /*sensitivityImage*/)
     276             :   {
     277          59 :     if (avgPBReady_p == false)
     278             :       {
     279          59 :         if (oneTimeMessage_p == false)
     280             :           {
     281         118 :             LogIO log_l(LogOrigin("AWProjectWBFT2", "makeSensitivityImage(Complex)[R&D]"));
     282          59 :             log_l << "Setting up for weights accumulation ";
     283          59 :             if (sensitivityPatternQualifierStr_p != "") log_l << "for term " << sensitivityPatternQualifier_p << " ";
     284             :             log_l << "during gridding to compute sensitivity pattern."
     285             :                   << endl
     286             :                   << "Consequently, the first gridding cycle will be slower than the subsequent ones." 
     287          59 :                   << LogIO::WARN;
     288          59 :             oneTimeMessage_p=true;
     289          59 :           }
     290             :       }
     291          59 :   }
     292           0 :     void AWProjectWBFT::makeSensitivityImage(const VisBuffer2&,
     293             :                                              const ImageInterface<DComplex>& /* DComplex imageTemplate*/,
     294             :                                              ImageInterface<Float>& /*sensitivityImage*/)
     295             :     {
     296           0 :       if (avgPBReady_p == false)
     297             :         {
     298           0 :           if (oneTimeMessage_p == false)
     299             :             {
     300           0 :               LogIO log_l(LogOrigin("AWProjectWBFT2", "makeSensitivityImage(DComplex)[R&D]"));
     301           0 :               log_l << "Setting up for weights accumulation ";
     302           0 :               if (sensitivityPatternQualifierStr_p != "") log_l << "for term " << sensitivityPatternQualifier_p << " ";
     303             :               log_l << "during gridding to compute sensitivity pattern."
     304             :                     << endl
     305             :                     << "Consequently, the first gridding cycle will be slower than the subsequent ones."
     306           0 :                     << LogIO::WARN;
     307           0 :               oneTimeMessage_p=true;
     308           0 :             }
     309             :         }
     310           0 :     }
     311             :   //
     312             :   //---------------------------------------------------------------
     313             :   // 
     314             :     template <class T>
     315          52 :   void AWProjectWBFT::ftWeightImage(Lattice<T>& wtImage, 
     316             :                                     const Matrix<Float>& sumWt,
     317             :                                     const Bool& doFFTNorm)
     318             :   {
     319         104 :     LogIO log_l(LogOrigin("AWProjectWBFT2", "ftWeightImage[R&D]"));
     320          52 :     if (wtImageFTDone_p) return;
     321             : 
     322          52 :     if ((sumWt.shape().nelements() < 2) || 
     323         208 :         (sumWt.shape()(0) != wtImage.shape()(2)) || 
     324         104 :         (sumWt.shape()(1) != wtImage.shape()(3)))
     325           0 :       log_l << "Sum of weights per poln and chan is required" << LogIO::EXCEPTION;
     326             :     //
     327             :     // Use only the amplitude of the gridded weights.  LatticeExpr
     328             :     // classes while useful, appear to be too strict about types (the
     329             :     // code below will not compile if the abs(wtImage) is not
     330             :     // converted back to a complex type).
     331             : 
     332          52 :     LatticeFFT::cfft2d(wtImage,false);
     333          52 :     wtImageFTDone_p=true;
     334             : 
     335          52 :     Int sizeX=wtImage.shape()(0), sizeY=wtImage.shape()(1);
     336             : 
     337          52 :     Array<T> wtBuf; wtImage.get(wtBuf,false);
     338          52 :     ArrayLattice<T> wtLat(wtBuf,true);
     339             :     //
     340             :     // Copy one 2D plane at a time, normalizing by the sum of weights
     341             :     // and possibly 2D FFT.
     342             :     //
     343             :     // Set up Lattice iterators on wtImage and sensitivityImage
     344             :     //
     345          52 :     IPosition axisPath(4, 0, 1, 2, 3);
     346          52 :     IPosition cursorShape(4, sizeX, sizeY, 1, 1);
     347             : 
     348          52 :     LatticeStepper wtImStepper(wtImage.shape(), cursorShape, axisPath);
     349          52 :     LatticeIterator<T> wtImIter(wtImage, wtImStepper);
     350             :     //
     351             :     // Iterate over channel and polarization axis
     352             :     //
     353          52 :     if (!doFFTNorm) sizeX=sizeY=1;
     354             :     //
     355             :     // Normalize each frequency and polarization plane of the complex
     356             :     // sensitivity pattern
     357             :     //
     358             :     // getSumOfCFWeights() returns the sum-of-weight appropriate for
     359             :     // computing sensitivity patterns (which could be different from
     360             :     // the data-sum-of-weights.
     361             :     //
     362             : 
     363         130 :     for(wtImIter.reset(); !wtImIter.atEnd(); wtImIter++)
     364             :       {
     365          78 :         wtImIter.rwCursor() = (wtImIter.rwCursor()
     366          78 :                                *Float(sizeX)*Float(sizeY));
     367             :       }
     368          52 :   }
     369             :   //
     370             :   //---------------------------------------------------------------
     371             :   // 
     372             :     template <class T>
     373         169 :   void AWProjectWBFT::makeWBSensitivityImage(Lattice<T>& wtImage,
     374             :                                              ImageInterface<Float>& sensitivityImage,
     375             :                                              const Matrix<Float>& sumWt,
     376             :                                              const Bool& doFFTNorm)
     377             :   {
     378         169 :     if (avgPBReady_p) return;
     379         104 :     LogIO log_l(LogOrigin("AWProjectWBFT2", "makeWBSensitivityImage[R&D]"));
     380             : 
     381          52 :     ftWeightImage(wtImage, sumWt, doFFTNorm);
     382             : 
     383          52 :     if (useDoubleGrid_p)
     384             :       {
     385          52 :         sensitivityImage.resize(griddedWeights_D.shape()); 
     386          52 :         sensitivityImage.setCoordinateInfo(griddedWeights_D.coordinates());
     387             :       }
     388             :     else
     389             :       {
     390           0 :         sensitivityImage.resize(griddedWeights.shape()); 
     391           0 :         sensitivityImage.setCoordinateInfo(griddedWeights.coordinates());
     392             :       }
     393             :     //
     394             :     // Rest of the code below is to (1) average the poln planes of the
     395             :     // weight image for each freq. channel, and (2) copy the averaged
     396             :     // value to the all the poln planes for each freq. channels of the
     397             :     // sensitivity image.  
     398             :     //
     399             :     // Set up Lattice iterator on wtImage for averaging all poln
     400             :     // planes and writing the result the only the first poln plane.
     401             :     //
     402          52 :     IPosition axisPath(2, 2, 3); // Step through the Poln (2) and Freq (3) axis.
     403         104 :     IPosition cursorShapeWt(4, wtImage.shape()(0), wtImage.shape()(1), 1, 1);
     404             : 
     405          52 :     LatticeStepper wtImStepper(wtImage.shape(), cursorShapeWt, axisPath);
     406          52 :     LatticeIterator<T> wtImIter(wtImage, wtImStepper);
     407          52 :     int nPolPlanes=wtImage.shape()(2);
     408             :     // First average all poln planes and write the result back to the first poln plane.
     409         208 :     for(wtImIter.reset(); !wtImIter.atEnd(); /*increment is inside the for-loop below*/)
     410             :     {
     411          78 :       Matrix<T> tmpWt(wtImIter.rwMatrixCursor().shape());
     412          78 :       ArrayLattice<T> tt(tmpWt,true);
     413         156 :       for(int i=0;i<nPolPlanes;i++)
     414             :         {
     415          78 :           Matrix<T> tmp0_ref;tmp0_ref.reference(wtImIter.rwMatrixCursor().nonDegenerate());
     416          78 :           ArrayLattice<T> p0(tmp0_ref,true); //Make ArrayLattice from Array by refence
     417         156 :           LatticeExpr<T> le(tt+p0);
     418          78 :           tt.copyData(le); 
     419          78 :           wtImIter++;
     420             :         }
     421         156 :       LatticeExpr<T> le(tt/nPolPlanes);
     422          78 :       tt.copyData(le); 
     423             :     }
     424             :     
     425         104 :     IPosition cursorShape(4, sensitivityImage.shape()(0), sensitivityImage.shape()(1), 1, 1);
     426          52 :     LatticeStepper senImStepper(sensitivityImage.shape(), cursorShape, axisPath);
     427          52 :     LatticeIterator<Float> senImIter(sensitivityImage, senImStepper);
     428             :     //
     429             :     // Copy the real part of the average of all planes of the wtImage
     430             :     // to all the planes of the sensitivity image (senImage).
     431             :     //
     432         208 :     for(wtImIter.reset(),senImIter.reset(); !wtImIter.atEnd();/*increment is inside the first for-loop below*/)
     433             :       {
     434             :         // Extract the first polarization plane from the weight image. 
     435          78 :         Matrix<T> wt_ref;wt_ref.reference(wtImIter.rwMatrixCursor().nonDegenerate());
     436          78 :         ArrayLattice<T> p0(wt_ref,true);
     437         156 :         for (int i=0;i<nPolPlanes;i++) wtImIter++; // Skip the rest of the poln planes
     438             : 
     439         156 :         for(int i=0;i<sensitivityImage.shape()(2);i++)
     440             :           {
     441             :             // // Now replace the polarization planes with their average.  REVIEW THIS FOR FM CASE.
     442          78 :             Matrix<Float> tmp;tmp.reference(senImIter.rwMatrixCursor().nonDegenerate());
     443          78 :             ArrayLattice<Float> tt(tmp,true); //Make ArrayLattice from Array by refence
     444         156 :             LatticeExpr<Float> le(abs(p0));
     445          78 :             tt.copyData(le); 
     446             : 
     447          78 :             senImIter++;
     448             :           }
     449             :       }
     450             : 
     451          52 :     if (tt_pp == "")
     452          52 :       cfCache_p->flush(sensitivityImage,sensitivityPatternQualifierStr_p);
     453             : 
     454          52 :     pbNormalized_p=false;
     455          52 :     resetPBs_p=false;
     456             : 
     457          52 :     avgPBReady_p=true;
     458          52 :   }
     459             :   //
     460             :   //---------------------------------------------------------------
     461             :   //
     462             :   // Convert the gridded visibilities to image. This implements the
     463             :   // basic 2D transform (vC-Z Theorem) using the FFT.
     464             :   //
     465             :   // This specialization of getImage() exists since the sensitivity
     466             :   // pattern in this FTMachine is computed as the FT of the gridded
     467             :   // weights (convolution functions).  The gridded weights are
     468             :   // available along with the gridded data at the end of the gridding
     469             :   // cycle.  This method first converts the gridded weights to
     470             :   // sensitivity image and then calls AWProjectFT::getImage(), which
     471             :   // in-turn calls normalizeImage() with the sensitivityImage and the
     472             :   // sum of weights.
     473             :   //
     474         169 :   ImageInterface<Complex>& AWProjectWBFT::getImage(Matrix<Float>& weights,
     475             :                                                    Bool fftNormalization) 
     476             :   {
     477         169 :     AlwaysAssert(image, AipsError);
     478         338 :     LogIO log_l(LogOrigin("AWProjectWBFT2", "getImage[R&D]"));
     479             : 
     480         169 :     weights.resize(sumWeight.shape());
     481         169 :     convertArray(weights, sumWeight);//I suppose this converts a
     482             :                                      //Matrix<Double> (sumWeights) to
     483             :                                      //Matrix<Float> (weights).  Why
     484             :                                      //is this conversion required?
     485             :                                      //--SB (Dec. 2010)
     486             :     //
     487             :     // Compute the sensitivity image as FT of the griddedWeigths.
     488             :     // Return the result in avgPB_p.  Cache it in the cfCache_p
     489             :     // object.  And raise the avgPBReady_p flag so that this becomes a
     490             :     // null call the next time around.
     491         169 :     if (useDoubleGrid_p)
     492         169 :       makeWBSensitivityImage(griddedWeights_D, *avgPB_p, weights, true);
     493             :     else
     494           0 :       makeWBSensitivityImage(griddedWeights, *avgPB_p, weights, true);
     495             :     //
     496             :     // This calls the overloadable method normalizeImage() which
     497             :     // normalizes the raw image by the sensitivty pattern (avgPB_p).
     498             :     //
     499         169 :     AWProjectFT::getImage(weights,fftNormalization);
     500             :         
     501         169 :     return *image;
     502         169 :   }
     503             :   //
     504             :   //---------------------------------------------------------------
     505             :   //
     506             :   // Initialize the FFT to the Sky. Here we have to setup and
     507             :   // initialize the grid.
     508             :   //
     509         176 :   void AWProjectWBFT::initializeToSky(ImageInterface<Complex>& iimage,
     510             :                                    Matrix<Float>& weight,
     511             :                                    const VisBuffer2& vb)
     512             :   {
     513         352 :     LogIO log_l(LogOrigin("AWProjectWBFT2","initializeToSky[R&D]"));
     514         176 :     AWProjectFT::initializeToSky(iimage,weight,vb);
     515             : 
     516         176 :     if (resetPBs_p)
     517             :       {
     518         117 :         if (useDoubleGrid_p)
     519             :           {
     520         117 :             griddedWeights_D.resize(iimage.shape()); 
     521         117 :             griddedWeights_D.setCoordinateInfo(iimage.coordinates());
     522         117 :             griddedWeights_D.set(0.0);
     523         117 :             pbPeaks.resize(griddedWeights_D.shape()(2));
     524         117 :             pbPeaks.set(0.0);
     525             :           }
     526             :         else
     527             :           {
     528           0 :             griddedWeights.resize(iimage.shape()); 
     529           0 :             griddedWeights.setCoordinateInfo(iimage.coordinates());
     530           0 :             griddedWeights.set(0.0);
     531           0 :             pbPeaks.resize(griddedWeights.shape()(2));
     532           0 :             pbPeaks.set(0.0);
     533             :           }
     534             : 
     535         117 :         resetPBs_p=false;
     536             :       }
     537             : 
     538         176 :     std::tuple<int, double>cubeinfo(1,-1.0);    
     539             :     double freqofBegChan;
     540         176 :     spectralCoord_p.toWorld(freqofBegChan, 0.0);
     541             :         
     542         176 :     cubeinfo=std::make_tuple(iimage.shape()(3),freqofBegChan);
     543             : 
     544             :     ///load AVGPB is quite the memory consumer for cubes as it will load the whole cube in memory a couple of times even.
     545             :     //cerr << "###Avoiding loading of avgPB " << avgPBReady_p << endl;
     546         176 :     if(!avgPBReady_p)
     547          87 :       avgPBReady_p = (cfCache_p->loadAvgPB(avgPB_p,sensitivityPatternQualifierStr_p, cubeinfo) != CFDefs::NOTCACHED);
     548             :     
     549         176 :     if(avgPBReady_p){
     550         130 :         LatticeExprNode le( max( *avgPB_p ) );
     551         130 :         Float avgPB_max=le.getFloat();
     552             :         
     553         130 :         if(avgPB_max <= 0.0) avgPBReady_p = false;
     554         130 :     }
     555             :     // Need to grid the weighted Convolution Functions to make the sensitivity pattern.
     556         176 :     if (!avgPBReady_p)
     557             :       {
     558             :         // Make a copy of the re-sampler and set it up.
     559          59 :         if (visResamplerWt_p.null()) visResamplerWt_p = visResampler_p->clone();
     560          59 :         visResamplerWt_p = visResampler_p;
     561          59 :         visResamplerWt_p->setMaps(chanMap, polMap);
     562          59 :         if (useDoubleGrid_p)
     563             :           {
     564          59 :             Array<DComplex> gwts; Bool removeDegenerateAxis=false;
     565          59 :             griddedWeights_D.get(gwts, removeDegenerateAxis);
     566          59 :             visResamplerWt_p->initializeToSky(gwts, sumCFWeight); //A NoOp right now.
     567          59 :           }
     568             :         else
     569             :           {
     570           0 :             Array<Complex> gwts; Bool removeDegenerateAxis=false;
     571           0 :             griddedWeights.get(gwts, removeDegenerateAxis);
     572           0 :             visResamplerWt_p->initializeToSky(gwts, sumCFWeight); //A NoOp right now.
     573           0 :           }
     574             :       }
     575         176 :   }
     576             :   //
     577             :   //---------------------------------------------------------------
     578             :   //
     579         169 :   void AWProjectWBFT::finalizeToSky()
     580             :   {
     581         338 :     LogIO log_l(LogOrigin("AWProjectWBFT2", "finalizeToSky[R&D]"));
     582         169 :     AWProjectFT::finalizeToSky();
     583             : 
     584         169 :     if(!visResamplerWt_p)
     585          82 :       return;
     586             : 
     587             :     //
     588             :     // SB: Not sure why the follwing if-stmt (not by SB) needs to be
     589             :     // in this class.  This be simply avoided by overloading this
     590             :     // method in the AWProjectWBFTHPG class making the NoOp obvious
     591             :     // for that class, and easily extendable & maintainable.
     592             :     //
     593          87 :     if(name()=="AWProjectWBFTHPG")
     594           0 :       return;
     595             : 
     596          87 :      if (!avgPBReady_p) 
     597             :       {
     598          52 :         if (useDoubleGrid_p)
     599             :           {
     600          52 :             Array<DComplex> gwts; Bool removeDegenerateAxis=false;
     601          52 :             griddedWeights_D.get(gwts, removeDegenerateAxis);
     602          52 :             visResamplerWt_p->finalizeToSky(gwts, sumCFWeight);
     603          52 :             visResamplerWt_p->releaseBuffers();
     604          52 :           }
     605             :         else
     606             :           {
     607           0 :             Array<Complex> gwts; Bool removeDegenerateAxis=false;
     608           0 :             griddedWeights.get(gwts, removeDegenerateAxis);
     609           0 :             visResamplerWt_p->finalizeToSky(gwts, sumCFWeight);
     610           0 :             visResamplerWt_p->releaseBuffers();
     611           0 :           }
     612             :       }
     613             :     
     614         174 :     visResampler_p->runTimeG_p
     615         261 :       =visResampler_p->runTimeG1_p
     616          87 :       =visResampler_p->runTimeG2_p
     617          87 :       =visResampler_p->runTimeG3_p
     618          87 :       =visResampler_p->runTimeG4_p
     619          87 :       =visResampler_p->runTimeG5_p
     620          87 :       =visResampler_p->runTimeG6_p
     621         174 :       =visResampler_p->runTimeG7_p
     622          87 :       =0.0;
     623          87 :     runTime1_p=0;
     624         169 :   }
     625             :   //
     626             :   //---------------------------------------------------------------
     627             :   // Method sets up the inputs for the VisResampler::DataToGrid()
     628             :   // method for gridding the CFs at the origin of the UVW-plane.  This
     629             :   // includes application of pointing offset correction and any other
     630             :   // term that might be included in VB2CFBMap::makeVBRow2CFBMap()
     631             :   // method.
     632             :     template <class T>
     633        7150 :     void AWProjectWBFT::resampleCFToGrid(Array<T>& gwts, 
     634             :                                          VBStore& vbs, const VisBuffer2& vb)
     635             :     {
     636        7150 :       visResamplerWt_p->copy(*visResampler_p);
     637             :     
     638        7150 :       po_p->fetchPointingOffset(*image, vb, doPointing);
     639       14300 :       vb2CFBMap_p->makeVBRow2CFBMap(*cfwts2_p,vb,
     640             :                                     paChangeDetector.getParAngleTolerance(),
     641        7150 :                                     chanMap,polMap,po_p);
     642        7150 :       convFuncCtor_p->prepareConvFunction(vb,*vb2CFBMap_p);
     643             :       //
     644             :       // Set the uvw array to zero-sized array and dopsf=true.
     645             :       // uvw.nelements()==0 is a hint to the re-sampler to put the
     646             :       // gridded weights at the origin of the uv-grid. dopsf=true so
     647             :       // that CF*Wts are accumulated (as against CF*Wts*Vis).
     648             :       //
     649             :       // Receive the sum-of-weights in a dummy array.
     650        7150 :       Matrix<Double> uvwOrigin;
     651        7150 :       vbs.uvw_p.reference(uvwOrigin); 
     652        7150 :       Bool dopsf_l=true;
     653        7150 :       vbs.accumCFs_p=((vbs.uvw_p.nelements() == 0) && dopsf_l);
     654        7150 :       vbs.ftmType_p=casa::refim::FTMachine::WEIGHT;  
     655        7150 :       Int nDataChan = vbs.flagCube_p.shape()[1];
     656             :     
     657        7150 :       vbs.startChan_p = 0; vbs.endChan_p = nDataChan;
     658        7150 :       visResamplerWt_p->DataToGrid(gwts, vbs, sumCFWeight, dopsf_l); 
     659        7150 :     }
     660             :   //
     661             :   //---------------------------------------------------------------
     662             :   // Methods to accumulate data on the grid.  If necessary, also
     663             :   // trigger the accumulation of CFs via ::resampleCFToGrid() method.
     664             :   //
     665           0 :   void AWProjectWBFT::resampleDataToGrid(Array<Complex>& griddedData_l,
     666             :                                          VBStore& vbs, const VisBuffer2& vb, 
     667             :                                          Bool& dopsf) 
     668             :   {
     669           0 :     AWProjectFT::resampleDataToGrid(griddedData_l,vbs,vb,dopsf);
     670           0 :     if (!avgPBReady_p)
     671             :       {
     672             :         //
     673             :         // Get a reference to the pixels of griddedWeights (a
     674             :         // TempImage!)
     675             :         //
     676           0 :         Array<Complex> gwts; Bool removeDegenerateAxis=false;
     677           0 :         griddedWeights.get(gwts, removeDegenerateAxis);
     678           0 :         resampleCFToGrid(gwts, vbs, vb);
     679           0 :       }
     680           0 :   };
     681             :   //
     682             :   //---------------------------------------------------------------
     683             :   //
     684       20933 :   void AWProjectWBFT::resampleDataToGrid(Array<DComplex>& griddedData_l,
     685             :                                          VBStore& vbs, const VisBuffer2& vb, 
     686             :                                          Bool& dopsf) 
     687             :   {
     688       20933 :     AWProjectFT::resampleDataToGrid(griddedData_l,vbs,vb,dopsf);
     689             :     
     690       20933 :     if (!avgPBReady_p)
     691             :       {
     692             :         //
     693             :         // Get a reference to the pixels of griddedWeights (a
     694             :         // TempImage!)
     695             :         //
     696        7150 :         Array<DComplex> gwts; Bool removeDegenerateAxis=false;
     697        7150 :         griddedWeights_D.get(gwts, removeDegenerateAxis);
     698        7150 :         resampleCFToGrid(gwts, vbs, vb);
     699        7150 :       }
     700       20933 :   };
     701             :     
     702             :     ////-----------------------------------------------------------------
     703             :     // SB: Is this functionality not served by the
     704             :     // ::resampleCFToGrid() method above?  Recommend that that be used
     705             :     // (or modifed as required) to ensure all mathematical terms are
     706             :     // included.
     707             :     //
     708           0 :  void  AWProjectWBFT::gridImgWeights(const VisBuffer2& vb)
     709             :  {
     710           0 :    if(avgPBReady_p)
     711           0 :      return;
     712             :    else
     713           0 :      avgPB_p=nullptr;  ///make sure it is not pointing to anything
     714             :    /*   // This does WEIGHTs gridding via the framework route 
     715             :    // (set ftmType and use ::put() for *all* gridding)
     716             :    ftmType_p=casa::refim::FTMachine::WEIGHT;
     717             :    put(vb,-1,false);
     718             :    return;
     719             :    */
     720             :    try
     721             :      {
     722           0 :        findConvFunction(*image, vb);
     723           0 :         if(avgPBReady_p)
     724           0 :           return;
     725             :      }
     726           0 :    catch(AipsError& x)
     727             :      {
     728           0 :        LogIO log_l(LogOrigin("AWProjectFT2", "put[R&D]"));
     729           0 :        log_l << x.getMesg() << LogIO::WARN;
     730           0 :        return;
     731           0 :      }
     732           0 :    Matrix<Float> imagingweight;
     733           0 :    getImagingWeight(imagingweight, vb);
     734           0 :    matchChannel(vb);
     735           0 :    Cube<Complex> data;
     736             :    //Fortran gridder need the flag as ints 
     737           0 :    Cube<Int> flags;
     738           0 :    Matrix<Float> elWeight;
     739             :    
     740           0 :    interpolateFrequencyTogrid(vb, imagingweight,data, flags , elWeight, FTMachine::PSF);
     741             :    //Matrix<Double> uvw(negateUV(vb));
     742           0 :    Matrix<Double> uvw;
     743           0 :    Vector<Double> dphase(vb.nRows());
     744           0 :    dphase=0.0;
     745           0 :    doUVWRotation_p=true;
     746           0 :    VBStore vbs;
     747           0 :    Vector<Int> gridShape = griddedData2.shape().asVector();
     748           0 :     ftmType_p=casa::refim::FTMachine::WEIGHT;
     749           0 :    setupVBStore(vbs,vb, elWeight,data,uvw,flags, dphase, True ,gridShape);
     750           0 :    if (useDoubleGrid_p){
     751           0 :         Array<DComplex> gwts; Bool removeDegenerateAxis=false;
     752           0 :         griddedWeights_D.get(gwts, removeDegenerateAxis);
     753           0 :         resampleCFToGrid(gwts, vbs, vb);
     754             :         
     755           0 :     }
     756             :    else{
     757           0 :      Array<Complex> gwts; Bool removeDegenerateAxis=false;
     758           0 :      griddedWeights.get(gwts, removeDegenerateAxis);
     759           0 :      resampleCFToGrid(gwts, vbs, vb);
     760             :      
     761           0 :    }
     762             :     
     763           0 :  }
     764             :   
     765          93 :   void AWProjectWBFT::setCFCache(CountedPtr<CFCache>& cfc, const Bool resetCFC) 
     766             :   {
     767          93 :     if (resetCFC) cfCache_p = cfc;
     768          93 :     if (!cfCache_p.null())
     769             :       {
     770          93 :         cfs2_p = CountedPtr<CFStore2>(&cfCache_p->memCache2_p[0],false);//new CFStore2;
     771          93 :         cfwts2_p =  CountedPtr<CFStore2>(&cfCache_p->memCacheWt2_p[0],false);//new CFStore2;
     772             :         
     773          93 :         avgPBReady_p=false;
     774             :       }
     775          93 :   }
     776             : 
     777             : } //# NAMESPACE CASA - END
     778             : };

Generated by: LCOV version 1.16