LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - GridFT.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 444 598 74.2 %
Date: 2024-12-11 20:54:31 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          21 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType, Float padding,
      92          21 :                Bool usezero, Bool useDoublePrec)
      93          21 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize),
      94          21 :   gridder(0), isTiled(false), convType(iconvType),
      95          21 :   maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
      96          21 :   usezero_p(usezero), noPadding_p(false), usePut2_p(false), 
      97          42 :   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          21 :   useDoubleGrid_p=useDoublePrec;  
     100             :   //  peek=NULL;
     101          21 : }
     102             : 
     103        2479 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
     104        2479 :                MPosition mLocation, Float padding, Bool usezero, Bool useDoublePrec)
     105        2479 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
     106        2479 :   tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
     107        2479 :   offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false), 
     108        4958 :   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        2479 :   mLocation_p=mLocation;
     111        2479 :   tangentSpecified_p=false;
     112        2479 :   useDoubleGrid_p=useDoublePrec;
     113             :   //  peek=NULL;
     114        2479 : }
     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           7 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
     130             :                MPosition mLocation, MDirection mTangent, Float padding,
     131           7 :                Bool usezero, Bool useDoublePrec)
     132           7 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
     133           7 :   tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
     134           7 :   offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false), 
     135          14 :   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           7 :   mLocation_p=mLocation;
     138           7 :   mTangent_p=mTangent;
     139           7 :   tangentSpecified_p=true;
     140           7 :   useDoubleGrid_p=useDoublePrec;
     141             :   //  peek=NULL;
     142           7 : }
     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         264 : GridFT& GridFT::operator=(const GridFT& other)
     160             : {
     161         264 :   if(this!=&other) {
     162             :     //Do the base parameters
     163         264 :     FTMachine::operator=(other);
     164             :     
     165             :     //private params
     166         264 :     imageCache=other.imageCache;
     167         264 :     cachesize=other.cachesize;
     168         264 :     tilesize=other.tilesize;
     169         264 :     convType=other.convType;
     170         264 :     convType.upcase();
     171         264 :     uvScale.resize();
     172         264 :     uvOffset.resize();
     173         264 :     uvScale.assign(other.uvScale);
     174         264 :     uvOffset.assign(other.uvOffset);
     175         264 :     if(other.gridder==0)
     176         264 :       gridder=0;
     177             :     else{  
     178           0 :       gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     179           0 :                                                      uvScale, uvOffset,
     180           0 :                                                      convType);
     181             :     }
     182         264 :     convFunc_p.resize();
     183         264 :     convSupport_p=other.convSupport_p;
     184         264 :     convSampling_p=other.convSampling_p;
     185         264 :     convFunc_p=other.convFunc_p;
     186         264 :     isTiled=other.isTiled;
     187             :     //lattice=other.lattice;
     188         264 :     lattice.reset( );
     189         264 :     tilesize=other.tilesize;
     190         264 :     arrayLattice.reset( );
     191         264 :     maxAbsData=other.maxAbsData;
     192         264 :     centerLoc=other.centerLoc;
     193         264 :     offsetLoc=other.offsetLoc;
     194         264 :     padding_p=other.padding_p;
     195         264 :     usezero_p=other.usezero_p;
     196         264 :     noPadding_p=other.noPadding_p;      
     197         264 :     machineName_p="GridFT";
     198         264 :     timemass_p=0.0;
     199         264 :     timegrid_p=0.0;
     200             :     //    peek = other.peek;
     201             :   };
     202         264 :   return *this;
     203             : };
     204             : 
     205             : //----------------------------------------------------------------------
     206         264 : GridFT::GridFT(const GridFT& other) : FTMachine(), machineName_p("GridFT")
     207             : {
     208         264 :   operator=(other);
     209         264 : }
     210             : 
     211             : //-----------------------------------------------------------------------
     212         264 :   FTMachine* GridFT::cloneFTM(){
     213         264 :     return new GridFT(*this);
     214             :   }
     215             : 
     216             :   //===============================
     217        2141 :  Long GridFT::estimateRAM(const CountedPtr<SIImageStore>& imstor){
     218        2141 :    Long mem=FTMachine::estimateRAM(imstor);
     219        2141 :    mem=mem*padding_p*padding_p;
     220        2141 :    return mem;
     221             :   }
     222             : 
     223             : 
     224             :   //----------------------------------------------------------------------
     225        2894 : void GridFT::init() {
     226             : 
     227        2894 :   logIO() << LogOrigin("GridFT", "init")  << LogIO::NORMAL;
     228             : 
     229        2894 :   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        2894 :     isTiled=false;
     250        2894 :     if(!noPadding_p && padding_p > 1.01){
     251        2869 :       CompositeNumber cn(uInt(image->shape()(0)*2));    
     252        2869 :       nx    = cn.nextLargerEven(Int(padding_p*Float(image->shape()(0))-0.5));
     253        2869 :       ny    = cn.nextLargerEven(Int(padding_p*Float(image->shape()(1))-0.5));
     254        2869 :     }
     255             :     else{
     256          25 :       nx    = image->shape()(0);
     257          25 :       ny    = image->shape()(1);
     258             :     }
     259        2894 :     npol  = image->shape()(2);
     260        2894 :     nchan = image->shape()(3);
     261             :     // }
     262             : 
     263        2894 :   sumWeight.resize(npol, nchan);
     264             : 
     265        2894 :   uvScale.resize(2);
     266        2894 :   uvScale(0)=(Float(nx)*image->coordinates().increment()(0)); 
     267        2894 :   uvScale(1)=(Float(ny)*image->coordinates().increment()(1)); 
     268        2894 :   uvOffset.resize(2);
     269        2894 :   uvOffset(0)=nx/2;
     270        2894 :   uvOffset(1)=ny/2;
     271             : 
     272             :   // Now set up the gridder. The possibilities are BOX and SF
     273        2894 :   if(gridder) delete gridder; gridder=0;
     274        2894 :   convType.upcase();
     275        5788 :   gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
     276        2894 :                                                  uvScale, uvOffset,
     277        2894 :                                                  convType);
     278             : 
     279        2894 :   convFunc_p.resize();
     280        2894 :   convSupport_p=gridder->cSupport()(0);
     281        2894 :   convSampling_p=gridder->cSampling();
     282        2894 :   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        2894 :   if(imageCache) delete imageCache; imageCache=0;
     288             : 
     289        2894 :   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        2894 : }
     310             : 
     311             : // This is nasty, we should use CountedPointers here.
     312        5538 : GridFT::~GridFT() {
     313        2769 :   if(imageCache) delete imageCache; imageCache=0;
     314             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     315        2769 :   if(gridder) delete gridder; gridder=0;
     316        5538 : }
     317             : 
     318             : // Initialize for a transform from the Sky domain. This means that
     319             : // we grid-correct, and FFT the image
     320             : 
     321         775 : void GridFT::initializeToVis(ImageInterface<Complex>& iimage,
     322             :                              const vi::VisBuffer2& vb)
     323             : {
     324         775 :   image=&iimage;
     325         775 :   toVis_p=true;
     326             : 
     327         775 :   ok();
     328             : 
     329         775 :   init();
     330             :   //  peek->reset();
     331             :   // Initialize the maps for polarization and channel. These maps
     332             :   // translate visibility indices into image indices
     333         775 :   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         775 :   prepGridForDegrid();
     351             : 
     352             :   //AlwaysAssert(lattice, AipsError);
     353             : 
     354             :  
     355             :     
     356         775 : }
     357             : 
     358         775 : void GridFT::prepGridForDegrid(){
     359         775 :   IPosition gridShape(4, nx, ny, npol, nchan);
     360         775 :   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         775 :   griddedData.set(Complex(0.0));
     366             : 
     367         775 :   IPosition stride(4, 1);
     368        1550 :   IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
     369        1550 :   IPosition trc(blc+image->shape()-stride);
     370             :   
     371         775 :   IPosition start(4, 0);
     372         775 :   griddedData(blc, trc) = image->getSlice(start, image->shape());
     373             :   
     374             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     375         775 :   arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
     376         775 :   lattice=arrayLattice;
     377             :   //logIO() << LogIO::DEBUGGING
     378             :   //      << "Starting grid correction and FFT of image" << LogIO::POST;
     379             : 
     380             :    // Do the Grid-correction. 
     381             :    {
     382         775 :      Vector<Complex> correction(nx);
     383         775 :      correction=Complex(1.0, 0.0);
     384             :      // Do the Grid-correction
     385         775 :      IPosition cursorShape(4, nx, 1, 1, 1);
     386         775 :      IPosition axisPath(4, 0, 1, 2, 3);
     387         775 :      LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
     388         775 :      LatticeIterator<Complex> lix(*lattice, lsx);
     389      547039 :      for(lix.reset();!lix.atEnd();lix++) {
     390      546264 :        gridder->correctX1D(correction, lix.position()(1));
     391      546264 :        lix.rwVectorCursor()/=correction;
     392             :      }
     393         775 :    }
     394         775 :    image->clearCache();
     395             :    // Now do the FFT2D in place
     396             :    //LatticeFFT::cfft2d(*lattice);
     397         775 :    ft_p.c2cFFT(*lattice);
     398             :    //logIO() << LogIO::DEBUGGING
     399             :    //       << "Finished grid correction and FFT of image" << LogIO::POST;
     400             :     
     401         775 : }
     402             : 
     403             : 
     404         773 : void GridFT::finalizeToVis()
     405             : {
     406             : 
     407         773 :   logIO() << LogOrigin("GridFT", "finalizeToVis")  << LogIO::NORMAL;
     408         773 :   logIO() <<LogIO::NORMAL2<< "Time to degrid " << timedegrid_p <<LogIO::POST;
     409         773 :   timedegrid_p=0.0;
     410             : 
     411         773 :  if(arrayLattice) arrayLattice=nullptr;
     412         773 :   if(lattice) lattice=nullptr;
     413         773 :   griddedData.resize();
     414         773 :   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         773 : }
     426             : 
     427             : 
     428             : // Initialize the FFT to the Sky. Here we have to setup and initialize the
     429             : // grid. 
     430        2119 : void GridFT::initializeToSky(ImageInterface<Complex>& iimage,
     431             :                              Matrix<Float>& weight, const vi::VisBuffer2& vb)
     432             : {
     433             :   // image always points to the image
     434        2119 :   image=&iimage;
     435        2119 :   toVis_p=false;
     436             : 
     437        2119 :   init();
     438             : 
     439             :   // Initialize the maps for polarization and channel. These maps
     440             :   // translate visibility indices into image indices
     441        2119 :   initMaps(vb);
     442             : 
     443             : 
     444             :   
     445        2119 :   sumWeight=0.0;
     446        2119 :   weight.resize(sumWeight.shape());
     447        2119 :   weight=0.0;
     448             : 
     449             :  
     450        2119 :   IPosition gridShape(4, nx, ny, npol, nchan);
     451        2119 :     if( !useDoubleGrid_p )
     452             :       {
     453          23 :         griddedData.resize(gridShape);
     454          23 :         griddedData=Complex(0.0);
     455             :       }
     456             :     else{
     457             :       
     458        2096 :       griddedData2.resize(gridShape);
     459        2096 :       griddedData2=DComplex(0.0);
     460             :     }
     461        2119 :   image->clearCache();
     462             :   //iimage.get(griddedData, false);
     463             :   //if(arrayLattice) delete arrayLattice; arrayLattice=0;
     464             :   
     465             :   
     466             :   //AlwaysAssert(lattice, AipsError);
     467        2119 : }
     468             : 
     469             : 
     470             : 
     471        2118 : 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        2118 :   logIO() << LogOrigin("GridFT", "finalizeToSky")  << LogIO::NORMAL;
     477        2118 :   logIO()<<LogIO::NORMAL2 <<"Time to massage data " << timemass_p << LogIO::POST;
     478        2118 :   logIO()<< LogIO::NORMAL2 <<"Time to grid data " << timegrid_p << LogIO::POST;
     479        2118 :   timemass_p=0.0;
     480        2118 :   timegrid_p=0.0;
     481        2118 :   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        2118 : }
     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      509336 : void GridFT::put(const vi::VisBuffer2& vb, Int row, Bool dopsf,
     684             :                  FTMachine::Type type)
     685             : {
     686             : 
     687      509336 :   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      509335 :   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      509335 :   if(max(chanMap)==-1)
     707             :     {
     708             :       //      peek->reset();
     709         136 :       return;
     710             :     }
     711             : 
     712      509199 :   Timer tim;
     713      509199 :   tim.mark();
     714             : 
     715             :   //const Matrix<Float> *imagingweight;
     716             :   //imagingweight=&(vb.imagingWeight());
     717      509199 :   Matrix<Float> imagingweight;
     718      509199 :   getImagingWeight(imagingweight, vb);
     719             :   
     720      509199 :   if(dopsf) {type=FTMachine::PSF;}
     721             : 
     722      509199 :   Cube<Complex> data;
     723             :   //Fortran gridder need the flag as ints 
     724      509199 :   Cube<Int> flags;
     725      509199 :   Matrix<Float> elWeight;
     726      509199 :   interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
     727             : 
     728             : 
     729             :   Bool iswgtCopy;
     730             :   const Float *wgtStorage;
     731      509199 :   wgtStorage=elWeight.getStorage(iswgtCopy);
     732             :   
     733             :   Bool isCopy;
     734             :   const Complex *datStorage;
     735      509199 :   if(!dopsf)
     736      311538 :     datStorage=data.getStorage(isCopy);
     737             :   else
     738      197661 :     datStorage=0;
     739             :   // If row is -1 then we pass through all rows
     740             :   Int startRow, endRow, nRow;
     741      509199 :   if (row==-1) {
     742      509199 :     nRow=vb.nRows();
     743      509199 :     startRow=0;
     744      509199 :     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      509199 :   const IPosition &fs=flags.shape();
     763      509199 :   std::vector<Int> s(fs.begin(),fs.end());
     764      509199 :   Int nvispol=s[0];
     765      509199 :   Int nvischan=s[1];
     766      509199 :   Int nvisrow=s[2];
     767      509199 :   Matrix<Double> uvw(negateUV(vb));
     768             : 
     769      509199 :   Vector<Double> dphase(vb.nRows());
     770      509199 :   Cube<Int> loc(2, nvischan, nRow);
     771      509199 :   Cube<Int> off(2, nvischan, nRow);
     772      509199 :   Matrix<Complex> phasor(nvischan, nRow);
     773      509199 :   Int csamp=convSampling_p;
     774      509199 :   dphase=0.0;
     775             :   
     776      509199 :   timemass_p +=tim.real();
     777      509199 :   tim.mark(); 
     778      509199 :   rotateUVW(uvw, dphase, vb);
     779      509199 :   refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
     780             :   Bool delphase;
     781      509199 :   Complex * phasorstor=phasor.getStorage(delphase);
     782      509199 :   const Double * visfreqstor=interpVisFreq_p.getStorage(del);
     783      509199 :   const Double * scalestor=uvScale.getStorage(del);
     784      509199 :   const Double * offsetstor=uvOffset.getStorage(del);
     785      509199 :   const Double* uvstor= uvw.getStorage(del);
     786      509199 :   Int * locstor=loc.getStorage(del);
     787      509199 :   Int * offstor=off.getStorage(del);
     788      509199 :   const Double *dpstor=dphase.getStorage(del);
     789             :   //Vector<Double> f1=interpVisFreq_p.copy();
     790      509199 :   Int nvchan=nvischan;
     791             :   Int irow;
     792      509199 :   Double cinv=Double(1.0)/C::c;
     793      509199 :   Int dow=0;
     794      509199 :   Int nth=1;
     795             : #ifdef _OPENMP
     796      509199 :   if(numthreads_p >0){
     797           0 :     nth=min(numthreads_p, omp_get_max_threads());
     798             :   }
     799             :   else{   
     800      509199 :     nth= omp_get_max_threads();
     801             :   }
     802             :   //nth=min(4,nth);
     803             : #endif
     804             :   
     805             : 
     806      509199 : #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      509199 :   Int idopsf=0;
     819      509199 :   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      509199 :   Vector<Int> rowFlags(vb.nRows());
     831      509199 :   rowFlags=0;
     832      509199 :   rowFlags(vb.flagRow())=true;
     833      509199 :   if(!usezero_p) {
     834   172382192 :     for (Int rownr=startRow; rownr<=endRow; rownr++) {
     835   171878527 :       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      509199 :   Int csupp=convSupport_p;
     843             :   
     844      509199 :   const Double * convfuncstor=(convFunc_p).getStorage(del);
     845             :   
     846             :   // cerr <<"Poffset " << min(off) << "  " << max(off) << " length " << gridder->cFunction().shape() << endl;
     847             :   
     848             : 
     849             : 
     850      509199 :   ixsub=1;
     851      509199 :   iysub=1; 
     852      509199 :   if (nth >4){
     853      244278 :     ixsub=8;
     854      244278 :     iysub=8; 
     855             :   }
     856      264921 :   else if(nth >1) {
     857      264921 :      ixsub=2;
     858      264921 :      iysub=2; 
     859             :   }
     860             : 
     861             :   
     862      509199 :   Int rbeg=startRow+1;
     863      509199 :   Int rend=endRow+1;
     864      509199 :   Block<Matrix<Double> > sumwgt(ixsub*iysub);
     865    17202675 :   for (icounter=0; icounter < ixsub*iysub; ++icounter){
     866    16693476 :     sumwgt[icounter].resize(sumWeight.shape());
     867    16693476 :     sumwgt[icounter].set(0.0);
     868             :   }
     869      509199 :  if(doneThreadPartition_p < 0){
     870        1175 :     xsect_p.resize(ixsub*iysub);
     871        1175 :     ysect_p.resize(ixsub*iysub);
     872        1175 :     nxsect_p.resize(ixsub*iysub);
     873        1175 :     nysect_p.resize(ixsub*iysub);
     874       36475 :     for (icounter=0; icounter < ixsub*iysub; ++icounter){
     875       35300 :       findGridSector(nx, ny, ixsub, iysub, 0, 0, icounter, xsect_p(icounter), ysect_p(icounter), nxsect_p(icounter), nysect_p(icounter), true);
     876             :     }
     877             :   } 
     878      509199 :  Vector<Int> xsect, ysect, nxsect, nysect;
     879      509199 :  xsect=xsect_p; ysect=ysect_p; nxsect=nxsect_p; nysect=nysect_p;
     880      509199 :   const Int* pmapstor=polMap.getStorage(del);
     881      509199 :   const Int *cmapstor=chanMap.getStorage(del);
     882      509199 :   Int nc=nchan;
     883      509199 :   Int np=npol;
     884      509199 :   Int nxp=nx;
     885      509199 :   Int nyp=ny;
     886      509199 :   const Int * flagstor=flags.getStorage(del);
     887      509199 :   const Int * rowflagstor=rowFlags.getStorage(del);
     888             :   ////////////////////////
     889             : 
     890             :   Bool gridcopy;
     891      509199 :   if(useDoubleGrid_p){
     892      503265 :     DComplex *gridstor=griddedData2.getStorage(gridcopy);
     893      503265 : #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    17120205 :   for (icounter=0; icounter < ixsub*iysub; ++icounter){
     929    16616940 :       sumWeight=sumWeight+sumwgt[icounter];
     930             :   }
     931             :   //phasor.putStorage(phasorstor, delphase); 
     932      503265 :   griddedData2.putStorage(gridstor, gridcopy);
     933      503265 :   if(dopsf && (nth >4))
     934       99198 :     tweakGridSector(nx, ny, ixsub, iysub);
     935             :   }
     936             :   else{
     937        5934 :     Complex *gridstor=griddedData.getStorage(gridcopy);
     938        5934 : #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       82470 :     for (icounter=0; icounter < ixsub*iysub; ++icounter){
     977       76536 :       sumWeight=sumWeight+sumwgt[icounter];
     978             :     }
     979             :     
     980        5934 :     griddedData.putStorage(gridstor, gridcopy);
     981        5934 :     if(dopsf && (nth > 4))
     982         480 :       tweakGridSector(nx, ny, ixsub, iysub);
     983             :   }
     984             :   // cerr << "sunweight " << sumWeight << endl;
     985             : 
     986      509199 :   timegrid_p+=tim.real();
     987             :   
     988      509199 :   if(!dopsf)
     989      311538 :     data.freeStorage(datStorage, isCopy);
     990      509199 :   elWeight.freeStorage(wgtStorage,iswgtCopy);
     991             :   
     992             :   //  peek->reset();
     993      509199 : }
     994             : 
     995          21 : void GridFT::modifyConvFunc(const Vector<Double>& convFunc, Int convSupport, Int convSampling){
     996          21 :   convFunc_p.resize();
     997          21 :   convFunc_p=convFunc;
     998          21 :   convSupport_p=convSupport;
     999          21 :   convSampling_p=convSampling;
    1000             : 
    1001          21 : } 
    1002             : 
    1003      159984 : void GridFT::get(vi::VisBuffer2& vb, Int row)
    1004             : {
    1005             : 
    1006      159984 :   gridOk(convSupport_p);
    1007             :   // If row is -1 then we pass through all rows
    1008             :   Int startRow, endRow, nRow;
    1009      159984 :   if (row < 0) {
    1010      159984 :     nRow=vb.nRows();
    1011      159984 :     startRow=0;
    1012      159984 :     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      159984 :     matchChannel(vb);
    1026             :   
    1027             :   
    1028             :     //cerr << "GETchanMap " << chanMap << endl;
    1029             :   //No point in reading data if its not matching in frequency
    1030      159984 :   if(max(chanMap)==-1)
    1031          58 :     return;
    1032             : 
    1033             : 
    1034             : 
    1035             :   // Get the uvws in a form that Fortran can use
    1036      159926 :   Matrix<Double> uvw(negateUV(vb));
    1037      159926 :   Vector<Double> dphase(vb.nRows());
    1038      159926 :   dphase=0.0;
    1039      159926 :   rotateUVW(uvw, dphase, vb);
    1040      159926 :   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      159926 :   Cube<Complex> data;
    1053      159926 :   Cube<Int> flags;
    1054      159926 :   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      159926 :   Int nvp=data.shape()(0);
    1060      159926 :   Int nvc=data.shape()(1);
    1061      159926 :   Int nvisrow=data.shape()(2);
    1062             :     
    1063             : 
    1064             :   //cerr << "get flags " << min(flags) << "  " << max(flags) << endl;
    1065             :   Complex *datStorage;
    1066             :   Bool isCopy;
    1067      159926 :   datStorage=data.getStorage(isCopy);
    1068             :   
    1069             :   ///
    1070      159926 :   Cube<Int> loc(2, nvc, nvisrow);
    1071      159926 :   Cube<Int> off(2, nvc, nRow);
    1072      159926 :   Matrix<Complex> phasor(nvc, nRow);
    1073      159926 :   Int csamp=convSampling_p;
    1074             :   Bool delphase;
    1075             :   Bool del;
    1076      159926 :   Complex * phasorstor=phasor.getStorage(delphase);
    1077      159926 :   const Double * visfreqstor=interpVisFreq_p.getStorage(del);
    1078      159926 :   const Double * scalestor=uvScale.getStorage(del);
    1079      159926 :   const Double * offsetstor=uvOffset.getStorage(del);
    1080      159926 :   const Double* uvstor= uvw.getStorage(del);
    1081      159926 :   Int * locstor=loc.getStorage(del);
    1082      159926 :   Int * offstor=off.getStorage(del);
    1083      159926 :   const Double *dpstor=dphase.getStorage(del);
    1084             :   //Vector<Double> f1=interpVisFreq_p.copy();
    1085      159926 :   Int nvchan=nvc;
    1086             :   Int irow;
    1087      159926 :   Double cinv=Double(1.0)/C::c;
    1088      159926 :   Int dow=0;
    1089      159926 :   Int nth=1;
    1090             : #ifdef _OPENMP
    1091      159926 :   if(numthreads_p >0){
    1092           0 :     nth=min(numthreads_p, omp_get_max_threads());
    1093             :   }
    1094             :   else{   
    1095      159926 :     nth= omp_get_max_threads();
    1096             :   }
    1097             :   //nth=min(4,nth);
    1098             : #endif
    1099             : 
    1100             : 
    1101      159926 : #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      159926 :   Int rbeg=startRow+1;
    1116      159926 :   Int rend=endRow+1;
    1117             : 
    1118             : 
    1119      159926 :   Vector<Int> rowFlags(vb.nRows());
    1120      159926 :   rowFlags=0;
    1121      159926 :   rowFlags(vb.flagRow())=true;
    1122             :   //cerr << "rowFlags " << rowFlags << endl;
    1123      159926 :   if(!usezero_p) {
    1124    55143110 :     for (Int rownr=startRow; rownr<=endRow; rownr++) {
    1125    54983184 :       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      159926 :     const Complex* gridstor=griddedData.getStorage(delgrid);
    1135      159926 :     const Double * convfuncstor=(convFunc_p).getStorage(del);
    1136             :     
    1137      159926 :     const Int* pmapstor=polMap.getStorage(del);
    1138      159926 :     const Int *cmapstor=chanMap.getStorage(del);
    1139      159926 :     Int nc=nchan;
    1140      159926 :     Int np=npol;
    1141      159926 :     Int nxp=nx;
    1142      159926 :     Int nyp=ny;
    1143      159926 :     Int csupp=convSupport_p;
    1144      159926 :     const Int * flagstor=flags.getStorage(del);
    1145      159926 :     const Int * rowflagstor=rowFlags.getStorage(del);
    1146             : 
    1147             : 
    1148      159926 :     Int npart=nth;
    1149             :     
    1150             : 
    1151      159926 :     Int ix=0;
    1152      159926 : #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      159926 :     data.putStorage(datStorage, isCopy);
    1180      159926 :     griddedData.freeStorage(gridstor, delgrid);
    1181             :     //cerr << "Get min max " << min(data) << "   " << max(data) << endl;
    1182             :   }
    1183      159926 :   interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
    1184             : 
    1185      159926 : }
    1186             : 
    1187             : 
    1188             : 
    1189             : // Finalize the FFT to the Sky. Here we actually do the FFT and
    1190             : // return the resulting image
    1191        2097 : ImageInterface<Complex>& GridFT::getImage(Matrix<Float>& weights, Bool normalize) 
    1192             : {
    1193             :   //AlwaysAssert(lattice, AipsError);
    1194        2097 :   AlwaysAssert(gridder, AipsError);
    1195        2097 :   AlwaysAssert(image, AipsError);
    1196        2097 :   logIO() << LogOrigin("GridFT", "getImage") << LogIO::NORMAL;
    1197             : 
    1198        2097 :   if((griddedData.nelements() ==0) && (griddedData2.nelements()==0)){
    1199           0 :     throw(AipsError("Programmer error ...request for image without right order of calls"));
    1200             :   }
    1201        2097 :   weights.resize(sumWeight.shape());
    1202             : 
    1203        2097 :   convertArray(weights, sumWeight);
    1204             :   // If the weights are all zero then we cannot normalize
    1205             :   // otherwise we don't care.
    1206        2097 :   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        2097 :     if(useDoubleGrid_p)
    1233             :       {
    1234        2095 :         ArrayLattice<DComplex> darrayLattice(griddedData2);
    1235             :         //LatticeFFT::cfft2d(darrayLattice,false);
    1236        2095 :         ft_p.c2cFFT(darrayLattice, False);
    1237        2095 :         griddedData.resize(griddedData2.shape());
    1238        2095 :         convertArray(griddedData, griddedData2);
    1239             :         
    1240        2095 :         SynthesisUtilMethods::getResource("mem peak in getImage");
    1241             : 
    1242             :         //Don't need the double-prec grid anymore...
    1243        2095 :         griddedData2.resize();
    1244        2095 :         arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
    1245        2095 :         lattice=arrayLattice;
    1246        2095 :       }
    1247             :     else{
    1248           2 :       arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
    1249           2 :       lattice=arrayLattice;
    1250             :       
    1251             :       //LatticeFFT::cfft2d(*lattice,false);
    1252           2 :       ft_p.c2cFFT(*lattice, False);
    1253             :     }
    1254             : 
    1255             :     
    1256             :     
    1257             :     {
    1258        2097 :       Int inx = lattice->shape()(0);
    1259        2097 :       Int iny = lattice->shape()(1);
    1260        2097 :       Vector<Complex> correction(inx);
    1261        2097 :       correction=Complex(1.0, 0.0);
    1262             :       // Do the Grid-correction
    1263        2097 :       IPosition cursorShape(4, inx, 1, 1, 1);
    1264        2097 :       IPosition axisPath(4, 0, 1, 2, 3);
    1265        2097 :       LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
    1266        2097 :       LatticeIterator<Complex> lix(*lattice, lsx);
    1267     1547545 :       for(lix.reset();!lix.atEnd();lix++) {
    1268     1545448 :         Int pol=lix.position()(2);
    1269     1545448 :         Int chan=lix.position()(3);
    1270     1545448 :         if(weights(pol, chan)!=0.0) {
    1271     1499440 :           gridder->correctX1D(correction, lix.position()(1));
    1272     1499440 :           lix.rwVectorCursor()/=correction;
    1273     1499440 :           if(normalize) {
    1274         200 :             Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan));
    1275         200 :             lix.rwCursor()*=rnorm;
    1276             :           }
    1277             :           else {
    1278     1499240 :             Complex rnorm(Float(inx)*Float(iny));
    1279     1499240 :             lix.rwCursor()*=rnorm;
    1280             :           }
    1281             :         }
    1282             :         else {
    1283       46008 :           lix.woCursor()=0.0;
    1284             :         }
    1285             :       }
    1286        2097 :     }
    1287        2097 :     LatticeLocker lock1 (*(image), FileLocker::Write);
    1288        2097 :     if(!isTiled) {
    1289             :       // Check the section from the image BEFORE converting to a lattice 
    1290        4194 :       IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
    1291        2097 :       IPosition stride(4, 1);
    1292        4194 :       IPosition trc(blc+image->shape()-stride);
    1293             :       // Do the copy
    1294        2097 :       IPosition start(4, 0);
    1295             :       
    1296        2097 :       image->put(griddedData(blc, trc));
    1297        2097 :     }
    1298        2097 :   }
    1299        2097 :   image->flush();
    1300        2097 :   image->clearCache();
    1301             : 
    1302        2097 :   if(arrayLattice) arrayLattice=nullptr;
    1303        2097 :   if(lattice) lattice=nullptr;
    1304        2097 :   griddedData.resize();
    1305        2097 :   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          42 : 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          42 :   Bool retval = true;
    1342          42 :   Float elpadd=padding_p;
    1343          42 :   if(toVis_p && withImage)
    1344          19 :     elpadd=1.0;
    1345             :   //save the base class variables
    1346          42 :   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          42 :   outRec.define("cachesize", Int64(cachesize));
    1353          42 :   outRec.define("tilesize", tilesize);
    1354          42 :   outRec.define("convtype", convType);
    1355          42 :   outRec.define("uvscale", uvScale);
    1356          42 :   outRec.define("uvoffset", uvOffset);
    1357          42 :   outRec.define("istiled", isTiled);
    1358          42 :   outRec.define("maxabsdata", maxAbsData);
    1359          42 :   Vector<Int> center_loc(4), offset_loc(4);
    1360         210 :   for (Int k=0; k<4 ; k++){
    1361         168 :     center_loc(k)=centerLoc(k);
    1362         168 :     offset_loc(k)=offsetLoc(k);
    1363             :   }
    1364          42 :   outRec.define("centerloc", center_loc);
    1365          42 :   outRec.define("offsetloc", offset_loc);
    1366          42 :   outRec.define("padding", elpadd);
    1367          42 :   outRec.define("usezero", usezero_p);
    1368          42 :   outRec.define("nopadding", noPadding_p);
    1369          42 :   return retval;
    1370          42 : }
    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     1342319 : void GridFT::ok() {
    1431     1342319 :   AlwaysAssert(image, AipsError);
    1432     1342319 : }
    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        4049 : String GridFT::name() const {
    1502             : 
    1503        4049 :   return machineName_p;
    1504             : 
    1505             : 
    1506             : }
    1507             : 
    1508             : }//End of namespace refim
    1509             : } //# NAMESPACE CASA - END
    1510             : 

Generated by: LCOV version 1.16