LCOV - code coverage report
Current view: top level - synthesis/TransformMachines - GridFT.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 392 610 64.3 %
Date: 2024-10-04 18:58:15 Functions: 16 28 57.1 %

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

Generated by: LCOV version 1.16