LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - GridFT.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 439 598 73.4 %
Date: 2025-12-19 19:56:21 Functions: 22 29 75.9 %

          Line data    Source code
       1             : //# GridFT.cc: Implementation of GridFT class
       2             : //# Copyright (C) 1997-2016
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : 
      28             : #include <msvis/MSVis/VisibilityIterator2.h>
      29             : #include <casacore/casa/Quanta/UnitMap.h>
      30             : #include <casacore/casa/Quanta/UnitVal.h>
      31             : #include <casacore/measures/Measures/Stokes.h>
      32             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      33             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      34             : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
      35             : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
      36             : #include <casacore/coordinates/Coordinates/Projection.h>
      37             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      38             : #include <casacore/casa/BasicSL/Constants.h>
      39             : #include <casacore/scimath/Mathematics/FFTServer.h>
      40             : #include <casacore/scimath/Mathematics/RigidVector.h>
      41             : #include <msvis/MSVis/StokesVector.h>
      42             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      43             : #include <synthesis/TransformMachines2/GridFT.h>
      44             : #include <synthesis/Utilities/FFT2D.h>
      45             : #include <msvis/MSVis/VisBuffer2.h>
      46             : #include <casacore/images/Images/ImageInterface.h>
      47             : #include <casacore/images/Images/PagedImage.h>
      48             : #include <casacore/casa/Containers/Block.h>
      49             : #include <casacore/casa/Containers/Record.h>
      50             : #include <casacore/casa/Arrays/ArrayLogical.h>
      51             : #include <casacore/casa/Arrays/ArrayMath.h>
      52             : #include <casacore/casa/Arrays/Array.h>
      53             : #include <casacore/casa/Arrays/MaskedArray.h>
      54             : #include <casacore/casa/Arrays/Vector.h>
      55             : #include <casacore/casa/Arrays/Matrix.h>
      56             : #include <casacore/casa/Arrays/Cube.h>
      57             : #include <casacore/casa/Arrays/MatrixIter.h>
      58             : #include <casacore/casa/BasicSL/String.h>
      59             : #include <casacore/casa/Utilities/Assert.h>
      60             : #include <casacore/casa/Exceptions/Error.h>
      61             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      62             : #include <casacore/measures/Measures/UVWMachine.h>
      63             : #include <casacore/lattices/Lattices/SubLattice.h>
      64             : #include <casacore/lattices/LRegions/LCBox.h>
      65             : #include <casacore/lattices/Lattices/LatticeCache.h>
      66             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      67             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      68             : #include <casacore/lattices/Lattices/LatticeStepper.h>
      69             : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
      70             : #include <casacore/casa/Utilities/CompositeNumber.h>
      71             : #include <casacore/casa/OS/Timer.h>
      72             : #include <sstream>
      73             : #ifdef _OPENMP
      74             : #include <omp.h>
      75             : #endif
      76             : 
      77             : using namespace casacore;
      78             : namespace casa { //# NAMESPACE CASA - BEGIN
      79             : namespace refim {//# namespace for imaging refactor
      80             : using namespace casacore;
      81             : using namespace casa;
      82             : using namespace casacore;
      83             : using namespace casa::refim;
      84             : 
      85           0 :   GridFT::GridFT() : FTMachine(), padding_p(1.0), imageCache(0), cachesize(1000000), tilesize(1000), gridder(0), isTiled(false), convType("SF"),
      86           0 :   maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
      87           0 :   usezero_p(false), noPadding_p(false), usePut2_p(false), 
      88           0 :                      machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0){
      89             : 
      90           0 :   }
      91          22 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType, Float padding,
      92          22 :                Bool usezero, Bool useDoublePrec)
      93          22 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize),
      94          22 :   gridder(0), isTiled(false), convType(iconvType),
      95          22 :   maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
      96          22 :   usezero_p(usezero), noPadding_p(false), usePut2_p(false), 
      97          44 :   machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
      98             : {
      99          22 :   useDoubleGrid_p=useDoublePrec;  
     100             :   //  peek=NULL;
     101          22 : }
     102             : 
     103        2534 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
     104        2534 :                MPosition mLocation, Float padding, Bool usezero, Bool useDoublePrec)
     105        2534 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
     106        2534 :   tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
     107        2534 :   offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false), 
     108        5068 :   usePut2_p(false), machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
     109             : {
     110        2534 :   mLocation_p=mLocation;
     111        2534 :   tangentSpecified_p=false;
     112        2534 :   useDoubleGrid_p=useDoublePrec;
     113             :   //  peek=NULL;
     114        2534 : }
     115             : 
     116           0 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
     117           0 :                MDirection mTangent, Float padding, Bool usezero, Bool useDoublePrec)
     118           0 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
     119           0 :   tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
     120           0 :   offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false), 
     121           0 :   usePut2_p(false), machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
     122             : {
     123           0 :   mTangent_p=mTangent;
     124           0 :   tangentSpecified_p=true;
     125           0 :   useDoubleGrid_p=useDoublePrec;
     126             :   //  peek=NULL;
     127           0 : }
     128             : 
     129           6 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
     130             :                MPosition mLocation, MDirection mTangent, Float padding,
     131           6 :                Bool usezero, Bool useDoublePrec)
     132           6 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
     133           6 :   tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
     134           6 :   offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false), 
     135          12 :   usePut2_p(false),machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
     136             : {
     137           6 :   mLocation_p=mLocation;
     138           6 :   mTangent_p=mTangent;
     139           6 :   tangentSpecified_p=true;
     140           6 :   useDoubleGrid_p=useDoublePrec;
     141             :   //  peek=NULL;
     142           6 : }
     143             : 
     144           0 : GridFT::GridFT(const RecordInterface& stateRec)
     145           0 : : FTMachine()
     146             : {
     147             :   // Construct from the input state record
     148           0 :   String error;
     149           0 :   if (!fromRecord(error, stateRec)) {
     150           0 :     throw (AipsError("Failed to create gridder: " + error));
     151             :   };
     152           0 :   timemass_p=0.0;
     153           0 :   timegrid_p=0.0;
     154           0 :   timedegrid_p=0.0;
     155             :   //  peek=NULL;
     156           0 : }
     157             : 
     158             : //---------------------------------------------------------------------- 
     159         267 : GridFT& GridFT::operator=(const GridFT& other)
     160             : {
     161         267 :   if(this!=&other) {
     162             :     //Do the base parameters
     163         267 :     FTMachine::operator=(other);
     164             :     
     165             :     //private params
     166         267 :     imageCache=other.imageCache;
     167         267 :     cachesize=other.cachesize;
     168         267 :     tilesize=other.tilesize;
     169         267 :     convType=other.convType;
     170         267 :     convType.upcase();
     171         267 :     uvScale.resize();
     172         267 :     uvOffset.resize();
     173         267 :     uvScale.assign(other.uvScale);
     174         267 :     uvOffset.assign(other.uvOffset);
     175         267 :     if(other.gridder==0)
     176         267 :       gridder=0;
     177             :     else{  
     178           0 :       gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     179           0 :                                                      uvScale, uvOffset,
     180           0 :                                                      convType);
     181             :     }
     182         267 :     convFunc_p.resize();
     183         267 :     convSupport_p=other.convSupport_p;
     184         267 :     convSampling_p=other.convSampling_p;
     185         267 :     convFunc_p=other.convFunc_p;
     186         267 :     isTiled=other.isTiled;
     187             :     //lattice=other.lattice;
     188         267 :     lattice.reset( );
     189         267 :     tilesize=other.tilesize;
     190         267 :     arrayLattice.reset( );
     191         267 :     maxAbsData=other.maxAbsData;
     192         267 :     centerLoc=other.centerLoc;
     193         267 :     offsetLoc=other.offsetLoc;
     194         267 :     padding_p=other.padding_p;
     195         267 :     usezero_p=other.usezero_p;
     196         267 :     noPadding_p=other.noPadding_p;      
     197         267 :     machineName_p="GridFT";
     198         267 :     timemass_p=0.0;
     199         267 :     timegrid_p=0.0;
     200             :     //    peek = other.peek;
     201             :   };
     202         267 :   return *this;
     203             : };
     204             : 
     205             : //----------------------------------------------------------------------
     206         267 : GridFT::GridFT(const GridFT& other) : FTMachine(), machineName_p("GridFT")
     207             : {
     208         267 :   operator=(other);
     209         267 : }
     210             : 
     211             : //-----------------------------------------------------------------------
     212         267 :   FTMachine* GridFT::cloneFTM(){
     213         267 :     return new GridFT(*this);
     214             :   }
     215             : 
     216             :   //===============================
     217        2197 :  Long GridFT::estimateRAM(const CountedPtr<SIImageStore>& imstor){
     218        2197 :    Long mem=FTMachine::estimateRAM(imstor);
     219        2197 :    mem=mem*padding_p*padding_p;
     220        2197 :    return mem;
     221             :   }
     222             : 
     223             : 
     224             :   //----------------------------------------------------------------------
     225        2952 : void GridFT::init() {
     226             : 
     227        2952 :   logIO() << LogOrigin("GridFT", "init")  << LogIO::NORMAL;
     228             : 
     229        2952 :   ok();
     230             :   // if (peek == NULL) 
     231             :   //   {
     232             :   //     // peek = new SynthesisAsyncPeek();
     233             :   //     // peek->reset();
     234             :   //     // peek->startThread();
     235             :   //   }
     236             : 
     237             :   /* hardwiring isTiled is false
     238             :   // Padding is possible only for non-tiled processing
     239             :   if((padding_p*padding_p*image->shape().product())>cachesize) {
     240             :     isTiled=true;
     241             :     nx    = image->shape()(0);
     242             :     ny    = image->shape()(1);
     243             :     npol  = image->shape()(2);
     244             :     nchan = image->shape()(3);
     245             :   }
     246             :   else {
     247             :   */
     248             :     // We are padding.
     249        2952 :     isTiled=false;
     250        2952 :     if(!noPadding_p && padding_p > 1.01){
     251        2930 :       CompositeNumber cn(uInt(image->shape()(0)*2));    
     252        2930 :       nx    = cn.nextLargerEven(Int(padding_p*Float(image->shape()(0))-0.5));
     253        2930 :       ny    = cn.nextLargerEven(Int(padding_p*Float(image->shape()(1))-0.5));
     254        2930 :     }
     255             :     else{
     256          22 :       nx    = image->shape()(0);
     257          22 :       ny    = image->shape()(1);
     258             :     }
     259        2952 :     npol  = image->shape()(2);
     260        2952 :     nchan = image->shape()(3);
     261             :     // }
     262             : 
     263        2952 :   sumWeight.resize(npol, nchan);
     264             : 
     265        2952 :   uvScale.resize(2);
     266        2952 :   uvScale(0)=(Float(nx)*image->coordinates().increment()(0)); 
     267        2952 :   uvScale(1)=(Float(ny)*image->coordinates().increment()(1)); 
     268        2952 :   uvOffset.resize(2);
     269        2952 :   uvOffset(0)=nx/2;
     270        2952 :   uvOffset(1)=ny/2;
     271             : 
     272             :   // Now set up the gridder. The possibilities are BOX and SF
     273        2952 :   if(gridder) delete gridder; gridder=0;
     274        2952 :   convType.upcase();
     275        5904 :   gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     276        2952 :                                                  uvScale, uvOffset,
     277        2952 :                                                  convType);
     278             : 
     279        2952 :   convFunc_p.resize();
     280        2952 :   convSupport_p=gridder->cSupport()(0);
     281        2952 :   convSampling_p=gridder->cSampling();
     282        2952 :   convFunc_p=gridder->cFunction();
     283             :   // Set up image cache needed for gridding. For BOX-car convolution
     284             :   // we can use non-overlapped tiles. Otherwise we need to use
     285             :   // overlapped tiles and additive gridding so that only increments
     286             :   // to a tile are written.
     287        2952 :   if(imageCache) delete imageCache; imageCache=0;
     288             : 
     289        2952 :   if(isTiled) {
     290           0 :     Float tileOverlap=0.5;
     291           0 :     if(convType=="BOX") {
     292           0 :       tileOverlap=0.0;
     293             :     }
     294             :     else {
     295           0 :       tileOverlap=0.5;
     296           0 :       tilesize=max(12,tilesize);
     297             :     }
     298           0 :     IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
     299           0 :     Vector<Float> tileOverlapVec(4);
     300           0 :     tileOverlapVec=0.0;
     301           0 :     tileOverlapVec(0)=tileOverlap;
     302           0 :     tileOverlapVec(1)=tileOverlap;
     303           0 :     Int tmpCacheVal=static_cast<Int>(cachesize);
     304           0 :     imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape, 
     305             :                                            tileOverlapVec,
     306           0 :                                            (tileOverlap>0.0));
     307             : 
     308           0 :   }
     309        2952 : }
     310             : 
     311             : // This is nasty, we should use CountedPointers here.
     312        5658 : GridFT::~GridFT() {
     313        2829 :   if(imageCache) delete imageCache; imageCache=0;
     314             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     315        2829 :   if(gridder) delete gridder; gridder=0;
     316        5658 : }
     317             : 
     318             : // Initialize for a transform from the Sky domain. This means that
     319             : // we grid-correct, and FFT the image
     320             : 
     321         785 : void GridFT::initializeToVis(ImageInterface<Complex>& iimage,
     322             :                              const vi::VisBuffer2& vb)
     323             : {
     324         785 :   image=&iimage;
     325         785 :   toVis_p=true;
     326             : 
     327         785 :   ok();
     328             : 
     329         785 :   init();
     330             :   //  peek->reset();
     331             :   // Initialize the maps for polarization and channel. These maps
     332             :   // translate visibility indices into image indices
     333         785 :   initMaps(vb);
     334             :     // Need to reset nx, ny for padding
     335             :   // Padding is possible only for non-tiled processing
     336             :   
     337             : 
     338             :   //cerr << "initialize to vis nx" << nx << "   " << ny <<  "  " << npol << " " << nchan << endl;
     339             : 
     340             :   //cerr << "image shape " << image->shape() << endl;
     341             : 
     342             :   // If we are memory-based then read the image in and create an
     343             :   // ArrayLattice otherwise just use the PagedImage
     344             :   /*if(isTiled) {
     345             :     lattice=std::shared_ptr<Lattice<Complex> >(image, false);
     346             :   }
     347             :   else {
     348             :      
     349             :   }*/
     350         785 :   prepGridForDegrid();
     351             : 
     352             :   //AlwaysAssert(lattice, AipsError);
     353             : 
     354             :  
     355             :     
     356         785 : }
     357             : 
     358         785 : void GridFT::prepGridForDegrid(){
     359         785 :   IPosition gridShape(4, nx, ny, npol, nchan);
     360         785 :   griddedData.resize(gridShape);
     361             :   //griddedData can be a reference of image data...if not using model col
     362             :   //hence using an undocumented feature of resize that if 
     363             :   //the size is the same as old data it is not changed.
     364             :   //if(!usePut2_p) griddedData.set(0);
     365         785 :   griddedData.set(Complex(0.0));
     366             : 
     367         785 :   IPosition stride(4, 1);
     368        1570 :   IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
     369        1570 :   IPosition trc(blc+image->shape()-stride);
     370             :   
     371         785 :   IPosition start(4, 0);
     372         785 :   griddedData(blc, trc) = image->getSlice(start, image->shape());
     373             :   
     374             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     375         785 :   arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
     376         785 :   lattice=arrayLattice;
     377             :   //logIO() << LogIO::DEBUGGING
     378             :   //      << "Starting grid correction and FFT of image" << LogIO::POST;
     379             : 
     380             :    // Do the Grid-correction. 
     381             :    {
     382         785 :      Vector<Complex> correction(nx);
     383         785 :      correction=Complex(1.0, 0.0);
     384             :      // Do the Grid-correction
     385         785 :      IPosition cursorShape(4, nx, 1, 1, 1);
     386         785 :      IPosition axisPath(4, 0, 1, 2, 3);
     387         785 :      LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
     388         785 :      LatticeIterator<Complex> lix(*lattice, lsx);
     389      555009 :      for(lix.reset();!lix.atEnd();lix++) {
     390      554224 :        gridder->correctX1D(correction, lix.position()(1));
     391      554224 :        lix.rwVectorCursor()/=correction;
     392             :      }
     393         785 :    }
     394         785 :    image->clearCache();
     395             :    // Now do the FFT2D in place
     396             :    //LatticeFFT::cfft2d(*lattice);
     397         785 :    ft_p.c2cFFT(*lattice);
     398             :    //logIO() << LogIO::DEBUGGING
     399             :    //       << "Finished grid correction and FFT of image" << LogIO::POST;
     400             :     
     401         785 : }
     402             : 
     403             : 
     404         785 : void GridFT::finalizeToVis()
     405             : {
     406             : 
     407         785 :   logIO() << LogOrigin("GridFT", "finalizeToVis")  << LogIO::NORMAL;
     408         785 :   logIO() <<LogIO::NORMAL2<< "Time to degrid " << timedegrid_p <<LogIO::POST;
     409         785 :   timedegrid_p=0.0;
     410             : 
     411         785 :  if(arrayLattice) arrayLattice=nullptr;
     412         785 :   if(lattice) lattice=nullptr;
     413         785 :   griddedData.resize();
     414         785 :   if(isTiled) {
     415             : 
     416             :    
     417             : 
     418           0 :     AlwaysAssert(imageCache, AipsError);
     419           0 :     AlwaysAssert(image, AipsError);
     420           0 :     ostringstream o;
     421           0 :     imageCache->flush();
     422           0 :     imageCache->showCacheStatistics(o);
     423           0 :     logIO() << o.str() << LogIO::POST;
     424           0 :   }
     425         785 : }
     426             : 
     427             : 
     428             : // Initialize the FFT to the Sky. Here we have to setup and initialize the
     429             : // grid. 
     430        2167 : void GridFT::initializeToSky(ImageInterface<Complex>& iimage,
     431             :                              Matrix<Float>& weight, const vi::VisBuffer2& vb)
     432             : {
     433             :   // image always points to the image
     434        2167 :   image=&iimage;
     435        2167 :   toVis_p=false;
     436             : 
     437        2167 :   init();
     438             : 
     439             :   // Initialize the maps for polarization and channel. These maps
     440             :   // translate visibility indices into image indices
     441        2167 :   initMaps(vb);
     442             : 
     443             : 
     444             :   
     445        2167 :   sumWeight=0.0;
     446        2167 :   weight.resize(sumWeight.shape());
     447        2167 :   weight=0.0;
     448             : 
     449             :  
     450        2167 :   IPosition gridShape(4, nx, ny, npol, nchan);
     451        2167 :     if( !useDoubleGrid_p )
     452             :       {
     453          22 :         griddedData.resize(gridShape);
     454          22 :         griddedData=Complex(0.0);
     455             :       }
     456             :     else{
     457             :       
     458        2145 :       griddedData2.resize(gridShape);
     459        2145 :       griddedData2=DComplex(0.0);
     460             :     }
     461        2167 :   image->clearCache();
     462             :   //iimage.get(griddedData, false);
     463             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     464             :   
     465             :   
     466             :   //AlwaysAssert(lattice, AipsError);
     467        2167 : }
     468             : 
     469             : 
     470             : 
     471        2166 : void GridFT::finalizeToSky()
     472             : {  
     473             :   //AlwaysAssert(lattice, AipsError);
     474             :   // Now we flush the cache and report statistics
     475             :   // For memory based, we don't write anything out yet.
     476        2166 :   logIO() << LogOrigin("GridFT", "finalizeToSky")  << LogIO::NORMAL;
     477        2166 :   logIO()<<LogIO::NORMAL2 <<"Time to massage data " << timemass_p << LogIO::POST;
     478        2166 :   logIO()<< LogIO::NORMAL2 <<"Time to grid data " << timegrid_p << LogIO::POST;
     479        2166 :   timemass_p=0.0;
     480        2166 :   timegrid_p=0.0;
     481        2166 :   if(isTiled) {
     482             :   
     483             : 
     484           0 :     AlwaysAssert(image, AipsError);
     485           0 :     AlwaysAssert(imageCache, AipsError);
     486           0 :     imageCache->flush();
     487           0 :     ostringstream o;
     488           0 :     imageCache->showCacheStatistics(o);
     489           0 :     logIO() << o.str() << LogIO::POST;
     490           0 :   }
     491             :   //  peek->terminate();
     492             :   //  peek->reset();
     493        2166 : }
     494             : 
     495             : 
     496             : 
     497           0 : Array<Complex>* GridFT::getDataPointer(const IPosition& centerLoc2D,
     498             :                                        Bool readonly) {
     499             :   Array<Complex>* result;
     500             :   // Is tiled: get tiles and set up offsets
     501           0 :   centerLoc(0)=centerLoc2D(0);
     502           0 :   centerLoc(1)=centerLoc2D(1);
     503           0 :   result=&imageCache->tile(offsetLoc,centerLoc, readonly);
     504           0 :   gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
     505           0 :   return result;
     506             : }
     507             : 
     508             : #define NEED_UNDERSCORES
     509             : #if defined(NEED_UNDERSCORES)
     510             : #define ggrid ggrid_
     511             : #define dgrid dgrid_
     512             : #define ggrids ggrids_
     513             : #define sectggridd sectggridd_
     514             : #define sectggrids sectggrids_
     515             : #define sectdgrid sectdgrid_
     516             : #define locuvw locuvw_
     517             : #endif
     518             : 
     519             : extern "C" { 
     520             :   void locuvw(const Double*, const Double*, const Double*, const Int*, const Double*, const Double*, const Int*, 
     521             :               Int*, Int*, Complex*, const Int*, const Int*, const Double*);
     522             :    void ggrid(Double*,
     523             :                 Double*,
     524             :                 const Complex*,
     525             :                 Int*,
     526             :                 Int*,
     527             :                 Int*,
     528             :                 const Int*,
     529             :                 const Int*,
     530             :                 const Float*,
     531             :                 Int*,
     532             :                 Int*,
     533             :                 Double*,
     534             :                 Double*,
     535             :                 DComplex*,
     536             :                 Int*,
     537             :                 Int*,
     538             :                 Int *,
     539             :                 Int *,
     540             :                 const Double*,
     541             :                 const Double*,
     542             :                 Int*,
     543             :                 Int*,
     544             :                 Double*,
     545             :                 Int*,
     546             :                 Int*,
     547             :                 Double*);
     548             :   void sectggridd(const Complex*,
     549             :                 const Int*,
     550             :                 const Int*,
     551             :                 const Int*,
     552             :                 const Int*,
     553             :                 const Int*,
     554             :                 const Float*,
     555             :                 const Int*,
     556             :                 DComplex*,
     557             :                 const Int*,
     558             :                 const Int*,
     559             :                 const Int *,
     560             :                 const Int *,
     561             :                   //support
     562             :                 const Int*,
     563             :                 const Int*,
     564             :                 const Double*,
     565             :                 const Int*,
     566             :                 const Int*,
     567             :                   Double*,
     568             :                   const Int*,
     569             :                   const Int*, 
     570             :                   const Int*,
     571             :                   const Int*,
     572             :                   const Int*, 
     573             :                   const Int*,
     574             :                   //loc, off, phasor
     575             :                   const Int*,
     576             :                   const Int*,
     577             :                   const Complex*);
     578             :   //single precision gridder
     579             :   void sectggrids(const Complex*,
     580             :                 const Int*,
     581             :                 const Int*,
     582             :                 const Int*,
     583             :                 const Int*,
     584             :                 const Int*,
     585             :                 const Float*,
     586             :                 const Int*,
     587             :                 Complex*,
     588             :                 const Int*,
     589             :                 const Int*,
     590             :                 const Int *,
     591             :                 const Int *,
     592             :                 const Int*,
     593             :                 const Int*,
     594             :                 const Double*,
     595             :                 const Int*,
     596             :                 const Int*,
     597             :                   Double*,
     598             :                   const Int*,
     599             :                   const Int*, 
     600             :                   const Int*,
     601             :                   const Int*,
     602             :                   const Int*, 
     603             :                   const Int*,
     604             :                   //loc, off, phasor
     605             :                   const Int*,
     606             :                   const Int*,
     607             :                   const Complex*);
     608             :   void ggrids(Double*,
     609             :                 Double*,
     610             :                 const Complex*,
     611             :                 Int*,
     612             :                 Int*,
     613             :                 Int*,
     614             :                 const Int*,
     615             :                 const Int*,
     616             :                 const Float*,
     617             :                 Int*,
     618             :                 Int*,
     619             :                 Double*,
     620             :                 Double*,
     621             :                 Complex*,
     622             :                 Int*,
     623             :                 Int*,
     624             :                 Int *,
     625             :                 Int *,
     626             :                 const Double*,
     627             :                 const Double*,
     628             :                 Int*,
     629             :                 Int*,
     630             :                 Double*,
     631             :                 Int*,
     632             :                 Int*,
     633             :                 Double*);
     634             : 
     635             :    void dgrid(Double*,
     636             :                 Double*,
     637             :                 Complex*,
     638             :                 Int*,
     639             :                 Int*,
     640             :                 const Int*,
     641             :                 const Int*,
     642             :                 Int*,
     643             :                 Int*,
     644             :                 Double*,
     645             :                 Double*,
     646             :                 const Complex*,
     647             :                 Int*,
     648             :                 Int*,
     649             :                 Int *,
     650             :                 Int *,
     651             :                 const Double*,
     652             :                 const Double*,
     653             :                 Int*,
     654             :                 Int*,
     655             :                 Double*,
     656             :                 Int*,
     657             :                 Int*);
     658             : 
     659             :   void sectdgrid(Complex*,
     660             :                 const Int*,
     661             :                 const Int*,
     662             :                 const Int*,
     663             :                 const Int*,
     664             :                 const Int*,
     665             :                 const Complex*,
     666             :                 const Int*,
     667             :                 const Int*,
     668             :                 const Int *,
     669             :                 const Int *,
     670             :                  //support
     671             :                 const Int*,
     672             :                 const Int*,
     673             :                 const Double*,
     674             :                 const Int*,
     675             :                  const Int*,
     676             :                  //rbeg, rend, loc, off, phasor
     677             :                  const Int*,
     678             :                  const Int*,
     679             :                  const Int*,
     680             :                  const Int*,
     681             :                  const Complex*);
     682             : }
     683      530188 : void GridFT::put(const vi::VisBuffer2& vb, Int row, Bool dopsf,
     684             :                  FTMachine::Type type)
     685             : {
     686             : 
     687      530188 :   gridOk(convSupport_p);
     688             :   //  peek->setVBPtr(&vb);
     689             : 
     690             :   //Check if ms has changed then cache new spw and chan selection
     691             :   //if(vb.isNewMs())
     692             :   //  matchAllSpwChans(vb);
     693             :   
     694             :   //Here we redo the match or use previous match
     695             :   
     696             :   //Channel matching for the actual spectral window of buffer
     697             :   //if(doConversion_p[vb.spectralWindows()[0]]){
     698      530187 :   matchChannel(vb);
     699             :   //}
     700             :   //else{
     701             :   //  chanMap.resize();
     702             :   //  chanMap=multiChanMap_p[vb.spectralWindows()[0]];
     703             :   //}
     704             : 
     705             :   //No point in reading data if its not matching in frequency
     706      530187 :   if(max(chanMap)==-1)
     707             :     {
     708             :       //      peek->reset();
     709         136 :       return;
     710             :     }
     711             : 
     712      530051 :   Timer tim;
     713      530051 :   tim.mark();
     714             : 
     715             :   //const Matrix<Float> *imagingweight;
     716             :   //imagingweight=&(vb.imagingWeight());
     717      530051 :   Matrix<Float> imagingweight;
     718      530051 :   getImagingWeight(imagingweight, vb);
     719             :   
     720      530051 :   if(dopsf) {type=FTMachine::PSF;}
     721             : 
     722      530051 :   Cube<Complex> data;
     723             :   //Fortran gridder need the flag as ints 
     724      530051 :   Cube<Int> flags;
     725      530051 :   Matrix<Float> elWeight;
     726      530051 :   interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
     727             : 
     728             : 
     729             :   Bool iswgtCopy;
     730             :   const Float *wgtStorage;
     731      530051 :   wgtStorage=elWeight.getStorage(iswgtCopy);
     732             :   
     733             :   Bool isCopy;
     734             :   const Complex *datStorage;
     735      530051 :   if(!dopsf)
     736      323698 :     datStorage=data.getStorage(isCopy);
     737             :   else
     738      206353 :     datStorage=0;
     739             :   // If row is -1 then we pass through all rows
     740             :   Int startRow, endRow, nRow;
     741      530051 :   if (row==-1) {
     742      530051 :     nRow=vb.nRows();
     743      530051 :     startRow=0;
     744      530051 :     endRow=nRow-1;
     745             :   } else {
     746           0 :     nRow=1;
     747           0 :     startRow=row;
     748           0 :     endRow=row;
     749             :   }
     750             : 
     751             :   //cerr << "nRow " << nRow << endl;
     752             : 
     753             : 
     754             :   // Get the uvws in a form that Fortran can use and do that
     755             :   // necessary phase rotation. On a Pentium Pro 200 MHz
     756             :   // when null, this step takes about 50us per uvw point. This
     757             :   // is just barely noticeable for Stokes I continuum and
     758             :   // irrelevant for other cases.
     759             :  
     760             :   Bool del; 
     761             :   //    IPosition s(flags.shape());
     762      530051 :   const IPosition &fs=flags.shape();
     763      530051 :   std::vector<Int> s(fs.begin(),fs.end());
     764      530051 :   Int nvispol=s[0];
     765      530051 :   Int nvischan=s[1];
     766      530051 :   Int nvisrow=s[2];
     767      530051 :   Matrix<Double> uvw(negateUV(vb));
     768             : 
     769      530051 :   Vector<Double> dphase(vb.nRows());
     770      530051 :   Cube<Int> loc(2, nvischan, nRow);
     771      530051 :   Cube<Int> off(2, nvischan, nRow);
     772      530051 :   Matrix<Complex> phasor(nvischan, nRow);
     773      530051 :   Int csamp=convSampling_p;
     774      530051 :   dphase=0.0;
     775             :   
     776      530051 :   timemass_p +=tim.real();
     777      530051 :   tim.mark(); 
     778      530051 :   rotateUVW(uvw, dphase, vb);
     779      530051 :   refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
     780             :   Bool delphase;
     781      530051 :   Complex * phasorstor=phasor.getStorage(delphase);
     782      530051 :   const Double * visfreqstor=interpVisFreq_p.getStorage(del);
     783      530051 :   const Double * scalestor=uvScale.getStorage(del);
     784      530051 :   const Double * offsetstor=uvOffset.getStorage(del);
     785      530051 :   const Double* uvstor= uvw.getStorage(del);
     786      530051 :   Int * locstor=loc.getStorage(del);
     787      530051 :   Int * offstor=off.getStorage(del);
     788      530051 :   const Double *dpstor=dphase.getStorage(del);
     789             :   //Vector<Double> f1=interpVisFreq_p.copy();
     790      530051 :   Int nvchan=nvischan;
     791             :   Int irow;
     792      530051 :   Double cinv=Double(1.0)/C::c;
     793      530051 :   Int dow=0;
     794      530051 :   Int nth=1;
     795             : #ifdef _OPENMP
     796      530051 :   if(numthreads_p >0){
     797           0 :     nth=min(numthreads_p, omp_get_max_threads());
     798             :   }
     799             :   else{   
     800      530051 :     nth= omp_get_max_threads();
     801             :   }
     802             :   //nth=min(4,nth);
     803             : #endif
     804             :   
     805             : 
     806      530051 : #pragma omp parallel default(none) private(irow) firstprivate(visfreqstor, nvchan, scalestor, offsetstor, csamp, phasorstor, uvstor, locstor, offstor, dpstor, cinv, dow) shared(startRow, endRow) num_threads(nth)
     807             :   {
     808             : #pragma omp for schedule(dynamic)
     809             :   for (irow=startRow; irow<=endRow; ++irow){
     810             :     //locateuvw(uvstor,dpstor, visfreqstor, nvchan, scalestor, offsetstor, csamp, 
     811             :     //        locstor, 
     812             :     //        offstor, phasorstor, irow);
     813             :     locuvw(uvstor, dpstor, visfreqstor, &nvchan, scalestor, offsetstor, &csamp, locstor, offstor, phasorstor, &irow, &dow, &cinv); 
     814             :   }  
     815             : 
     816             :   }//end pragma parallel
     817             :   // Take care of translation of Bools to Integer
     818      530051 :   Int idopsf=0;
     819      530051 :   if(dopsf) idopsf=1;
     820             : 
     821             :   //////TESTOO
     822             :   //ofstream myfile;
     823             :   //myfile.open ("putLoc.txt", ios::out | ios::app | ios::ate );
     824             :   //myfile << vb.rowIds()(0) << " uv " << uvw.column(0) << " loc " << loc(0,0,0) << ", " << loc(1,0,0) << "\n" << endl;
     825             :   //myfile.close();
     826             :   ///////////////
     827             : 
     828             :   
     829             : 
     830      530051 :   Vector<Int> rowFlags(vb.nRows());
     831      530051 :   rowFlags=0;
     832      530051 :   rowFlags(vb.flagRow())=true;
     833      530051 :   if(!usezero_p) {
     834   177541900 :     for (Int rownr=startRow; rownr<=endRow; rownr++) {
     835   177017863 :       if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
     836             :     }
     837             :   }
     838             :   
     839             :   /////////////Some extra stuff for openmp
     840             : 
     841             :   Int ixsub, iysub, icounter;
     842      530051 :   Int csupp=convSupport_p;
     843             :   
     844      530051 :   const Double * convfuncstor=(convFunc_p).getStorage(del);
     845             :   
     846             :   // cerr <<"Poffset " << min(off) << "  " << max(off) << " length " << gridder->cFunction().shape() << endl;
     847             :   
     848             : 
     849             : 
     850      530051 :   ixsub=1;
     851      530051 :   iysub=1; 
     852      530051 :   if (nth >4){
     853      249770 :     ixsub=8;
     854      249770 :     iysub=8; 
     855             :   }
     856      280281 :   else if(nth >1) {
     857      280281 :      ixsub=2;
     858      280281 :      iysub=2; 
     859             :   }
     860             : 
     861             :   
     862      530051 :   Int rbeg=startRow+1;
     863      530051 :   Int rend=endRow+1;
     864      530051 :   Block<Matrix<Double> > sumwgt(ixsub*iysub);
     865    17636455 :   for (icounter=0; icounter < ixsub*iysub; ++icounter){
     866    17106404 :     sumwgt[icounter].resize(sumWeight.shape());
     867    17106404 :     sumwgt[icounter].set(0.0);
     868             :   }
     869      530051 :  if(doneThreadPartition_p < 0){
     870        1200 :     xsect_p.resize(ixsub*iysub);
     871        1200 :     ysect_p.resize(ixsub*iysub);
     872        1200 :     nxsect_p.resize(ixsub*iysub);
     873        1200 :     nysect_p.resize(ixsub*iysub);
     874       37260 :     for (icounter=0; icounter < ixsub*iysub; ++icounter){
     875       36060 :       findGridSector(nx, ny, ixsub, iysub, 0, 0, icounter, xsect_p(icounter), ysect_p(icounter), nxsect_p(icounter), nysect_p(icounter), true);
     876             :     }
     877             :   } 
     878      530051 :  Vector<Int> xsect, ysect, nxsect, nysect;
     879      530051 :  xsect=xsect_p; ysect=ysect_p; nxsect=nxsect_p; nysect=nysect_p;
     880      530051 :   const Int* pmapstor=polMap.getStorage(del);
     881      530051 :   const Int *cmapstor=chanMap.getStorage(del);
     882      530051 :   Int nc=nchan;
     883      530051 :   Int np=npol;
     884      530051 :   Int nxp=nx;
     885      530051 :   Int nyp=ny;
     886      530051 :   const Int * flagstor=flags.getStorage(del);
     887      530051 :   const Int * rowflagstor=rowFlags.getStorage(del);
     888             :   ////////////////////////
     889             : 
     890             :   Bool gridcopy;
     891      530051 :   if(useDoubleGrid_p){
     892      524037 :     DComplex *gridstor=griddedData2.getStorage(gridcopy);
     893      524037 : #pragma omp parallel default(none) private(icounter, del) firstprivate(idopsf, datStorage, wgtStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc,ixsub, iysub, rend, rbeg, csamp, csupp, nvispol, nvischan, nvisrow, phasorstor, locstor, offstor,  xsect, ysect, nxsect, nysect) shared(sumwgt) num_threads(nth)
     894             :   
     895             :   {
     896             :     //cerr << "numthreads " << omp_get_num_threads() << endl;
     897             : #pragma omp for schedule(dynamic) 
     898             :     for(icounter=0; icounter < ixsub*iysub; ++icounter){
     899             :       //cerr << "thread id " << omp_get_thread_num() << endl;
     900             :       Int x0=xsect(icounter);
     901             :       Int y0=ysect(icounter);
     902             :       Int nxsub=nxsect(icounter);
     903             :       Int nysub=nysect(icounter);
     904             :      
     905             :       sectggridd(datStorage,
     906             :           &nvispol,
     907             :           &nvischan,
     908             :           &idopsf,
     909             :           flagstor,
     910             :           rowflagstor,
     911             :           wgtStorage,
     912             :           &nvisrow,
     913             :           gridstor,
     914             :           &nxp,
     915             :           &nyp,
     916             :           &np,
     917             :           &nc,
     918             :           &csupp,
     919             :            &csamp,
     920             :           convfuncstor,
     921             :           cmapstor,
     922             :           pmapstor,
     923             :          (sumwgt[icounter]).getStorage(del),
     924             :                  &x0, &y0, &nxsub, &nysub, &rbeg, &rend, locstor, offstor,
     925             :                  phasorstor);
     926             :     }//end for
     927             :   }// end pragma parallel
     928    17577585 :   for (icounter=0; icounter < ixsub*iysub; ++icounter){
     929    17053548 :       sumWeight=sumWeight+sumwgt[icounter];
     930             :   }
     931             :   //phasor.putStorage(phasorstor, delphase); 
     932      524037 :   griddedData2.putStorage(gridstor, gridcopy);
     933      524037 :   if(dopsf && (nth >4))
     934      102130 :     tweakGridSector(nx, ny, ixsub, iysub);
     935             :   }
     936             :   else{
     937        6014 :     Complex *gridstor=griddedData.getStorage(gridcopy);
     938        6014 : #pragma omp parallel default(none) private(icounter, del) firstprivate(idopsf, datStorage, wgtStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc,ixsub, iysub, rend, rbeg, csamp, csupp, nvispol, nvischan, nvisrow, phasorstor, locstor, offstor, xsect, ysect, nxsect, nysect) shared(sumwgt) num_threads(ixsub*iysub)
     939             :     {
     940             :       //cerr << "numthreads " << omp_get_num_threads() << endl;
     941             : #pragma omp for schedule(dynamic)
     942             : 
     943             :       for(icounter=0; icounter < ixsub*iysub; ++icounter){
     944             :         //cerr << "thread id " << omp_get_thread_num() << endl;
     945             :         Int x0=xsect(icounter);
     946             :         Int y0=ysect(icounter);
     947             :         Int nxsub=nxsect(icounter);
     948             :         Int nysub=nysect(icounter);
     949             : 
     950             : 
     951             :         
     952             :         //cerr << "x0 " << x0 << " y0 " << y0 << " nxsub " << nxsub << " nysub " << nysub << endl;
     953             :         sectggrids(datStorage,
     954             :                    &nvispol,
     955             :                    &nvischan,
     956             :                    &idopsf,
     957             :                    flagstor,
     958             :                    rowflagstor,
     959             :                    wgtStorage,
     960             :                    &nvisrow,
     961             :                    gridstor,
     962             :                    &nxp,
     963             :                    &nyp,
     964             :                    &np,
     965             :                    &nc,
     966             :                    &csupp,
     967             :                    &csamp,
     968             :                    convfuncstor,
     969             :                    cmapstor,
     970             :                    pmapstor,
     971             :                    (sumwgt[icounter]).getStorage(del),
     972             :                    &x0, &y0, &nxsub, &nysub, &rbeg, &rend, locstor, offstor,
     973             :                    phasorstor);
     974             :       }//end for
     975             :   }// end pragma parallel
     976       58870 :     for (icounter=0; icounter < ixsub*iysub; ++icounter){
     977       52856 :       sumWeight=sumWeight+sumwgt[icounter];
     978             :     }
     979             :     
     980        6014 :     griddedData.putStorage(gridstor, gridcopy);
     981        6014 :     if(dopsf && (nth > 4))
     982         480 :       tweakGridSector(nx, ny, ixsub, iysub);
     983             :   }
     984             :   // cerr << "sunweight " << sumWeight << endl;
     985             : 
     986      530051 :   timegrid_p+=tim.real();
     987             :   
     988      530051 :   if(!dopsf)
     989      323698 :     data.freeStorage(datStorage, isCopy);
     990      530051 :   elWeight.freeStorage(wgtStorage,iswgtCopy);
     991             :   
     992             :   //  peek->reset();
     993      530051 : }
     994             : 
     995          22 : void GridFT::modifyConvFunc(const Vector<Double>& convFunc, Int convSupport, Int convSampling){
     996          22 :   convFunc_p.resize();
     997          22 :   convFunc_p=convFunc;
     998          22 :   convSupport_p=convSupport;
     999          22 :   convSampling_p=convSampling;
    1000             : 
    1001          22 : } 
    1002             : 
    1003      164612 : void GridFT::get(vi::VisBuffer2& vb, Int row)
    1004             : {
    1005             : 
    1006      164612 :   gridOk(convSupport_p);
    1007             :   // If row is -1 then we pass through all rows
    1008             :   Int startRow, endRow, nRow;
    1009      164612 :   if (row < 0) {
    1010      164612 :     nRow=vb.nRows();
    1011      164612 :     startRow=0;
    1012      164612 :     endRow=nRow-1;
    1013             :     //unnecessary zeroing
    1014             :     //vb.modelVisCube()=Complex(0.0,0.0);
    1015             :   } else {
    1016           0 :     nRow=1;
    1017           0 :     startRow=row;
    1018           0 :     endRow=row;
    1019             :     //unnecessary zeroing
    1020             :     //vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
    1021             :   }
    1022             : 
    1023             : 
    1024             : ///Channel matching for the actual spectral window of buffer
    1025      164612 :     matchChannel(vb);
    1026             :   
    1027             :   
    1028             :     //cerr << "GETchanMap " << chanMap << endl;
    1029             :   //No point in reading data if its not matching in frequency
    1030      164612 :   if(max(chanMap)==-1)
    1031          58 :     return;
    1032             : 
    1033             : 
    1034             : 
    1035             :   // Get the uvws in a form that Fortran can use
    1036      164554 :   Matrix<Double> uvw(negateUV(vb));
    1037      164554 :   Vector<Double> dphase(vb.nRows());
    1038      164554 :   dphase=0.0;
    1039      164554 :   rotateUVW(uvw, dphase, vb);
    1040      164554 :   refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
    1041             : 
    1042             :   
    1043             : 
    1044             :   //Check if ms has changed then cache new spw and chan selection
    1045             :   //if(vb.isNewMs())
    1046             :   //  matchAllSpwChans(vb);
    1047             : 
    1048             : 
    1049             :   //Here we redo the match or use previous match
    1050             :   
    1051             :   
    1052      164554 :   Cube<Complex> data;
    1053      164554 :   Cube<Int> flags;
    1054      164554 :   getInterpolateArrays(vb, data, flags);
    1055             : 
    1056             :   //cerr << "max min data " << max(griddedData) << " " << min(griddedData) << "  flags  " << max(flags) << "    " << min(flags) << endl;  
    1057             : 
    1058             :   //    IPosition s(data.shape());
    1059      164554 :   Int nvp=data.shape()(0);
    1060      164554 :   Int nvc=data.shape()(1);
    1061      164554 :   Int nvisrow=data.shape()(2);
    1062             :     
    1063             : 
    1064             :   //cerr << "get flags " << min(flags) << "  " << max(flags) << endl;
    1065             :   Complex *datStorage;
    1066             :   Bool isCopy;
    1067      164554 :   datStorage=data.getStorage(isCopy);
    1068             :   
    1069             :   ///
    1070      164554 :   Cube<Int> loc(2, nvc, nvisrow);
    1071      164554 :   Cube<Int> off(2, nvc, nRow);
    1072      164554 :   Matrix<Complex> phasor(nvc, nRow);
    1073      164554 :   Int csamp=convSampling_p;
    1074             :   Bool delphase;
    1075             :   Bool del;
    1076      164554 :   Complex * phasorstor=phasor.getStorage(delphase);
    1077      164554 :   const Double * visfreqstor=interpVisFreq_p.getStorage(del);
    1078      164554 :   const Double * scalestor=uvScale.getStorage(del);
    1079      164554 :   const Double * offsetstor=uvOffset.getStorage(del);
    1080      164554 :   const Double* uvstor= uvw.getStorage(del);
    1081      164554 :   Int * locstor=loc.getStorage(del);
    1082      164554 :   Int * offstor=off.getStorage(del);
    1083      164554 :   const Double *dpstor=dphase.getStorage(del);
    1084             :   //Vector<Double> f1=interpVisFreq_p.copy();
    1085      164554 :   Int nvchan=nvc;
    1086             :   Int irow;
    1087      164554 :   Double cinv=Double(1.0)/C::c;
    1088      164554 :   Int dow=0;
    1089      164554 :   Int nth=1;
    1090             : #ifdef _OPENMP
    1091      164554 :   if(numthreads_p >0){
    1092           0 :     nth=min(numthreads_p, omp_get_max_threads());
    1093             :   }
    1094             :   else{   
    1095      164554 :     nth= omp_get_max_threads();
    1096             :   }
    1097             :   //nth=min(4,nth);
    1098             : #endif
    1099             : 
    1100             : 
    1101      164554 : #pragma omp parallel default(none) private(irow) firstprivate(visfreqstor, nvchan, scalestor, offsetstor, csamp, phasorstor, uvstor, locstor, offstor, dpstor, cinv, dow) shared(startRow, endRow) num_threads(nth) 
    1102             : 
    1103             :   {
    1104             : #pragma omp for schedule(dynamic)
    1105             :   for (irow=startRow; irow<=endRow; ++irow){
    1106             :     //locateuvw(uvstor,dpstor, visfreqstor, nvchan, scalestor, offsetstor, csamp, 
    1107             :     //        locstor, 
    1108             :     //        offstor, phasorstor, irow);
    1109             :     
    1110             :     locuvw(uvstor, dpstor, visfreqstor, &nvchan, scalestor, offsetstor, &csamp, locstor, offstor, phasorstor, &irow, &dow, &cinv);
    1111             :   }  
    1112             : 
    1113             :   }//end pragma parallel
    1114             : 
    1115      164554 :   Int rbeg=startRow+1;
    1116      164554 :   Int rend=endRow+1;
    1117             : 
    1118             : 
    1119      164554 :   Vector<Int> rowFlags(vb.nRows());
    1120      164554 :   rowFlags=0;
    1121      164554 :   rowFlags(vb.flagRow())=true;
    1122             :   //cerr << "rowFlags " << rowFlags << endl;
    1123      164554 :   if(!usezero_p) {
    1124    56762618 :     for (Int rownr=startRow; rownr<=endRow; rownr++) {
    1125    56598064 :       if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
    1126             :     }
    1127             :   }
    1128             : 
    1129             : 
    1130             :   //cerr <<"offset " << min(off) << "  " <<max(off) << " length " << gridder->cFunction().shape() << endl;
    1131             : 
    1132             :   {
    1133             :     Bool delgrid;
    1134      164554 :     const Complex* gridstor=griddedData.getStorage(delgrid);
    1135      164554 :     const Double * convfuncstor=(convFunc_p).getStorage(del);
    1136             :     
    1137      164554 :     const Int* pmapstor=polMap.getStorage(del);
    1138      164554 :     const Int *cmapstor=chanMap.getStorage(del);
    1139      164554 :     Int nc=nchan;
    1140      164554 :     Int np=npol;
    1141      164554 :     Int nxp=nx;
    1142      164554 :     Int nyp=ny;
    1143      164554 :     Int csupp=convSupport_p;
    1144      164554 :     const Int * flagstor=flags.getStorage(del);
    1145      164554 :     const Int * rowflagstor=rowFlags.getStorage(del);
    1146             : 
    1147             : 
    1148      164554 :     Int npart=nth;
    1149             :     
    1150             : 
    1151      164554 :     Int ix=0;
    1152      164554 : #pragma omp parallel default(none) private(ix, rbeg, rend) firstprivate(datStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc, csamp, csupp, nvp, nvc, nvisrow, phasorstor, locstor, offstor) shared(npart) num_threads(npart)
    1153             :     { 
    1154             : #pragma omp for schedule(dynamic) 
    1155             :       for (ix=0; ix< npart; ++ix){
    1156             :         rbeg=ix*(nvisrow/npart)+1;
    1157             :         rend=(ix != (npart-1)) ? (rbeg+(nvisrow/npart)-1) : (rbeg+(nvisrow/npart)+nvisrow%npart-1) ;
    1158             :         //cerr << "rbeg " << rbeg << " rend " << rend << "  " << nvisrow << endl;
    1159             :         
    1160             :         sectdgrid(datStorage,
    1161             :                   &nvp,
    1162             :                   &nvc,
    1163             :                   flagstor,
    1164             :                   rowflagstor,
    1165             :                   &nvisrow,
    1166             :                   gridstor,
    1167             :                   &nxp,
    1168             :                   &nyp,
    1169             :                   &np,
    1170             :                   &nc,
    1171             :                   &csupp,
    1172             :                   &csamp,
    1173             :                   convfuncstor,
    1174             :                   cmapstor,
    1175             :                   pmapstor,
    1176             :                   &rbeg, &rend, locstor, offstor, phasorstor);
    1177             :       }//end pragma parallel
    1178             :     }
    1179      164554 :     data.putStorage(datStorage, isCopy);
    1180      164554 :     griddedData.freeStorage(gridstor, delgrid);
    1181             :     //cerr << "Get min max " << min(data) << "   " << max(data) << endl;
    1182             :   }
    1183      164554 :   interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
    1184             : 
    1185      164554 : }
    1186             : 
    1187             : 
    1188             : 
    1189             : // Finalize the FFT to the Sky. Here we actually do the FFT and
    1190             : // return the resulting image
    1191        2144 : ImageInterface<Complex>& GridFT::getImage(Matrix<Float>& weights, Bool normalize) 
    1192             : {
    1193             :   //AlwaysAssert(lattice, AipsError);
    1194        2144 :   AlwaysAssert(gridder, AipsError);
    1195        2144 :   AlwaysAssert(image, AipsError);
    1196        2144 :   logIO() << LogOrigin("GridFT", "getImage") << LogIO::NORMAL;
    1197             : 
    1198        2144 :   if((griddedData.nelements() ==0) && (griddedData2.nelements()==0)){
    1199           0 :     throw(AipsError("Programmer error ...request for image without right order of calls"));
    1200             :   }
    1201        2144 :   weights.resize(sumWeight.shape());
    1202             : 
    1203        2144 :   convertArray(weights, sumWeight);
    1204             :   // If the weights are all zero then we cannot normalize
    1205             :   // otherwise we don't care.
    1206        2144 :   if(normalize&&max(weights)==0.0) {
    1207             :     logIO() << LogIO::SEVERE << "No useful data in GridFT: weights all zero"
    1208           0 :             << LogIO::POST;
    1209             :   }
    1210             :   else {
    1211             : 
    1212             :     //const IPosition latticeShape = lattice->shape();
    1213             :     
    1214             :     //logIO() << LogIO::DEBUGGING
    1215             :     //      << "Starting FFT and scaling of image" << LogIO::POST;
    1216             :     
    1217             : 
    1218             :   
    1219             :     // if(useDoubleGrid_p){
    1220             :     //   convertArray(griddedData, griddedData2);
    1221             :     //   //Don't need the double-prec grid anymore...
    1222             :     //   griddedData2.resize();
    1223             :     // }
    1224             : 
    1225             :     // x and y transforms
    1226             :     //    LatticeFFT::cfft2d(*lattice,false);
    1227             :     //
    1228             :     // Retain the double precision grid for FFT as well.  Convert it
    1229             :     // to single precision just after (since images are still single
    1230             :     // precision).
    1231             :     //
    1232        2144 :     if(useDoubleGrid_p)
    1233             :       {
    1234        2144 :         ArrayLattice<DComplex> darrayLattice(griddedData2);
    1235             :         //LatticeFFT::cfft2d(darrayLattice,false);
    1236        2144 :         ft_p.c2cFFT(darrayLattice, False);
    1237        2144 :         griddedData.resize(griddedData2.shape());
    1238        2144 :         convertArray(griddedData, griddedData2);
    1239             :         
    1240        2144 :         SynthesisUtilMethods::getResource("mem peak in getImage");
    1241             : 
    1242             :         //Don't need the double-prec grid anymore...
    1243        2144 :         griddedData2.resize();
    1244        2144 :         arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
    1245        2144 :         lattice=arrayLattice;
    1246        2144 :       }
    1247             :     else{
    1248           0 :       arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
    1249           0 :       lattice=arrayLattice;
    1250             :       
    1251             :       //LatticeFFT::cfft2d(*lattice,false);
    1252           0 :       ft_p.c2cFFT(*lattice, False);
    1253             :     }
    1254             : 
    1255             :     
    1256             :     
    1257             :     {
    1258        2144 :       Int inx = lattice->shape()(0);
    1259        2144 :       Int iny = lattice->shape()(1);
    1260        2144 :       Vector<Complex> correction(inx);
    1261        2144 :       correction=Complex(1.0, 0.0);
    1262             :       // Do the Grid-correction
    1263        2144 :       IPosition cursorShape(4, inx, 1, 1, 1);
    1264        2144 :       IPosition axisPath(4, 0, 1, 2, 3);
    1265        2144 :       LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1266        2144 :       LatticeIterator<Complex> lix(*lattice, lsx);
    1267     1583072 :       for(lix.reset();!lix.atEnd();lix++) {
    1268     1580928 :         Int pol=lix.position()(2);
    1269     1580928 :         Int chan=lix.position()(3);
    1270     1580928 :         if(weights(pol, chan)!=0.0) {
    1271     1523400 :           gridder->correctX1D(correction, lix.position()(1));
    1272     1523400 :           lix.rwVectorCursor()/=correction;
    1273     1523400 :           if(normalize) {
    1274           0 :             Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan));
    1275           0 :             lix.rwCursor()*=rnorm;
    1276             :           }
    1277             :           else {
    1278     1523400 :             Complex rnorm(Float(inx)*Float(iny));
    1279     1523400 :             lix.rwCursor()*=rnorm;
    1280             :           }
    1281             :         }
    1282             :         else {
    1283       57528 :           lix.woCursor()=0.0;
    1284             :         }
    1285             :       }
    1286        2144 :     }
    1287        2144 :     LatticeLocker lock1 (*(image), FileLocker::Write);
    1288        2144 :     if(!isTiled) {
    1289             :       // Check the section from the image BEFORE converting to a lattice 
    1290        4288 :       IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    1291        2144 :       IPosition stride(4, 1);
    1292        4288 :       IPosition trc(blc+image->shape()-stride);
    1293             :       // Do the copy
    1294        2144 :       IPosition start(4, 0);
    1295             :       
    1296        2144 :       image->put(griddedData(blc, trc));
    1297        2144 :     }
    1298        2144 :   }
    1299        2144 :   image->flush();
    1300        2144 :   image->clearCache();
    1301             : 
    1302        2144 :   if(arrayLattice) arrayLattice=nullptr;
    1303        2144 :   if(lattice) lattice=nullptr;
    1304        2144 :   griddedData.resize();
    1305        2144 :   return *image;
    1306             : }
    1307             : 
    1308             : // Get weight image
    1309           0 : void GridFT::getWeightImage(ImageInterface<Float>& weightImage, Matrix<Float>& weights) 
    1310             : {
    1311             : 
    1312           0 :   logIO() << LogOrigin("GridFT", "getWeightImage") << LogIO::NORMAL;
    1313             : 
    1314           0 :   weights.resize(sumWeight.shape());
    1315           0 :   convertArray(weights,sumWeight);
    1316             : 
    1317           0 :   const IPosition latticeShape = weightImage.shape();
    1318             : 
    1319           0 :   Int nx=latticeShape(0);
    1320           0 :   Int ny=latticeShape(1);
    1321             : 
    1322           0 :   IPosition loc(2, 0);
    1323           0 :   IPosition cursorShape(4, nx, ny, 1, 1);
    1324           0 :   IPosition axisPath(4, 0, 1, 2, 3);
    1325           0 :   LatticeStepper lsx(latticeShape, cursorShape, axisPath);
    1326           0 :   LatticeIterator<Float> lix(weightImage, lsx);
    1327           0 :   for(lix.reset();!lix.atEnd();lix++) {
    1328           0 :     Int pol=lix.position()(2);
    1329           0 :     Int chan=lix.position()(3);
    1330           0 :     lix.rwCursor()=weights(pol,chan);
    1331             :   }
    1332           0 : }
    1333             : 
    1334          45 : Bool GridFT::toRecord(String& error,
    1335             :                       RecordInterface& outRec, Bool withImage, const String diskimage)
    1336             : {
    1337             : 
    1338             :   
    1339             : 
    1340             :   // Save the current GridFT object to an output state record
    1341          45 :   Bool retval = true;
    1342          45 :   Float elpadd=padding_p;
    1343          45 :   if(toVis_p && withImage)
    1344          19 :     elpadd=1.0;
    1345             :   //save the base class variables
    1346          45 :   if(!FTMachine::toRecord(error, outRec, withImage, diskimage))
    1347           0 :     return false;
    1348             : 
    1349             :   //a call to init  will redo imagecache and gridder
    1350             :   // so no need to save these
    1351             : 
    1352          45 :   outRec.define("cachesize", Int64(cachesize));
    1353          45 :   outRec.define("tilesize", tilesize);
    1354          45 :   outRec.define("convtype", convType);
    1355          45 :   outRec.define("uvscale", uvScale);
    1356          45 :   outRec.define("uvoffset", uvOffset);
    1357          45 :   outRec.define("istiled", isTiled);
    1358          45 :   outRec.define("maxabsdata", maxAbsData);
    1359          45 :   Vector<Int> center_loc(4), offset_loc(4);
    1360         225 :   for (Int k=0; k<4 ; k++){
    1361         180 :     center_loc(k)=centerLoc(k);
    1362         180 :     offset_loc(k)=offsetLoc(k);
    1363             :   }
    1364          45 :   outRec.define("centerloc", center_loc);
    1365          45 :   outRec.define("offsetloc", offset_loc);
    1366          45 :   outRec.define("padding", elpadd);
    1367          45 :   outRec.define("usezero", usezero_p);
    1368          45 :   outRec.define("nopadding", noPadding_p);
    1369          45 :   return retval;
    1370          45 : }
    1371             : 
    1372           0 : Bool GridFT::fromRecord(String& error,
    1373             :                         const RecordInterface& inRec)
    1374             : {
    1375           0 :   Bool retval = true;
    1376           0 :   if(!FTMachine::fromRecord(error, inRec))
    1377           0 :     return false;
    1378           0 :   gridder=0; imageCache=0; lattice.reset( ); arrayLattice.reset( );
    1379             :   //For some reason int64 seems to be getting lost...
    1380             :   //this is not an important parameter...so filing a jira 
    1381           0 :   if(inRec.isDefined("cachesize"))
    1382           0 :     cachesize=inRec.asInt64("cachesize");
    1383             :   else
    1384           0 :     cachesize=1000000;
    1385           0 :   inRec.get("tilesize", tilesize);
    1386           0 :   inRec.get("convtype", convType);
    1387           0 :   inRec.get("uvscale", uvScale);
    1388           0 :   inRec.get("uvoffset", uvOffset);
    1389           0 :   inRec.get("istiled", isTiled);
    1390           0 :   inRec.get("maxabsdata", maxAbsData);
    1391           0 :   Vector<Int> center_loc(4), offset_loc(4);
    1392           0 :   inRec.get("centerloc", center_loc);
    1393           0 :   inRec.get("offsetloc", offset_loc);
    1394           0 :   uInt ndim4 = 4;
    1395           0 :   centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2), 
    1396           0 :                       center_loc(3));
    1397           0 :   offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2), 
    1398           0 :                       offset_loc(3));
    1399           0 :   inRec.get("padding", padding_p);
    1400           0 :   inRec.get("usezero", usezero_p);
    1401           0 :   inRec.get("nopadding", noPadding_p);
    1402             : 
    1403           0 :   machineName_p="GridFT";
    1404             :   ///setup some of the parameters if there is an image
    1405           0 :   if(inRec.isDefined("image") || inRec.isDefined("diskimage"))
    1406           0 :     init();
    1407             :   /*if(!cmplxImage_p.null()){
    1408             :     //FTMachine::fromRecord would have recovered the image
    1409             :     // Might be changing the shape of sumWeight
    1410             : 
    1411             :     if(isTiled) {
    1412             :       lattice=std::shared_ptr<Lattice<Complex> >(image, false);
    1413             :     }
    1414             :     else {
    1415             :       // Make the grid the correct shape and turn it into an array lattice
    1416             :       // Check the section from the image BEFORE converting to a lattice 
    1417             :       if(!toVis_p){
    1418             :         IPosition gridShape(4, nx, ny, npol, nchan);
    1419             :         griddedData.resize(gridShape);
    1420             :         griddedData=Complex(0.0);
    1421             :       }
    1422             :       else{
    1423             :         prepGridForDegrid();
    1424             :       }
    1425             :     }
    1426             :     };*/
    1427           0 :   return retval;
    1428           0 : }
    1429             : 
    1430     1392947 : void GridFT::ok() {
    1431     1392947 :   AlwaysAssert(image, AipsError);
    1432     1392947 : }
    1433             : 
    1434             : // Make a plain straightforward honest-to-God image. This returns
    1435             : // a complex image, without conversion to Stokes. The representation
    1436             : // is that required for the visibilities.
    1437             : //----------------------------------------------------------------------
    1438           0 : void GridFT::makeImage(FTMachine::Type type, 
    1439             :                        vi::VisibilityIterator2& vi,
    1440             :                        ImageInterface<Complex>& theImage,
    1441             :                        Matrix<Float>& weight) {
    1442             : 
    1443             : 
    1444           0 :   logIO() << LogOrigin("GridFT", "makeImage") << LogIO::NORMAL;
    1445             : 
    1446           0 :   if(type==FTMachine::COVERAGE) {
    1447           0 :     logIO() << "Type COVERAGE not defined for Fourier transforms" << LogIO::EXCEPTION;
    1448             :   }
    1449             : 
    1450             : 
    1451             : 
    1452             : 
    1453             :   // Loop over all visibilities and pixels
    1454           0 :   vi::VisBuffer2* vb=vi.getVisBuffer();
    1455             :   
    1456             :   // Initialize put (i.e. transform to Sky) for this model
    1457           0 :   vi.origin();
    1458             : 
    1459           0 :   if(vb->polarizationFrame()==MSIter::Linear) {
    1460           0 :     StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::LINEAR);
    1461             :   }
    1462             :   else {
    1463           0 :     StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::CIRCULAR);
    1464             :   }
    1465             :   
    1466           0 :   initializeToSky(theImage,weight,*vb);
    1467             : 
    1468             :   // Loop over the visibilities, putting VisBuffers
    1469           0 :   for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
    1470           0 :     for (vi.origin(); vi.more(); vi.next()) {
    1471             :       
    1472           0 :       switch(type) {
    1473           0 :       case FTMachine::RESIDUAL:
    1474           0 :           vb->setVisCube(vb->visCubeCorrected()-vb->visCubeModel());
    1475           0 :           put(*vb, -1, false);
    1476           0 :           break;
    1477           0 :       case FTMachine::MODEL:
    1478           0 :           vb->setVisCube(vb->visCubeModel());
    1479           0 :           put(*vb, -1, false);
    1480           0 :           break;
    1481           0 :       case FTMachine::CORRECTED:
    1482           0 :           vb->setVisCube(vb->visCubeCorrected());
    1483           0 :           put(*vb, -1, false);
    1484           0 :           break;
    1485           0 :       case FTMachine::PSF:
    1486           0 :           vb->setVisCube(Complex(1.0,0.0));
    1487           0 :           put(*vb, -1, true);
    1488           0 :           break;
    1489           0 :       case FTMachine::OBSERVED:
    1490             :       default:
    1491           0 :         put(*vb, -1, false);
    1492           0 :         break;
    1493             :       }
    1494             :     }
    1495             :   }
    1496           0 :   finalizeToSky();
    1497             :   // Normalize by dividing out weights, etc.
    1498           0 :   getImage(weight, true);
    1499           0 : }
    1500             : 
    1501        4148 : String GridFT::name() const {
    1502             : 
    1503        4148 :   return machineName_p;
    1504             : 
    1505             : 
    1506             : }
    1507             : 
    1508             : }//End of namespace refim
    1509             : } //# NAMESPACE CASA - END
    1510             : 

Generated by: LCOV version 1.16