LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - WPConvFunc.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 189 362 52.2 %
Date: 2024-10-10 11:40:37 Functions: 4 14 28.6 %

          Line data    Source code
       1             : //# WPConvFunc.cc: implementation of WPConvFunc
       2             : //# Copyright (C) 2007-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 adressed 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             : //#
      27             : //# $Id$
      28             : #include <sstream>
      29             : #include <iostream>
      30             : #include <iomanip>
      31             : #include <casacore/casa/Arrays/ArrayMath.h>
      32             : #include <casacore/casa/Arrays/Array.h>
      33             : #include <casacore/casa/Arrays/MaskedArray.h>
      34             : #include <casacore/casa/Arrays/Vector.h>
      35             : #include <casacore/casa/Arrays/Slice.h>
      36             : #include <casacore/casa/Arrays/Matrix.h>
      37             : #include <casacore/casa/Arrays/Cube.h>
      38             : #include <casacore/casa/OS/HostInfo.h>
      39             : #include <casacore/casa/Utilities/Assert.h>
      40             : #include <casacore/casa/Utilities/CompositeNumber.h>
      41             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      42             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      43             : 
      44             : #include <casacore/images/Images/ImageInterface.h>
      45             : #include <casacore/images/Images/PagedImage.h>
      46             : #include <casacore/images/Images/TempImage.h>
      47             : #include <casacore/casa/Logging/LogIO.h>
      48             : #include <casacore/casa/Logging/LogSink.h>
      49             : #include <casacore/casa/Logging/LogMessage.h>
      50             : 
      51             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      52             : #include <casacore/lattices/Lattices/SubLattice.h>
      53             : #include <casacore/lattices/LRegions/LCBox.h>
      54             : #include <casacore/lattices/LEL/LatticeExpr.h>
      55             : #include <casacore/lattices/Lattices/LatticeCache.h>
      56             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      57             : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
      58             : #include <msvis/MSVis/VisBuffer2.h>
      59             : #include <msvis/MSVis/VisibilityIterator2.h>
      60             : #include <casacore/scimath/Mathematics/FFTPack.h>
      61             : #include <msvis/MSVis/VisBuffer.h>
      62             : #include <msvis/MSVis/VisibilityIterator.h>
      63             : #include <synthesis/TransformMachines/SimplePBConvFunc.h> //por SINCOS
      64             : 
      65             : #include <synthesis/TransformMachines2/WPConvFunc.h>
      66             : #ifdef _OPENMP
      67             : #include <omp.h>
      68             : #endif
      69             : 
      70             : 
      71             : 
      72             : 
      73             : using namespace casacore;
      74             : namespace casa { //# NAMESPACE CASA - BEGIN
      75             : namespace refim{ //namespace for refactoring imager
      76             : 
      77             : using namespace casacore;
      78             : using namespace casa;
      79             : using namespace casacore;
      80             : using namespace casa::refim;
      81             :   typedef unsigned long long ooLong; 
      82           1 :  WPConvFunc::WPConvFunc(const Double minW, const Double maxW, const Double rmsW):
      83           1 :    actualConvIndex_p(-1), convSize_p(0), convSupport_p(0), minW_p(minW), maxW_p(maxW), rmsW_p(rmsW) {
      84             :    //
      85           1 :   }
      86           0 : WPConvFunc::WPConvFunc(const WPConvFunc& other):
      87           0 :    actualConvIndex_p(-1), convSize_p(0), convSupport_p(0){
      88             : 
      89           0 :     operator=(other);
      90           0 :   }
      91             : 
      92           0 :   WPConvFunc& WPConvFunc::operator=(const WPConvFunc& other){
      93           0 :     if(this != &other){
      94           0 :       uInt numConv=other.convFunctions_p.nelements();
      95           0 :       convFunctions_p.resize(numConv, true, false);
      96           0 :       convSupportBlock_p.resize(numConv, true, false);
      97           0 :       for (uInt k=0; k < numConv; ++k){
      98           0 :         convFunctions_p[k]=new Cube<Complex>();
      99           0 :         *(convFunctions_p[k])=*(other.convFunctions_p[k]);
     100           0 :         convSupportBlock_p[k]=new Vector<Int> ();
     101           0 :         *(convSupportBlock_p[k]) = *(other.convSupportBlock_p[k]);
     102             :       }
     103             :      
     104           0 :       convFunctionMap_p=other.convFunctionMap_p;
     105           0 :       convSizes_p.resize();
     106           0 :       convSizes_p=other.convSizes_p;
     107           0 :       actualConvIndex_p=other.actualConvIndex_p;
     108           0 :       convSize_p=other.convSize_p;
     109           0 :       convSupport_p.resize();
     110           0 :       convSupport_p=other.convSupport_p;
     111           0 :       convFunc_p.resize();
     112           0 :       convFunc_p=other.convFunc_p;
     113           0 :       wScaler_p=other.wScaler_p;
     114           0 :       convSampling_p=other.convSampling_p;
     115           0 :       nx_p=other.nx_p; 
     116           0 :       ny_p=other.ny_p;
     117           0 :       minW_p=other.minW_p;
     118           0 :       maxW_p=other.maxW_p;
     119           0 :       rmsW_p=other.rmsW_p;
     120             : 
     121             : 
     122             :       
     123             :     }
     124           0 :     return *this;
     125             :   }
     126             : 
     127           0 :   WPConvFunc::~WPConvFunc(){
     128             :     //usage of CountedPtr keeps this simple
     129             : 
     130           0 :   }
     131             : 
     132           0 :   WPConvFunc::WPConvFunc(const RecordInterface& rec):
     133           0 :    actualConvIndex_p(-1), convSize_p(0), convSupport_p(0){
     134           0 :     String error;
     135           0 :     if (!fromRecord(error, rec)) {
     136           0 :       throw (AipsError("Failed to create WPConvFunc: " + error));
     137             :     }
     138             : 
     139           0 :   }
     140             : 
     141         202 : void WPConvFunc::findConvFunction(const ImageInterface<Complex>& image, 
     142             :                                   const vi::VisBuffer2& vb,
     143             :                                     const Int& wConvSizeUser,
     144             :                                     const Vector<Double>& uvScale,
     145             :                                     const Vector<Double>& uvOffset, 
     146             :                                     const Float& padding,
     147             :                                     Int& convSampling,
     148             :                                     Cube<Complex>& convFunc, 
     149             :                                     Int& convSize,
     150             :                                     Vector<Int>& convSupport, Double& wScale){
     151         202 :    if(checkCenterPix(image)){ 
     152         201 :      convFunc.resize();
     153         201 :      convFunc.reference(convFunc_p);
     154         201 :      convSize=convSize_p;
     155         201 :      convSampling=convSampling_p;
     156         201 :      convSupport.resize();
     157         201 :      convSupport=convSupport_p;
     158         201 :     wScale=Float((convFunc.shape()(2)-1)*(convFunc.shape()(2)-1))/wScaler_p;
     159         201 :     return;
     160             :    }
     161           1 :    LogIO os;
     162           1 :    os << LogOrigin("WPConvFunc", "findConvFunction")  << LogIO::NORMAL;
     163             :    
     164             :    
     165             :   // Get the coordinate system
     166           1 :    CoordinateSystem coords(image.coordinates());
     167           1 :    Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
     168           1 :    nx_p=Int(image.shape()(directionIndex)); 
     169           1 :    ny_p=Int(image.shape()(directionIndex+1));
     170             :    
     171           1 :    Int wConvSize=wConvSizeUser;
     172             :    ////Automatic mode
     173             :    Double maxUVW;
     174           1 :    if(wConvSize < 1){
     175           0 :      maxUVW=rmsW_p < 0.5*(minW_p+maxW_p) ? 1.05*maxW_p: (rmsW_p /(0.5*((minW_p)+maxW_p))*1.05*maxW_p) ;
     176           0 :      wConvSize=Int(maxUVW*fabs(sin(fabs(image.coordinates().increment()(0))*max(nx_p, ny_p)/2.0)));  
     177           0 :      convSupport.resize(wConvSize);
     178             :    }
     179             :    else{    
     180           1 :      if(maxW_p> 0.0)
     181           0 :        maxUVW= 1.05*maxW_p;
     182             :      else
     183           1 :        maxUVW=0.25/abs(image.coordinates().increment()(0));
     184             :      
     185             :    }
     186           1 :    if(wConvSize>1) {
     187           1 :      os << "W projection using " << wConvSize << " planes" << LogIO::POST;
     188             :      
     189             :      os << "Using maximum possible W = " << maxUVW
     190           1 :         << " (wavelengths)" << LogIO::POST;
     191             :     
     192           1 :      Double invLambdaC=vb.getFrequency(0,0)/C::c;
     193             :      os << "Typical wavelength = " << 1.0/invLambdaC
     194           1 :         << " (m)" << LogIO::POST;
     195             :      
     196             :     
     197           1 :      wScale=Float((wConvSize-1)*(wConvSize-1))/maxUVW;
     198             :      //wScale=Float(wConvSize-1)/maxUVW;
     199           1 :      wScaler_p=maxUVW;;
     200           1 :      os << "Scaling in W (at maximum W) = " << 1.0/wScale
     201           1 :         << " wavelengths per pixel" << LogIO::POST;
     202             :    }
     203             : 
     204           1 :    Int planesPerChunk=100;
     205             : 
     206             : 
     207           1 :    if(wConvSize>1) {
     208           1 :      Int maxMemoryMB=min(uInt64(HostInfo::memoryTotal(true)), uInt64(HostInfo::memoryFree()))/1024;
     209             :      ////Common you have to have 4 GB...memoryFree sometimes is whacky
     210           1 :      if(maxMemoryMB < 4000)
     211           0 :        maxMemoryMB=4000;
     212           1 :      convSize=max(Int(nx_p*padding),Int(ny_p*padding));
     213             :      ///Do the same thing as in WProject::init
     214           1 :      CompositeNumber cn(convSize);    
     215           1 :      convSize    = cn.nextLargerEven(convSize);
     216             :     //nominal  100 wprojplanes above that you may (or not) go swapping
     217             :      
     218           1 :      planesPerChunk=Int((Double(maxMemoryMB)/8.0*1024.0*1024.0)/Double(convSize)/Double(convSize));
     219             :      //cerr << "planesPerChunk" << planesPerChunk << endl;
     220           1 :      planesPerChunk=min(planesPerChunk, 100);
     221             :      //    CompositeNumber cn(Int(maxConvSizeConsidered/2.0)*2);
     222           1 :     convSampling_p=4;
     223             :     
     224             :     //convSize=min(convSize,(Int)cn.nearestEven(Int(maxConvSizeConsidered/2.0)*2));
     225             : 
     226           1 :    }
     227             :    else{
     228           0 :      convSampling_p=1;
     229           0 :     convSize=max(Int(nx_p*padding),Int(ny_p*padding));
     230             :    }
     231           1 :    convSampling=convSampling_p;
     232           1 :    Int maxConvSize=convSize;
     233           1 :    convSupport.resize(wConvSize);
     234           1 :    convSupport.set(-1);
     235             :    ////set sampling
     236           1 :    AlwaysAssert(directionIndex>=0, AipsError);
     237           1 :    DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
     238           1 :    Vector<Double> sampling;
     239           1 :    sampling = dc.increment();
     240           1 :    sampling*=Double(convSampling_p);
     241             :    //sampling*=Double(max(nx,ny))/Double(convSize);
     242           1 :    sampling[0]*=Double(padding*Float(nx_p))/Double(convSize);
     243           1 :    sampling[1]*=Double(padding*Float(ny_p))/Double(convSize);
     244             :    /////
     245           1 :    Int inner=convSize/convSampling_p;
     246             :    ConvolveGridder<Double, Complex>
     247           2 :      ggridder(IPosition(2, inner, inner), uvScale, uvOffset, "SF");
     248             :    
     249           1 :    Int nchunk=wConvSize/planesPerChunk;
     250           1 :    if((wConvSize%planesPerChunk) !=0)
     251           1 :      nchunk +=1;
     252           1 :    Vector<Int> chunksize(nchunk, planesPerChunk);
     253           1 :    if((wConvSize%planesPerChunk) !=0)
     254           1 :     chunksize(nchunk-1)=wConvSize%planesPerChunk;
     255             :    
     256           1 :    Int warner=0;
     257           1 :    Vector<Complex> maxes(wConvSize);
     258             :   // Bool maxdel;
     259             :   // Complex* maxptr=maxes.getStorage(maxdel);
     260           1 :   Matrix<Complex> corr(inner, inner);
     261           1 :   Vector<Complex> correction(inner);
     262          27 :    for (Int iy=-inner/2;iy<inner/2;iy++) {
     263             :      
     264          26 :      ggridder.correctX1D(correction, iy+inner/2);
     265          26 :      corr.row(iy+inner/2)=correction;
     266             :    }
     267             :    Bool cpcor;
     268             :   
     269           1 :    Complex *cor=corr.getStorage(cpcor);
     270           1 :    Vector<Int>pcsupp;
     271           1 :    pcsupp=convSupport;
     272             :    Bool delsupstor;
     273           1 :    Int* suppstor=pcsupp.getStorage(delsupstor);
     274           1 :    Double s1=sampling(1);
     275           1 :    Double s0=sampling(0);
     276             :    ///////////Por FFTPack
     277           1 :    Vector<Float> wsave(2*convSize*convSize+15);
     278           1 :    Int lsav=2*convSize*convSize+15;
     279             :    Bool wsavesave;
     280           1 :    Float *wsaveptr=wsave.getStorage(wsavesave);
     281             :    Int ier;
     282           1 :    FFTPack::cfft2i(convSize, convSize, wsaveptr, lsav, ier);
     283             :    ////////// 
     284           1 :    Matrix<Complex> screen(convSize, convSize);
     285           1 :    makeGWplane(screen, 0, s0, s1, wsaveptr, lsav, inner, cor, wScale);
     286           1 :    Float maxconv=abs(screen(0,0));
     287           2 :    for (Int chunkId=nchunk-1; chunkId >= 0;  --chunkId){
     288             :      //cerr << "chunkId " << chunkId << endl;
     289           1 :      Cube<Complex> convFuncSect( maxConvSize/2-1, maxConvSize/2-1, chunksize(chunkId));
     290           1 :      convFuncSect.set(0.0);
     291           1 :      Bool convFuncStor=false;
     292           1 :      Complex *convFuncPtr=convFuncSect.getStorage(convFuncStor);
     293             :       //////openmp like to share reference param ...but i don't like to share
     294           1 :      Int cpConvSize=maxConvSize;
     295             :      //cerr << "orig convsize " << convSize << endl;
     296             :      // Int cpWConvSize=wConvSize;
     297           1 :      Double cpWscale=wScale;
     298           1 :      Int wstart=planesPerChunk*chunkId;
     299           1 :      Int wend=wstart+chunksize(chunkId)-1;
     300             :      
     301             : #ifdef _OPENMP
     302           1 :      omp_set_nested(0);
     303           1 :      Int nthreads=omp_get_max_threads();
     304           1 :      nthreads=min(nthreads, chunksize(chunkId));
     305           1 :      omp_set_num_threads(nthreads);
     306             :      
     307             : #endif
     308           1 : #pragma omp parallel for default(none) firstprivate(/*cpWConvSize,*/ cpConvSize, convFuncPtr, s0, s1, wsaveptr, lsav, cor, inner, cpWscale,  wstart, wend) schedule(dynamic, 1)
     309             :      
     310             : 
     311             :      for (Int iw=wstart; iw < (wend+1)  ; ++iw) {
     312             :        Matrix<Complex> screen1(cpConvSize, cpConvSize);
     313             :        makeGWplane(screen1, iw, s0, s1, wsaveptr, lsav, inner, cor, cpWscale);
     314             :        ooLong offset=ooLong(ooLong(iw-wstart)*ooLong(cpConvSize/2-1)*ooLong(cpConvSize/2-1));
     315             :        for (ooLong y=0; y< ooLong(cpConvSize/2)-1; ++y){
     316             :          for (ooLong x=0; x< ooLong(cpConvSize/2)-1; ++x){
     317             :            ////////convFuncPtr[offset+y*(convSize/2-1)+x] = quarter(x,y);
     318             :            convFuncPtr[offset+y*ooLong(cpConvSize/2-1)+x] = screen1(x,y);
     319             :          }
     320             :        }
     321             : 
     322             :      }//iw
     323             : 
     324           1 :      convFuncSect.putStorage(convFuncPtr, convFuncStor);
     325          51 :      for (uInt iw=0; iw< uInt(chunksize(chunkId)); ++iw){
     326          50 :        convFuncSect.xyPlane(iw)=convFuncSect.xyPlane(iw)/(maxconv);
     327             :      }
     328           1 :      convFuncPtr=convFuncSect.getStorage(convFuncStor);
     329           1 :      Int thischunkSize=chunksize(chunkId);
     330             :      //cerr << "chunkId* planesPerChunk " << chunkId* planesPerChunk << "  chunksize " << thischunkSize << endl;
     331           1 : #pragma omp parallel for default(none) firstprivate(suppstor, cpConvSize, /*cpWConvSize,*/ convFuncPtr, maxConvSize, thischunkSize, wstart, planesPerChunk, chunkId) reduction(+: warner)      
     332             :      for (Int iw=0; iw<thischunkSize; iw++) {
     333             :        Bool found=false;
     334             :        Int trial=0;
     335             :        ooLong ploffset=(ooLong)(cpConvSize/2-1)*(ooLong)(cpConvSize/2-1)*(ooLong)iw;
     336             :        for (trial=cpConvSize/2-2;trial>0;trial--) {
     337             :          // if((abs(convFunc(trial,0,iw))>1e-3)||(abs(convFunc(0,trial,iw))>1e-3) ) {
     338             :          if((abs(convFuncPtr[(ooLong)(trial)+ploffset])>1e-3)||(abs(convFuncPtr[(ooLong)(trial*(cpConvSize/2-1))+ploffset])>1e-3) ) {
     339             :            //cout <<"iw " << iw << " x " << abs(convFunc(trial,0,iw)) << " y " 
     340             :            //   <<abs(convFunc(0,trial,iw)) << endl; 
     341             :            found=true;
     342             :            break;
     343             :          }
     344             :        }
     345             :        Int trueIw=iw+chunkId* planesPerChunk;
     346             :        if(found) {
     347             :          suppstor[trueIw]=Int(0.5+Float(trial)/Float(convSampling_p))+1;
     348             :          if(suppstor[trueIw]*convSampling_p*2 >= maxConvSize){
     349             :            suppstor[trueIw]=cpConvSize/2/convSampling_p-1;
     350             :            ++warner;
     351             :          }
     352             :        }
     353             :        else{
     354             :          suppstor[trueIw]=cpConvSize/2/convSampling_p-1;
     355             :          ++warner;
     356             :        }
     357             :      }
     358           1 :      convFuncSect.putStorage(convFuncPtr, convFuncStor);
     359           1 :      if(chunkId==(nchunk-1)){
     360           1 :          Int newConvSize=2*(suppstor[wConvSize-1]+2)*convSampling;
     361           1 :          if(newConvSize < convSize){
     362           1 :            convFunc.resize((newConvSize/2-1),
     363           1 :                   (newConvSize/2-1),
     364             :                            wConvSize);
     365           1 :            convSize=newConvSize;
     366             :          }
     367             :          else{
     368           0 :            convFunc.resize((convSize/2-1),
     369           0 :                   (convSize/2-1),
     370             :                            wConvSize);
     371             :          }               
     372             :      }
     373           1 :     IPosition blc(3, 0,0,wstart);
     374           1 :     IPosition trc(3, (convSize/2-2),(convSize/2-2),wend);
     375           2 :     convFunc(blc, trc)=convFuncSect(IPosition(3, 0,0,0), IPosition(3, (convSize/2-2),
     376           2 :                                                                   (convSize/2-2), thischunkSize-1));
     377             : 
     378             : 
     379           1 :    }//chunkId
     380           1 :    corr.putStorage(cor, cpcor);
     381           1 :    pcsupp.putStorage(suppstor, delsupstor);
     382           1 :    convSupport=pcsupp;
     383           1 :    Double pbSum=0.0;
     384          10 :    for (Int iy=-convSupport(0);iy<=convSupport(0);iy++) {
     385          90 :      for (Int ix=-convSupport(0);ix<=convSupport(0);ix++) {
     386          81 :        pbSum+=real(convFunc(abs(ix)*convSampling_p,abs(iy)*convSampling_p,0));
     387             :      }
     388             :    }
     389           1 :    if(pbSum>0.0) {
     390           1 :      convFunc*=Complex(1.0/pbSum,0.0);
     391             :    }
     392             :    else {
     393             :      os << "Convolution function integral is not positive"
     394           0 :         << LogIO::EXCEPTION;
     395             :   } 
     396             : 
     397             : 
     398           1 :     os << "Convolution support = " << convSupport*convSampling_p
     399             :           << " pixels in Fourier plane"
     400           1 :           << LogIO::POST;
     401           1 :     convSupportBlock_p.resize(actualConvIndex_p+1);
     402           1 :     convSupportBlock_p[actualConvIndex_p]= new Vector<Int>();
     403           1 :     convSupportBlock_p[actualConvIndex_p]->assign(convSupport);
     404           1 :     convFunctions_p.resize(actualConvIndex_p+1);
     405           1 :     convFunctions_p[actualConvIndex_p]= new Cube<Complex>(convFunc);
     406           1 :     convSizes_p.resize(actualConvIndex_p+1, true);
     407           1 :     convSizes_p(actualConvIndex_p)=convSize;
     408           1 :     Int maxMemoryMB=HostInfo::memoryTotal(true)/1024;
     409             :   Int memoryMB;
     410           1 :   memoryMB = Int(Double(convSize/2-1)*Double(convSize/2-1)*
     411           1 :                  Double(wConvSize)*8.0/1024.0/1024.0);
     412             :   os << "Memory used in gridding function = "
     413             :      << memoryMB << " MB from maximum "
     414           1 :           << maxMemoryMB << " MB" << LogIO::POST;
     415           1 :   convSampling=convSampling_p;
     416           1 :   wScale=Float((wConvSize-1)*(wConvSize-1))/wScaler_p;
     417             : 
     418           1 : }//end func
     419             : 
     420          51 :   void WPConvFunc::makeGWplane(Matrix<Complex>& screen, const Int iw, Double s0, Double s1, Float *& wsaveptr, Int& lsav, Int& inner, Complex*& cor, Double&cpWscale){
     421             : 
     422          51 :     Int cpConvSize=screen.shape()(0);
     423             :     //cerr << "cpConvSize " << cpConvSize << "   shape " << screen.shape() << endl;
     424          51 :     screen.set(0.0);
     425             :      Bool cpscr;
     426          51 :      Complex *scr=screen.getStorage(cpscr);
     427          51 :       Double twoPiW=2.0*C::pi*Double(iw*iw)/cpWscale;
     428        1377 :          for (Int iy=-inner/2;iy<inner/2;iy++) {
     429        1326 :            Double m=s1*Double(iy);
     430        1326 :            Double msq=m*m;
     431             :            //////Int offset= (iy+convSize/2)*convSize;
     432             :            ///fftpack likes it flipped
     433        1326 :            ooLong offset= (iy>-1 ? ooLong(iy) : ooLong(iy+cpConvSize))*ooLong(cpConvSize);
     434       35802 :            for (Int ix=-inner/2;ix<inner/2;ix++) {
     435             :              //////       Int ind=offset+ix+convSize/2;
     436             :              ///fftpack likes it flipped
     437       34476 :              ooLong ind=offset+(ix > -1 ? ooLong(ix) : ooLong(ix+cpConvSize));
     438       34476 :              Double l=s0*Double(ix);
     439       34476 :              Double rsq=l*l+msq;
     440       34476 :              if(rsq<1.0) {
     441       34476 :                Double phase=twoPiW*(sqrt(1.0-rsq)-1.0);
     442             :                Double cval, sval;
     443       34476 :                SINCOS(phase, sval, cval);
     444       34476 :                Complex comval(cval, sval);
     445       34476 :                scr[ind]=(cor[ix+inner/2+ (iy+inner/2)*inner])*comval;
     446             :                //screen(ix+convSize/2, iy+convSize/2)=comval; 
     447             :              }
     448             :            }
     449             :          }
     450             :          ////Por FFTPack
     451          51 :          Vector<Float>work(2*cpConvSize*cpConvSize);
     452          51 :          Int lenwrk=2*cpConvSize*cpConvSize;
     453             :          Bool worksave;
     454          51 :          Float *workptr=work.getStorage(worksave);
     455             :          Int ier;
     456          51 :          FFTPack::cfft2f(cpConvSize, cpConvSize, cpConvSize, scr, wsaveptr, lsav, workptr, lenwrk, ier);
     457             :        
     458          51 :        screen.putStorage(scr, cpscr);
     459             : 
     460          51 :   } 
     461             : 
     462             : 
     463         202 : Bool WPConvFunc::checkCenterPix(const ImageInterface<Complex>& image){
     464             : 
     465         202 :   CoordinateSystem imageCoord=image.coordinates();
     466         202 :   MDirection wcenter;  
     467         202 :   Int directionIndex=imageCoord.findCoordinate(Coordinate::DIRECTION);
     468             :   DirectionCoordinate
     469         202 :     directionCoord=imageCoord.directionCoordinate(directionIndex);
     470         202 :   Vector<Double> incr=directionCoord.increment();
     471         202 :   nx_p=image.shape()(directionIndex);
     472         202 :   ny_p=image.shape()(directionIndex+1);
     473             : 
     474             : 
     475             :   //Images with same number of pixels and increments can have the same conv functions
     476         202 :   ostringstream oos;
     477         202 :   oos << std::setprecision(6);
     478             : 
     479         202 :   oos << nx_p << "_"<< fabs(incr(0)) << "_";
     480         202 :   oos << ny_p << "_"<< fabs(incr(1));
     481         202 :   String imageKey(oos);
     482             : 
     483         202 :   if(convFunctionMap_p.size( ) == 0){
     484           1 :     convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(imageKey, 0));
     485           1 :     actualConvIndex_p=0;
     486           1 :     return false;
     487             :   }
     488             :    
     489         201 :   if( convFunctionMap_p.find(imageKey) == convFunctionMap_p.end( ) ){
     490           0 :     actualConvIndex_p=convFunctionMap_p.size( );
     491           0 :     convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(imageKey,actualConvIndex_p));
     492           0 :     return false;
     493             :   }
     494             :   else{
     495         201 :     actualConvIndex_p=convFunctionMap_p[imageKey];
     496         201 :     convFunc_p.resize(); // break any reference
     497         201 :     convFunc_p.reference(*convFunctions_p[actualConvIndex_p]);
     498         201 :     convSupport_p.resize();
     499         201 :     convSupport_p.reference(*convSupportBlock_p[actualConvIndex_p]);
     500         201 :     convSize_p=convSizes_p[actualConvIndex_p];
     501             : 
     502             :   }
     503             : 
     504         201 :   return true;
     505         202 : }
     506             : 
     507           0 : Bool WPConvFunc::toRecord(RecordInterface& rec){
     508             : 
     509           0 :   Int numConv=convFunctions_p.nelements();
     510             :   try{
     511           0 :     rec.define("numconv", numConv);
     512           0 :     auto convptr = convFunctionMap_p.begin( );
     513           0 :     for (Int k=0; k < numConv; ++k, ++convptr){
     514           0 :       rec.define("convfunctions"+String::toString(k), *(convFunctions_p[k]));
     515           0 :       rec.define("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
     516           0 :       rec.define("key"+String::toString(k), convptr->first);
     517           0 :       rec.define("val"+String::toString(k), convptr->second);
     518             :     }
     519           0 :     rec.define("convsizes", convSizes_p);
     520           0 :     rec.define("actualconvIndex",actualConvIndex_p);
     521           0 :     rec.define("convsize", convSize_p);
     522           0 :     rec.define("convsupport", convSupport_p);
     523           0 :     rec.define("convfunc",convFunc_p);
     524           0 :     rec.define("wscaler", wScaler_p);
     525           0 :     rec.define("convsampling", convSampling_p);
     526           0 :     rec.define("nx", nx_p);
     527           0 :     rec.define("ny", ny_p);
     528             :   }
     529           0 :   catch(AipsError x) {
     530           0 :     return false;
     531           0 :   }
     532           0 :   return true;
     533             : 
     534             :  
     535             : 
     536             : }
     537             : 
     538           0 :  Bool WPConvFunc::fromRecord(String& err, const RecordInterface& rec){
     539             :   
     540           0 :   Int numConv=0;
     541             :   try{
     542           0 :     rec.get("numconv", numConv);
     543           0 :     convFunctions_p.resize(numConv, true, false);
     544           0 :     convSupportBlock_p.resize(numConv, true, false);
     545           0 :     convFunctionMap_p.clear( );
     546           0 :     for (Int k=0; k < numConv; ++k){
     547           0 :       convFunctions_p[k]=new Cube<Complex>();
     548           0 :       convSupportBlock_p[k]=new Vector<Int>();
     549           0 :       rec.get("convfunctions"+String::toString(k), *(convFunctions_p[k]));
     550           0 :       rec.get("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
     551           0 :       String key;
     552             :       Int val;
     553           0 :       rec.get("key"+String::toString(k), key);
     554           0 :       rec.get("val"+String::toString(k), val);
     555           0 :       convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(key,val));
     556           0 :     }
     557           0 :     rec.get("convsizes", convSizes_p);
     558           0 :     rec.get("actualconvIndex",actualConvIndex_p);
     559           0 :     rec.get("convsize", convSize_p);
     560           0 :     rec.get("convsupport", convSupport_p);
     561           0 :     rec.get("convfunc",convFunc_p);
     562           0 :     if(rec.isDefined("wscaler"))
     563           0 :       rec.get("wscaler", wScaler_p);
     564           0 :     rec.get("convsampling", convSampling_p);
     565           0 :     rec.get("nx", nx_p);
     566           0 :     rec.get("ny", ny_p);
     567             :   }
     568           0 :   catch(AipsError x) {
     569           0 :     err=x.getMesg();
     570           0 :     return false;
     571           0 :   }
     572           0 :   return true;
     573             : 
     574             :   }
     575           0 :   Bool WPConvFunc::makeWConvFuncs(Cube<Complex>& wconv, Vector<Int>& supports,  CoordinateSystem& cs, const Int& npix, const Vector<Double>& wVals){
     576           0 :     uInt nw=wVals.nelements();
     577           0 :     supports.resize(nw);
     578             :     //cerr << "wVals" << wVals << endl;
     579           0 :     Double wVal=wVals(nw-1);
     580           0 :     Matrix<Complex> screen;
     581           0 :     makeSkyWFunc(screen, cs, npix, wVal);
     582           0 :     FFT2D ft(True);
     583             :     Bool isCopyScr;
     584           0 :     Complex* scr=screen.getStorage(isCopyScr);
     585           0 :     ft.c2cFFT(scr, npix, npix);
     586           0 :     screen.putStorage(scr,isCopyScr);
     587           0 :     Int sup=findSupport(screen);
     588             :     ///TESTOO
     589             :     //sup=256;
     590             :     /////
     591           0 :     if (sup < 1)
     592           0 :       throw(AipsError("Could not find support for w term"));
     593           0 :     Int convSize=2*(sup+2);
     594           0 :     if (convSize > npix)
     595           0 :       convSize=npix;
     596           0 :     wconv.resize(convSize, convSize, nw);
     597           0 :     IPosition blc(2, npix/2-convSize/2, npix/2-convSize/2);
     598           0 :     IPosition trc(2, npix/2+convSize/2-1, npix/2+convSize/2-1);
     599           0 :     wconv.xyPlane(nw-1).assign(screen(blc, trc));
     600           0 :     supports(nw-1)=sup;
     601           0 :     for(Int k=0; k < (nw-1); ++k){
     602           0 :       wVal=wVals[k];
     603           0 :       makeSkyWFunc(screen, cs, npix, wVal);
     604           0 :       Complex* scr=screen.getStorage(isCopyScr);
     605           0 :       ft.c2cFFT(scr, npix, npix);
     606           0 :       screen.putStorage(scr,isCopyScr);
     607           0 :       sup=findSupport(screen);
     608           0 :       supports[k]=sup;
     609           0 :       wconv.xyPlane(k)=screen(blc, trc);
     610             :     }
     611             :     
     612             :     
     613             :     
     614           0 :     return True;
     615           0 :   }
     616           0 :   Int WPConvFunc::findSupport(Matrix<Complex>& arr){
     617           0 :     Int shape=arr.shape()[0];
     618           0 :     Float maxval=real(max((fabs(arr))));
     619           0 :     Float minval=real(min((fabs(arr))));
     620           0 :     Float maxshift=maxval-minval;
     621             :     //cerr << "####maxval " << maxval << " shift " << maxshift << endl;
     622           0 :     Int trial=0;
     623           0 :     Bool found=False;
     624           0 :     Float sqrt_2=1.0/sqrt(2);
     625           0 :     while(!found && (trial < (shape/2))){
     626           0 :       Float frac=(fabs( arr(shape/2, (shape/2+ trial) ) )-minval)/maxshift;
     627           0 :       if( frac < 1e-2){
     628           0 :         found=True;
     629             :         //cerr << "found at trial " << trial << endl;
     630             :         
     631             :       }
     632           0 :       ++trial;
     633             :       
     634             :     }
     635             :     
     636           0 :     if(!found)
     637           0 :       return shape/2;
     638             :       
     639           0 :     return trial;
     640             :     
     641             :   }
     642           0 :    Bool WPConvFunc::makeSkyWFunc(Matrix<Complex>& screen,
     643             :        const CoordinateSystem& cs, const Int& npix, const Double& wVal){
     644             :      
     645           0 :     screen.resize(npix, npix);
     646             :     //cerr << "SCR shape " << screen.shape() << endl;
     647           0 :     screen.set(0.0);
     648             :     //Assuming largest wVals is latest
     649           0 :     Double scale1=cs.increment()(0); 
     650           0 :     Double scale2=cs.increment()(1); 
     651           0 :     Double uvoff=Double(npix)/2.0;
     652             :     Bool isScrCopy;
     653           0 :     Complex *scr=screen.getStorage(isScrCopy);
     654             :     
     655           0 :     Double twoPiW=2.0*C::pi* wVal;
     656           0 :       for (uInt iy=0; iy < uInt(npix); ++iy){
     657           0 :          Double m=scale2*(Double(iy)-uvoff);
     658           0 :          Double msq=m*m;
     659           0 :          for(uInt ix=0; ix < uInt(npix); ++ix){
     660           0 :           Double l=scale1*(Double(ix)-uvoff);
     661           0 :           Double rsq=l*l+msq;
     662           0 :           if(rsq<1.0) {
     663           0 :                Double phase=twoPiW*(sqrt(1.0-rsq)-1.0);
     664             :                Double cval, sval;
     665           0 :                SINCOS(phase, sval, cval);
     666             :            //cerr << "ix " << ix << " iy " << iy << " pix " << ix+ iy*npix << endl;
     667           0 :                scr[ix+iy*npix]=Complex(cval, sval);
     668             :            //screen(ix, iy)=Complex(cval, sval);
     669             :           }
     670             :              }
     671             :            
     672             :            
     673             :       }
     674           0 :       screen.putStorage(scr, isScrCopy);
     675             :         
     676             :         
     677             :         
     678             :     
     679             :       
     680           0 :     return True;
     681             :     
     682             :     
     683             :      
     684             :    }
     685             : 
     686             : 
     687             : 
     688             : } //end of namespace refim
     689             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16