LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - SimplePBConvFunc.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 0 516 0.0 %
Date: 2023-11-02 14:27:30 Functions: 0 20 0.0 %

          Line data    Source code
       1             : //# SimplePBConvFunc.cc: implementation of SimplePBConvFunc
       2             : //# Copyright (C) 2007-2020
       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 adressed as follows:
      20             : //#        Internet email: aips2-request@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 <casacore/casa/Arrays/ArrayMath.h>
      29             : #include <casacore/casa/Arrays/Array.h>
      30             : #include <casacore/casa/Arrays/MaskedArray.h>
      31             : #include <casacore/casa/Arrays/Vector.h>
      32             : #include <casacore/casa/Arrays/Slice.h>
      33             : #include <casacore/casa/Arrays/Slicer.h>
      34             : #include <casacore/casa/Arrays/Matrix.h>
      35             : #include <casacore/casa/Arrays/Cube.h>
      36             : #include <casacore/casa/OS/Timer.h>
      37             : #include <casacore/casa/Utilities/Assert.h>
      38             : #include <casacore/casa/Quanta/MVTime.h>
      39             : #include <casacore/casa/Quanta/MVAngle.h>
      40             : #include <casacore/measures/Measures/MeasTable.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/images/Images/SubImage.h>
      48             : #include <casacore/casa/Logging/LogIO.h>
      49             : #include <casacore/casa/Logging/LogSink.h>
      50             : #include <casacore/casa/Logging/LogMessage.h>
      51             : 
      52             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      53             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      54             : #include <casacore/lattices/Lattices/SubLattice.h>
      55             : #include <casacore/lattices/LRegions/LCBox.h>
      56             : #include <casacore/lattices/LEL/LatticeExpr.h>
      57             : #include <casacore/lattices/Lattices/LatticeCache.h>
      58             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      59             : 
      60             : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
      61             : 
      62             : #include <msvis/MSVis/VisBuffer.h>
      63             : #include <msvis/MSVis/VisibilityIterator.h>
      64             : 
      65             : #include <synthesis/TransformMachines2/SimplePBConvFunc.h>
      66             : #include <synthesis/TransformMachines2/SkyJones.h>
      67             : 
      68             : #include <casacore/casa/Utilities/CompositeNumber.h>
      69             : #include <iomanip>
      70             : #include <math.h>
      71             : 
      72             : using namespace casacore;
      73             : namespace casa { //# NAMESPACE CASA - BEGIN
      74             : namespace refim {//# namespace for imaging refactor
      75             : using namespace casacore;
      76             : using namespace casa;
      77             : using namespace casacore;
      78             : using namespace casa::refim;
      79             : 
      80           0 : SimplePBConvFunc::SimplePBConvFunc(): nchan_p(-1),
      81             :         npol_p(-1), pointToPix_p(), directionIndex_p(-1), thePix_p(0),
      82             :         filledFluxScale_p(false),doneMainConv_p(0),
      83             :                                       
      84           0 :                                       calcFluxScale_p(true), usePointingTable_p(False), actualConvIndex_p(-1), convSize_p(0), convSupport_p(0), pointingPix_p()    {
      85             :     //
      86             : 
      87           0 :     pbClass_p=PBMathInterface::COMMONPB;
      88           0 :     ft_p=FFT2D(true);
      89           0 :     usePointingTable_p=False;
      90           0 : }
      91             : 
      92           0 :   SimplePBConvFunc::SimplePBConvFunc(const PBMathInterface::PBClass typeToUse): 
      93             :     nchan_p(-1),npol_p(-1),pointToPix_p(),
      94             :     directionIndex_p(-1), thePix_p(0), filledFluxScale_p(false),doneMainConv_p(0), 
      95           0 :     calcFluxScale_p(true), usePointingTable_p(False), actualConvIndex_p(-1), convSize_p(0), convSupport_p(0), pointingPix_p() {
      96             :     //
      97           0 :     pbClass_p=typeToUse;
      98           0 :     ft_p=FFT2D(true);
      99           0 :     usePointingTable_p=False;
     100           0 :   }
     101           0 :   SimplePBConvFunc::SimplePBConvFunc(const RecordInterface& rec, const Bool calcfluxneeded)
     102             :   : nchan_p(-1),npol_p(-1),pointToPix_p(), directionIndex_p(-1), thePix_p(0), filledFluxScale_p(false),
     103             :     doneMainConv_p(0), 
     104           0 :     calcFluxScale_p(calcfluxneeded), usePointingTable_p(False), actualConvIndex_p(-1), convSize_p(0), convSupport_p(0), pointingPix_p() 
     105             :   {
     106           0 :     String err;
     107           0 :     fromRecord(err, rec, calcfluxneeded);
     108           0 :     ft_p=FFT2D(true);
     109           0 :     usePointingTable_p=False;
     110           0 :   }
     111           0 :   SimplePBConvFunc::~SimplePBConvFunc(){
     112             :     //
     113             : 
     114           0 :   }
     115             : 
     116           0 :   void SimplePBConvFunc::storeImageParams(const ImageInterface<Complex>& iimage,
     117             :                                           const vi::VisBuffer2& vb){
     118             :     //image signature changed...rather simplistic for now
     119           0 :     if((iimage.shape().product() != nx_p*ny_p*nchan_p*npol_p) || nchan_p < 1){
     120           0 :       csys_p=iimage.coordinates();
     121           0 :       Int coordIndex=csys_p.findCoordinate(Coordinate::DIRECTION);
     122           0 :       AlwaysAssert(coordIndex>=0, AipsError);
     123           0 :       directionIndex_p=coordIndex;
     124           0 :       dc_p=csys_p.directionCoordinate(directionIndex_p);
     125           0 :       ObsInfo imInfo=csys_p.obsInfo();
     126           0 :       String tel= imInfo.telescope();
     127           0 :       MPosition pos;
     128           0 :       MSColumns mscol(vb.ms());
     129           0 :       if (vb.subtableColumns().observation().nrow() > 0) {
     130           0 :         tel =vb.subtableColumns().observation().telescopeName()(mscol.observationId()(0));
     131             :       }
     132           0 :       if (tel.length() == 0 || !tel.contains("VLA") ||
     133           0 :           !MeasTable::Observatory(pos,tel)) {
     134             :         // unknown observatory, use first antenna
     135           0 :           Int ant1=vb.antenna1()(0);
     136           0 :           pos=vb.subtableColumns().antenna().positionMeas()(ant1);
     137             :       }
     138           0 :       imInfo.setTelescope(tel);
     139           0 :       csys_p.setObsInfo(imInfo);
     140             :       //Store this to build epochs via the time access of visbuffer later
     141           0 :       timeMType_p=MEpoch::castType(mscol.timeMeas()(0).getRef().getType());
     142           0 :       timeUnit_p=Unit(mscol.timeMeas().measDesc().getUnits()(0).getName());
     143             :       // timeUnit_p=Unit("s");
     144             :       //cout << "UNIT " << timeUnit_p.getValue() << " name " << timeUnit_p.getName()  << endl;
     145           0 :       pointFrame_p=MeasFrame(imInfo.obsDate(), pos);
     146           0 :       MDirection::Ref elRef(dc_p.directionType(), pointFrame_p);
     147             :       //For now we set the conversion from this direction 
     148           0 :       pointToPix_p=MDirection::Convert( MDirection(), elRef);
     149           0 :       nx_p=iimage.shape()(coordIndex);
     150           0 :       ny_p=iimage.shape()(coordIndex+1);
     151           0 :       pointingPix_p.resize(nx_p, ny_p);
     152           0 :       pointingPix_p.set(false);
     153           0 :       coordIndex=csys_p.findCoordinate(Coordinate::SPECTRAL);
     154           0 :       Int pixAxis=csys_p.pixelAxes(coordIndex)[0];
     155           0 :       nchan_p=iimage.shape()(pixAxis);
     156           0 :       coordIndex=csys_p.findCoordinate(Coordinate::STOKES);
     157           0 :       pixAxis=csys_p.pixelAxes(coordIndex)[0];
     158           0 :       npol_p=iimage.shape()(pixAxis);
     159           0 :       if(calcFluxScale_p){
     160           0 :           if(fluxScale_p.shape().nelements()==0){
     161           0 :                   fluxScale_p=TempImage<Float>(IPosition(4,nx_p,ny_p,npol_p,nchan_p), csys_p);
     162           0 :                   fluxScale_p.set(0.0);
     163             :           }
     164           0 :           filledFluxScale_p=false;
     165             :       }
     166             :       
     167             :     }
     168             : 
     169           0 :   }
     170             : 
     171           0 :   void SimplePBConvFunc::toPix(const vi::VisBuffer2& vb, const MVDirection& extraShift, const Bool useExtraShift){
     172           0 :     thePix_p.resize(2);
     173             : 
     174           0 :     const MDirection& p1=pointingDirAnt1(vb);
     175           0 :     if(dc_p.directionType() !=  MDirection::castType(p1.getRef().getType())){
     176             :       //pointToPix_p.setModel(theDir);
     177             : 
     178           0 :         String tel= csys_p.obsInfo().telescope();
     179           0 :         if(!tel.contains("VLA")) {
     180             :                 //use first antenna as direction1_p is used to calculate pointing
     181             :                 // as only VLA uses observatory pos for calculations
     182           0 :                   Int ant1=vb.antenna1()(0);
     183           0 :                   MPosition pos=vb.subtableColumns().antenna().positionMeas()(ant1);
     184           0 :                   pointFrame_p.resetPosition(pos);
     185             :         }
     186           0 :       MEpoch timenow(Quantity(vb.time()(0), timeUnit_p), timeMType_p);
     187             :       //cerr << "Ref " << vb.direction1()(0).getRefString() <<  " ep " << timenow.getRefString() << " time " << MVTime(timenow.getValue().getTime()).string(MVTime::YMD) << endl; 
     188           0 :       pointFrame_p.resetEpoch(timenow);
     189             :       ///////////////////////////
     190             :       //MDirection some=pointToPix_p(vb.direction1()(0));
     191             :       //MVAngle mvRa=some.getAngle().getValue()(0);
     192             :       //MVAngle mvDec=some.getAngle().getValue()(1);
     193             :       
     194             :       //cout  << mvRa(0.0).string(MVAngle::TIME,8) << "   ";
     195             :       // cout << mvDec.string(MVAngle::DIG2,8) << "   ";
     196             :       //cout << MDirection::showType(some.getRefPtr()->getType()) << endl;
     197             : 
     198             :       //////////////////////////
     199             :       //pointToPix holds pointFrame_p by reference...
     200             :       //thus good to go for conversion
     201           0 :       direction1_p=pointToPix_p(p1);
     202             :       //direction2_p=pointToPix_p(vb.direction2()(0));
     203           0 :       direction2_p=direction1_p;
     204             :       
     205             : 
     206             :     }
     207             :     else{
     208           0 :       direction1_p=p1;
     209             :      
     210             :       //direction2_p=vb.direction2()(0);
     211             :       //For now 
     212           0 :       direction2_p=direction1_p;
     213             :      
     214             :     }
     215             :     //Should return both antennas direction in the future
     216             :     
     217           0 :     if(useExtraShift){
     218           0 :       direction1_p.shift(extraShift, False);
     219           0 :       direction2_p.shift(extraShift, False);
     220             :     }
     221           0 :     dc_p.toPixel(thePix_p, direction1_p);
     222             :    
     223           0 :   }
     224             : 
     225           0 :   void SimplePBConvFunc::setWeightImage(CountedPtr<TempImage<Float> >& wgtimage){
     226           0 :     convWeightImage_p=wgtimage;
     227           0 :     filledFluxScale_p=false;
     228           0 :     calcFluxScale_p=true;
     229             : 
     230           0 :   }
     231             :  
     232           0 :   void SimplePBConvFunc::reset(){
     233           0 :     doneMainConv_p.resize();
     234           0 :     convFunctions_p.resize(0, true);
     235           0 :     convWeights_p.resize(0, true);
     236           0 :     convSizes_p.resize(0, true);
     237           0 :     convSupportBlock_p.resize(0, true);
     238           0 :     convFunctionMap_p.clear();
     239           0 :    vbConvIndex_p.clear();
     240           0 :    ft_p=FFT2D(true);
     241           0 :   }
     242             : 
     243             : 
     244             : 
     245           0 :   Int SimplePBConvFunc::convIndex(const vi::VisBuffer2& vb, const uInt nchan){
     246           0 :     String elkey=String::toString(vb.msId())+String("_")+String::toString(vb.spectralWindows()[0])+String("_")+String::toString(nchan);
     247           0 :           if(vbConvIndex_p.count(elkey) > 0){
     248           0 :                   return vbConvIndex_p[elkey];
     249             :           }
     250           0 :           Int val=vbConvIndex_p.size();
     251           0 :           vbConvIndex_p[elkey]=val;
     252           0 :           return val;
     253             :   }
     254             : 
     255           0 :   const MDirection& SimplePBConvFunc::pointingDirAnt1(const vi::VisBuffer2& vb){
     256             :    
     257             :     
     258           0 :     std::ostringstream oss;
     259             :     
     260           0 :     oss << vb.msId() << "_" << vb.antenna1()(0) << "_";
     261           0 :     oss.precision(13);
     262           0 :     oss << vb.time()(0);
     263           0 :     String elkey=oss.str();
     264             :     //  String elkey=String::toString(vb.msId())+String("_")+String::toString(vb.antenna1()(0))+String("_")
     265             :     //                                                                    +String::toString(vb.time()(0));
     266             : 
     267             :     //cerr << "key " << elkey << " count " << ant1PointVal_p.count(elkey)  << " size " << ant1PointVal_p.size() << "  " << ant1PointingCache_p.nelements() << endl;
     268           0 :     if(ant1PointVal_p.count(elkey) > 0){
     269           0 :       return ant1PointingCache_p[ant1PointVal_p[elkey]];
     270             : 
     271             :     }
     272           0 :     Bool hasValidPointing=False;
     273           0 :     if(Table::isReadable(vb.ms().pointingTableName())){
     274           0 :       hasValidPointing=usePointingTable_p &&  (vb.ms().pointing().nrow() >0);
     275             :     }
     276             :    
     277           0 :     Int val=ant1PointingCache_p.nelements();
     278           0 :     ant1PointingCache_p.resize(val+1, true);
     279           0 :     if(hasValidPointing){
     280             :       //ant1PointingCache_p[val]=vb.direction1()[0];
     281           0 :       ant1PointingCache_p[val]=vbutil_p->getPointingDir(vb, vb.antenna1()(0), 0, dc_p.directionType());
     282             :     }
     283             :     else
     284           0 :       ant1PointingCache_p[val]=vbutil_p->getPhaseCenter(vb);
     285             :     //ant1PointingCache_p[val]=vbUtil_p.getPointingDir(vb, vb.antenna1()(0), 0);
     286           0 :     ant1PointVal_p[elkey]=val;
     287           0 :     return ant1PointingCache_p[val];
     288             : 
     289             :   }
     290           0 : void SimplePBConvFunc::findConvFunction(const ImageInterface<Complex>& iimage, 
     291             :                                         const vi::VisBuffer2& vb,
     292             :                                         const Int& convSampling,
     293             :                                         const Vector<Double>& visFreq, 
     294             :                                           Array<Complex>& convFunc, 
     295             :                                           Array<Complex>& weightConvFunc, 
     296             :                                           Vector<Int>& convsize,
     297             :                                           Vector<Int>& convSupport,
     298             :                                           Vector<Int>& convFuncPolMap,
     299             :                                           Vector<Int>& convFuncChanMap,
     300             :                                           Vector<Int>& convFuncRowMap,
     301             :                                         const Bool /*getConjFreqConvFunc*/,
     302             :                                         const MVDirection& extraShift, const Bool useExtraShift
     303             :                                           ){
     304             : 
     305             : 
     306             : 
     307           0 :   Int convSamp=2*convSampling;
     308             :   /////////////////////////
     309           0 :   LogIO os1;
     310           0 :   os1<< "msID " << vb.msId()  <<  " ANT1 id" << vb.antenna1()(0) << " direction " << vb.direction1()(0).toString() <<  " ANT2 id" << vb.antenna2()(0) << " direction " << vb.direction2()(0).toString() << LogIO::DEBUG1 << LogIO::POST ; 
     311             :     //////////////////////
     312           0 :   storeImageParams(iimage, vb);
     313           0 :   convFuncChanMap.resize(vb.nChannels());
     314           0 :   Vector<Double> beamFreqs;
     315           0 :   findUsefulChannels(convFuncChanMap, beamFreqs, vb, visFreq);
     316             :   //cerr << "CHANMAP " << convFuncChanMap << " beamFreqs " << beamFreqs << endl;
     317           0 :   Int nBeamChans=beamFreqs.nelements();
     318             :   //indgen(convFuncChanMap);
     319           0 :   convFuncPolMap.resize(vb.nCorrelations());
     320           0 :   convFuncPolMap.set(0);
     321             :   //Only one plane in this version
     322           0 :   convFuncRowMap.resize();
     323           0 :   convFuncRowMap=Vector<Int>(vb.nRows(),0);
     324             :   //break reference
     325           0 :   convFunc.resize();
     326           0 :   weightConvFunc.resize();
     327           0 :   LogIO os;
     328           0 :   os << LogOrigin("SimplePBConv", "findConvFunction")  << LogIO::NORMAL;
     329             :   
     330             :   
     331             :   // Get the coordinate system
     332           0 :   CoordinateSystem coords(iimage.coordinates());
     333             :   
     334             :   
     335           0 :   actualConvIndex_p=convIndex(vb, visFreq.nelements());
     336             :   //cerr << "In findConv " << actualConvIndex_p << endl;
     337             :   // Make a two dimensional image to calculate the
     338             :   // primary beam. We want this on a fine grid in the
     339             :   // UV plane 
     340           0 :   Int directionIndex=directionIndex_p;
     341           0 :     AlwaysAssert(directionIndex>=0, AipsError);
     342             :     
     343             :     // Set up the convolution function.
     344           0 :     Int nx=nx_p;
     345           0 :     Int ny=ny_p;
     346             :     //    convSize_p=max(nx,ny)*convSampling;
     347             :     //cerr << "size " << nx << "  " << ny << endl;
     348             :     //3 times the support size
     349           0 :     if(doneMainConv_p.shape()[0] < (actualConvIndex_p+1)){
     350             :       // cerr << "resizing DONEMAIN " <<   doneMainConv_p.shape()[0] << endl;
     351           0 :       doneMainConv_p.resize(actualConvIndex_p+1, true);
     352           0 :       doneMainConv_p[actualConvIndex_p]=false;
     353             :     }
     354             : 
     355           0 :     if(!(doneMainConv_p[actualConvIndex_p])){
     356             : 
     357             :       //convSize_p=4*(sj_p->support(vb, coords));
     358           0 :       convSize_p=Int(max(nx_p, ny_p)/2)*2*convSamp;
     359             :       // Make this a nice composite number, to speed up FFTs
     360             :       //cerr << "convSize_p 0 " <<  convSize_p << " convSamp " << convSamp<< endl;
     361           0 :       CompositeNumber cn(uInt(convSize_p*2.0));  
     362             :      
     363           0 :       convSize_p  = cn.nextLargerEven(Int(convSize_p));
     364             :       //cerr << "convSize : " << convSize_p << endl;
     365             : 
     366             :     }
     367             :     
     368             :    
     369           0 :     toPix(vb, extraShift, useExtraShift);
     370             :     //Timer tim;
     371             :     //tim.mark();
     372           0 :     addPBToFlux(vb);
     373             :     //tim.show("After addPBToFlux");
     374           0 :     DirectionCoordinate dc=dc_p;
     375             : 
     376             :     //where in the image in pixels is this pointing
     377           0 :     Vector<Double> pixFieldDir(2);
     378           0 :     pixFieldDir=thePix_p;
     379             : 
     380             :     //cerr << "pix of pointing " << pixFieldDir << endl;
     381           0 :     MDirection fieldDir=direction1_p;
     382             :     //shift from center
     383           0 :     pixFieldDir(0) = pixFieldDir(0) - Double(nx / 2);
     384           0 :     pixFieldDir(1) = pixFieldDir(1) - Double(ny / 2);
     385             : 
     386             :     //phase gradient per pixel to apply
     387           0 :     pixFieldDir(0) = -pixFieldDir(0)*2.0*C::pi/Double(nx)/Double(convSampling);
     388           0 :     pixFieldDir(1) = -pixFieldDir(1)*2.0*C::pi/Double(ny)/Double(convSampling);
     389             : 
     390             :     //cerr << "DonemainConv " << doneMainConv_p[actualConvIndex_p] << endl;
     391           0 :     if(!doneMainConv_p[actualConvIndex_p]){
     392           0 :       Vector<Double> sampling;
     393           0 :       sampling = dc.increment();
     394           0 :       sampling*=Double(convSamp);
     395           0 :       sampling(0)*=Double(nx)/Double(convSize_p);
     396           0 :       sampling(1)*=Double(ny)/Double(convSize_p);
     397           0 :       dc.setIncrement(sampling);
     398             :       
     399             :       
     400           0 :       Vector<Double> unitVec(2);
     401           0 :       unitVec=convSize_p/2;
     402           0 :       dc.setReferencePixel(unitVec);
     403             :       
     404             :       
     405             :       //make sure we are using the same units
     406           0 :       fieldDir.set(dc.worldAxisUnits()(0));
     407             :       
     408           0 :       dc.setReferenceValue(fieldDir.getAngle().getValue());
     409             :       
     410           0 :       coords.replaceCoordinate(dc, directionIndex);
     411           0 :       Int spind=coords.findCoordinate(Coordinate::SPECTRAL);
     412           0 :       SpectralCoordinate spCoord=coords.spectralCoordinate(spind);
     413           0 :       spCoord.setReferencePixel(Vector<Double>(1,0.0));
     414           0 :       spCoord.setReferenceValue(Vector<Double>(1, beamFreqs(0)));
     415           0 :       if(beamFreqs.nelements() >1)
     416           0 :         spCoord.setIncrement(Vector<Double>(1, beamFreqs(1)-beamFreqs(0)));
     417           0 :       coords.replaceCoordinate(spCoord, spind);
     418             : 
     419             : 
     420           0 :       CoordinateSystem coordLastPlane= coords;
     421           0 :       spCoord.setReferenceValue(Vector<Double>(1, beamFreqs(nBeamChans-1)));
     422           0 :       coordLastPlane.replaceCoordinate(spCoord, spind);
     423             :       //cerr << "BEAM freqs " << beamFreqs << endl;
     424             : 
     425             :       //  coords.list(logIO(), MDoppler::RADIO, IPosition(), IPosition());
     426             :       
     427           0 :       Int tempConvSize=((convSize_p/4/(convSamp/convSampling))/2)*2;
     428           0 :       IPosition pbShape(4, tempConvSize, tempConvSize, 1, nBeamChans);
     429             :       
     430           0 :       Long memtot=HostInfo::memoryFree();
     431           0 :       Double memtobeused= Double(memtot)*1024.0;
     432             :       //check for 32 bit OS and limit it to 2Gbyte
     433             :       if( sizeof(void*) == 4){
     434             :           if(memtot > 2000000)
     435             :                   memtot=2000000;
     436             :       }
     437           0 :       if(memtot <= 2000000)
     438           0 :           memtobeused=0.0;
     439             :       //cerr << "mem to be used " << memtobeused << endl;
     440             :       //tim.mark();
     441           0 :       IPosition start(4, 0, 0, 0, 0);
     442             :       //IPosition pbSlice(4, convSize_p, convSize_p, 1, 1);
     443             :       //cerr << "pbshape " << pbShape << endl;
     444           0 :       TempImage<Complex> twoDPB(TiledShape(pbShape, IPosition(4, pbShape(0), pbShape(1), 1, 1)), coords, memtobeused/10.0);
     445             : 
     446             :       //tim.show("after making one image");
     447           0 :       convFunc_p.resize(tempConvSize, tempConvSize);
     448           0 :       convFunc_p=0.0;
     449             :       
     450             :       
     451             : 
     452             :       // Accumulate terms 
     453             :       //Matrix<Complex> screen(convSize_p, convSize_p);
     454             :       //screen=1.0;
     455             :       // Either the SkyJones
     456             :       //tim.mark();
     457             :       //twoDPB.set(Complex(1.0,0.0));
     458             :       //for (Int k=0; k < nBeamChans; ++k){
     459             :       //blcin[3]=k;
     460             :       //trcin[3]=k;
     461             :       //Slicer slin(blcin, trcin, Slicer::endIsLast);
     462             :       //SubImage<Complex> subim(twoDPB, slin, true);
     463           0 :       TempImage<Complex> subim(IPosition(4, convSize_p, convSize_p, 1, 1), coordLastPlane, memtobeused/2.2);
     464           0 :       subim.set(Complex(1.0,0.0));
     465             :       //twoDPB.putSlice(screen, start);
     466           0 :       sj_p->apply(subim, subim, vb, 0); 
     467             :       //LatticeFFT::cfft2d(subim);
     468           0 :       ft_p.c2cFFT(subim);
     469             :         //  }
     470             :       //tim.show("after an apply" );
     471             :       //tim.mark();
     472           0 :       TempImage<Float> screen2(TiledShape(IPosition(4, convSize_p, convSize_p, 1, 1)), coordLastPlane, memtobeused/2.2);
     473           0 :       screen2.set(1.0);
     474           0 :       TempImage<Complex> subout(TiledShape(IPosition(4, convSize_p, convSize_p, 1, 1)), coordLastPlane, memtobeused/2.2);
     475             :       //////Making a reference on half of the lattice as on the Mac rcfft is failing for some 
     476             :       //////reason
     477           0 :       SubImage<Complex> halfsubout(subout, Slicer(IPosition(4, 0, 0, 0, 0), IPosition(4, convSize_p/2, convSize_p-1, 0, 0), Slicer::endIsLast), true);
     478           0 :       sj_p->applySquare(screen2, screen2, vb, 0); 
     479           0 :       ft_p.r2cFFT(halfsubout, screen2);
     480             :       //LatticeFFT::rcfft(halfsubout, screen2, true, false);
     481             :       //Real FFT fills only first half of the array
     482             :       //making it look like a Complex to Complex FFT
     483           0 :       IPosition iblc(4, 0, 3*subout.shape()(1)/8, 0, 0);
     484           0 :       IPosition itrc(4, 0, 5*subout.shape()(1)/8, 0, 0);
     485           0 :       for(Int x=subout.shape()(0)/2; x <(5*subout.shape()(0)/8); ++x){
     486             :         
     487           0 :         iblc[0]=x-subout.shape()(0)/2;
     488           0 :         itrc[0]=x-subout.shape()(0)/2;
     489           0 :         Slicer isl(iblc, itrc, Slicer::endIsLast);
     490           0 :         iblc[0]=x;
     491           0 :         subout.putSlice(subout.getSlice(isl), iblc);
     492             :       }
     493           0 :       for(Int x=subout.shape()(0)/2+1; x <(5*subout.shape()(0)/8); ++x){
     494             :         
     495           0 :         iblc[0]=x;
     496           0 :         itrc[0]=x;
     497           0 :         Slicer isl(iblc, itrc, Slicer::endIsLast);
     498           0 :         iblc[0]=subout.shape()(0)-x;
     499           0 :         subout.putSlice(subout.getSlice(isl), iblc);
     500           0 :         if(x==(subout.shape()(0)-1)){
     501           0 :           iblc[0]=0;
     502           0 :           subout.putSlice(subout.getSlice(isl), iblc);
     503             :         }
     504             :       }
     505             :       //End of FFT's
     506             :       //tim.show("After apply2 ");
     507           0 :       TempImage<Complex> twoDPB2(TiledShape(pbShape, IPosition(4, pbShape(0), pbShape(1), 1, 1)), coords, memtobeused/10.0);
     508             :       
     509           0 :       IPosition blcout(4, 0, 0, 0, nBeamChans-1);
     510           0 :       IPosition trcout(4, pbShape(0)-1, pbShape(1)-1, 0,nBeamChans-1);
     511           0 :       Slicer outsl(blcout, trcout, Slicer::endIsLast);
     512             :       
     513           0 :       IPosition blcin(4, convSize_p/2-pbShape(0)/2, convSize_p/2-pbShape(1)/2, 0, 0);
     514           0 :       IPosition trcin(4, convSize_p/2+pbShape(0)/2-1, convSize_p/2+pbShape(1)/2-1, 0, 0);
     515           0 :       Slicer insl(blcin, trcin, Slicer::endIsLast);
     516             :       {
     517           0 :         SubImage<Complex> subtwoDPB(twoDPB, outsl, true);
     518           0 :         SubImage<Complex> intwoDPB(subim, insl, false);
     519           0 :         subtwoDPB.copyData(intwoDPB);
     520             :       }
     521             :       {
     522           0 :         SubImage<Complex> subtwoDPB2(twoDPB2, outsl, true);
     523           0 :         SubImage<Complex> intwoDPB2(subout, insl, false);
     524           0 :         subtwoDPB2.copyData(intwoDPB2);
     525             :       }
     526             :       
     527           0 :       if(nBeamChans > 0){
     528           0 :         blcin=IPosition(4,0,0,0, nBeamChans-1);
     529           0 :         trcin=IPosition(4, pbShape(0)-1, pbShape(1)-1, 0, nBeamChans-1);
     530           0 :         Slicer slin(blcin, trcin, Slicer::endIsLast);
     531           0 :         SubImage<Complex> origPB(twoDPB, slin, false);
     532           0 :         IPosition elshape= origPB.shape();
     533           0 :         Matrix<Complex> i1=origPB.get(true);
     534           0 :         SubImage<Complex> origPB2(twoDPB2, slin, false);
     535           0 :         Matrix<Complex> i2=origPB2.get(true);
     536           0 :         Int cenX=i1.shape()(0)/2;
     537           0 :         Int cenY=i1.shape()(1)/2;
     538             :         
     539             :            
     540           0 :         for (Int kk=0; kk < nBeamChans; ++kk){
     541           0 :           Double fratio=beamFreqs(kk)/beamFreqs(nBeamChans-1);
     542             :           //cerr << "fratio " << fratio << endl;
     543           0 :           Float convRatio=convSamp/convSampling;
     544           0 :           blcin[3]=kk;
     545           0 :           trcin[3]=kk;
     546             :           //Slicer slout(blcin, trcin, Slicer::endIsLast);
     547           0 :           Matrix<Complex> o1(i1.shape(), Complex(0.0));
     548           0 :           Matrix<Complex> o2(i2.shape(), Complex(0.0));
     549           0 :           for (Int yy=0;  yy < i1.shape()(1); ++yy){
     550             :             //Int nyy= (Double(yy-cenY)*fratio) + cenY; 
     551           0 :             Double nyy= (Double((yy-cenY)*convRatio)/fratio) + cenY;
     552           0 :             Double cyy=ceil(nyy);
     553           0 :             Double fyy= floor(nyy);
     554           0 :             Int iy=nyy > fyy+0.5 ? Int(cyy) : Int(fyy); 
     555           0 :             if(cyy <2*cenY && fyy >=0.0)
     556           0 :               for(Int xx=0; xx < i1.shape()(0); ++ xx){
     557             :                 //Int nxx= Int(Double(xx-cenX)*fratio) + cenX; 
     558           0 :                 Double nxx= Int(Double((xx-cenX)*convRatio)/fratio) + cenX;
     559           0 :                 Double cxx=ceil(nxx);
     560           0 :                 Double fxx= floor(nxx);
     561           0 :                 Int ix=nxx > fxx+0.5 ? Int(cxx) : Int(fxx) ;
     562           0 :                 if(cxx < 2*cenX && fxx >=0.0 ){
     563             :                   //Double dist=sqrt((nxx-cxx)*(nxx-cxx)+(nyy-cyy)*(nyy-cyy))/sqrt(2.0);
     564             :                   //o1(xx, yy)=float(1-dist)*i1(fxx, fyy)+ dist*i1(cxx,cyy);
     565           0 :                   o1(xx, yy)=i1( ix, iy);
     566             :                   //o2(xx, yy)=i2(nxx, nyy);
     567             :                   //o2(xx, yy)=float(1-dist)*i2(fxx, fyy)+ dist*i2(cxx,cyy);
     568           0 :                   o2(xx, yy)=i2(ix, iy);
     569             :                 }
     570             :               }
     571             :           }
     572           0 :           twoDPB.putSlice(o1.reform(elshape), blcin);
     573           0 :           twoDPB2.putSlice(o2.reform(elshape), blcin);
     574             :         }
     575             :         
     576             :       }
     577             : 
     578             :       /*
     579             :       {
     580             :         TempImage<Float> screen2(TiledShape(pbShape, IPosition(4, pbShape(0), pbShape(1), 1, 1)), coords, memtobeused);
     581             :           //    Matrix<Float> screenoo(convSize_p, convSize_p);
     582             :           //screenoo.set(1.0);
     583             :           //screen2.putSlice(screenoo,start);
     584             :           //screen2.set(1.0);
     585             :           for (Int k=0; k < nBeamChans; ++k){
     586             :             blcin[3]=k;
     587             :             trcin[3]=k;
     588             :             Slicer slin(blcin, trcin, Slicer::endIsLast);
     589             :             SubImage<Float> subim(screen2, slin, true);
     590             :             SubImage<Complex> subout(twoDPB2, slin, true);
     591             :             subim.set(1.0);
     592             :             //twoDPB.putSlice(screen, start);
     593             :             sj_p->applySquare(subim, subim, vb, 0); 
     594             :             //// LatticeExpr<Complex> le(subim);
     595             :             //// subout.copyData(le);
     596             :             ///// LatticeFFT::cfft2d(subout);
     597             :            
     598             :             LatticeFFT::rcfft(subout, subim, true, false);
     599             :             IPosition iblc(4, 0, 3*subout.shape()(1)/8, 0, 0);
     600             :             IPosition itrc(4, 0, 5*subout.shape()(1)/8, 0, 0);
     601             :             for(Int x=subout.shape()(0)/2; x <(5*subout.shape()(0)/8); ++x){
     602             :               
     603             :               iblc[0]=x-subout.shape()(0)/2;
     604             :               itrc[0]=x-subout.shape()(0)/2;
     605             :               Slicer isl(iblc, itrc, Slicer::endIsLast);
     606             :               iblc[0]=x;
     607             :               subout.putSlice(subout.getSlice(isl), iblc);
     608             :             }
     609             :             for(Int x=subout.shape()(0)/2+1; x <(5*subout.shape()(0)/8); ++x){
     610             :               
     611             :               iblc[0]=x;
     612             :               itrc[0]=x;
     613             :               Slicer isl(iblc, itrc, Slicer::endIsLast);
     614             :               iblc[0]=subout.shape()(0)-x;
     615             :               subout.putSlice(subout.getSlice(isl), iblc);
     616             :               if(x==(subout.shape()(0)-1)){
     617             :                 iblc[0]=0;
     618             :                 subout.putSlice(subout.getSlice(isl), iblc);
     619             :               }
     620             :             }
     621             :             
     622             :           }
     623             :       
     624             :           //sj_p->applySquare(screen2, screen2, vb, 0);
     625             :           //LatticeExpr<Complex> le(screen2);
     626             :           //twoDPB2.copyData(le);
     627             :       }
     628             :       
     629             :       */ 
     630             :       
     631             :       /*
     632             :       if(0) {
     633             :         CoordinateSystem ftCoords(coords);
     634             :         //directionIndex=ftCoords.findCoordinate(Coordinate::DIRECTION);
     635             :         //AlwaysAssert(directionIndex>=0, AipsError);
     636             :         dc=coords.directionCoordinate(directionIndex);
     637             :         Vector<Bool> axes(2); axes(0)=true;axes(1)=true;
     638             :         Vector<Int> shape(2); shape(0)=convSize_p;shape(1)=convSize_p;
     639             :         Coordinate* ftdc=dc.makeFourierCoordinate(axes,shape);
     640             :         //ftCoords.replaceCoordinate(*ftdc, directionIndex);
     641             :         delete ftdc; ftdc=0;
     642             :         ostringstream os1;
     643             :         os1 << "Screen_" << vb.fieldId() ;
     644             :         PagedImage<Complex> thisScreen(twoDPB2.shape(), ftCoords, String(os1));
     645             :         //LatticeExpr<Float> le(abs(twoDPB2));
     646             :         thisScreen.copyData(twoDPB2);
     647             :         LatticeFFT::cfft2d(thisScreen, false);
     648             :         PagedImage<Complex> thisScreen0(twoDPB.shape(), ftCoords, String("PB_")+String(os1));
     649             :         thisScreen0.copyData(twoDPB);
     650             :         LatticeFFT::cfft2d(thisScreen0, false);
     651             :       }
     652             :       */
     653             :       /* 
     654             :       // Now FFT and get the result back
     655             :       //LatticeFFT::cfft2d(twoDPB);
     656             :       //LatticeFFT::cfft2d(twoDPB2);
     657             :       
     658             :       // Write out FT of screen as an image
     659             :       if(0) {
     660             :         CoordinateSystem ftCoords(coords);
     661             :         directionIndex=ftCoords.findCoordinate(Coordinate::DIRECTION);
     662             :         AlwaysAssert(directionIndex>=0, AipsError);
     663             :         dc=coords.directionCoordinate(directionIndex);
     664             :         Vector<Bool> axes(2); axes(0)=true;axes(1)=true;
     665             :         Vector<Int> shape(2); shape(0)=convSize_p;shape(1)=convSize_p;
     666             :         Coordinate* ftdc=dc.makeFourierCoordinate(axes,shape);
     667             :         ftCoords.replaceCoordinate(*ftdc, directionIndex);
     668             :         delete ftdc; ftdc=0;
     669             :         ostringstream os1;
     670             :         os1 << "FTScreen_" << vb.fieldId() ;
     671             :         PagedImage<Float> thisScreen(pbShape, ftCoords, String(os1));
     672             :         LatticeExpr<Float> le(abs(twoDPB2));
     673             :         thisScreen.copyData(le);
     674             :       }
     675             :       */
     676             :       //cerr << "twoDPB shape " << twoDPB.shape() << " slice shape " << IPosition(4, tempConvSize, tempConvSize, 1, 1) << endl;
     677           0 :       convFunc_p=twoDPB.getSlice(IPosition(4,0,0,0,0), IPosition(4, tempConvSize, tempConvSize, 1, 1), true);
     678           0 :       weightConvFunc_p.resize();
     679           0 :       weightConvFunc_p=twoDPB2.getSlice(IPosition(4,0,0,0,nBeamChans-1), IPosition(4, tempConvSize, tempConvSize, 1, 1), true);
     680             :       //convFunc/=max(abs(convFunc));
     681           0 :       Float maxAbsConvFunc=max(amplitude(weightConvFunc_p));
     682             :       
     683           0 :       Float minAbsConvFunc=min(amplitude(weightConvFunc_p));
     684             :       //cerr << "min max " << minAbsConvFunc << "  " <<  maxAbsConvFunc << endl;
     685           0 :       convSupport_p=-1;
     686           0 :       Bool found=false;
     687             :       //Bool found2=true;
     688             :       //Int trial2=0;
     689           0 :       Int trial=0;
     690           0 :       for (trial=tempConvSize/2-2;trial>0;trial--) {
     691             :         //Searching down a diagonal
     692           0 :         if(abs(weightConvFunc_p(tempConvSize/2-trial, tempConvSize/2-trial)) >  (1.0e-3*maxAbsConvFunc)) {
     693           0 :           found=true;
     694           0 :           trial=Int(sqrt(2.0*Float(trial*trial)));
     695           0 :           break;
     696             :         }
     697             :       }
     698           0 :       if(!found){
     699           0 :         if((maxAbsConvFunc-minAbsConvFunc) > (1.0e-3*maxAbsConvFunc)) 
     700           0 :           found=true;
     701             :         // if it drops by more than 2 magnitudes per pixel
     702           0 :         trial=( tempConvSize > (10*convSampling)) ? 5*convSampling : (tempConvSize/2 - 4*convSampling);
     703             :       }
     704             : 
     705           0 :       if(trial < 5*convSampling) 
     706           0 :         trial=( tempConvSize > (10*convSampling)) ? 5*convSampling : (tempConvSize/2 - 4*convSampling);
     707             :       
     708           0 :       if(found) {
     709           0 :         convSupport_p=Int(0.5+Float(trial)/Float(convSampling))+1;
     710             :       }
     711             :       else {
     712             :         os << "Convolution function is misbehaved - support seems to be zero\n"
     713             :            << "Reasons can be: \n(1)The image definition not covering one or more of the pointings selected\n"
     714             :            << "(2) No unflagged data in a given pointing\n"
     715             :            << "(3) The entries in the POINTING subtable do not match the field being imaged."
     716             :            << "Please check, and try again with an empty POINTING subtable.)\n"
     717           0 :            << LogIO::EXCEPTION;
     718             :       }
     719             : 
     720             :       // Normalize such that plane 0 sums to 1 (when jumping in
     721             :       // steps of convSampling)
     722             :       
     723           0 :       Double pbSum=0.0;
     724             :       //Double pbSum2=0.0;
     725             :       
     726             :       
     727             : 
     728           0 :       for (Int iy=-convSupport_p;iy<=convSupport_p;iy++) {
     729           0 :         for (Int ix=-convSupport_p;ix<=convSupport_p;ix++) {
     730           0 :           Complex val=convFunc_p(ix*convSampling+tempConvSize/2,
     731           0 :                                  iy*convSampling+tempConvSize/2);
     732           0 :           pbSum+=real(val);
     733             :       
     734             :           //pbSum+=sqrt(real(val)*real(val)+ imag(val)*imag(val));
     735             :         }
     736             :       }
     737             :       
     738             :  
     739             :       //pbSum=sum(amplitude(convFunc_p))/Double(convSampling)/Double(convSampling);
     740             : 
     741           0 :       if(pbSum>0.0) {
     742           0 :         convFunc_p*=Complex(1.0/pbSum,0.0);
     743             :       }
     744             :       else {
     745             :         os << "Convolution function integral is not positive"
     746           0 :            << LogIO::EXCEPTION;
     747             :       }
     748             :       
     749             :       //##########################################
     750             :       os << "Convolution support = " << convSupport_p
     751             :          << " pixels in Fourier plane"
     752           0 :          << LogIO::POST;
     753             :       
     754           0 :       convSupportBlock_p.resize(actualConvIndex_p+1);
     755           0 :       convSizes_p.resize(actualConvIndex_p+1);
     756             :       //Only one beam for now...but later this should be able to
     757             :       // take all the beams for the different antennas.
     758           0 :       convSupportBlock_p[actualConvIndex_p]=new Vector<Int>(1);
     759           0 :       convSizes_p[actualConvIndex_p]=new Vector<Int> (1);
     760           0 :       (*(convSupportBlock_p[actualConvIndex_p]))[0]=convSupport_p;
     761           0 :       convFunctions_p.resize(actualConvIndex_p+1);
     762           0 :       convWeights_p.resize(actualConvIndex_p+1);
     763           0 :       convFunctions_p[actualConvIndex_p]= new Array<Complex>();
     764           0 :       convWeights_p[actualConvIndex_p]= new Array<Complex>();
     765           0 :       Int newConvSize=2*(convSupport_p+2)*convSampling;
     766             :       //NEED to chop this right ...and in the centre
     767           0 :       if(newConvSize >=tempConvSize)
     768           0 :           newConvSize=tempConvSize;
     769             : 
     770           0 :       IPosition blc(4, (tempConvSize/2)-(newConvSize/2),
     771           0 :                   (tempConvSize/2)-(newConvSize/2), 0, 0);
     772           0 :       IPosition trc(4, (tempConvSize/2)+(newConvSize/2-1),
     773           0 :                       (tempConvSize/2)+(newConvSize/2-1), 0, nBeamChans-1);
     774           0 :       convFunctions_p[actualConvIndex_p]->resize(IPosition(5, newConvSize, newConvSize, 1, nBeamChans,1));
     775             :       //cerr << "convFunc shape " << (convFunctions_p[actualConvIndex_p])->shape() << 
     776             :       //"  " << " twoDPB shape " <<twoDPB.get(false)(blc,trc).shape() << endl;
     777           0 :       convFunctions_p[actualConvIndex_p]->copyMatchingPart(twoDPB.get(false)(blc,trc));//*Complex(1.0/pbSum,0.0));
     778           0 :       convSize_p=newConvSize;
     779           0 :       convWeights_p[actualConvIndex_p]->resize(IPosition(5, newConvSize, newConvSize, 1, nBeamChans,1));
     780           0 :       convWeights_p[actualConvIndex_p]->copyMatchingPart(twoDPB2.get(false)(blc,trc));//*Complex(1.0/pbSum2,0.0));
     781           0 :       blc.resize(5, false);
     782           0 :       trc.resize(5,false);
     783           0 :       blc=IPosition(5, 0, 0, 0, 0,0);
     784           0 :       trc=IPosition(5, newConvSize-1, newConvSize-1, 0, 0,0);
     785           0 :       for (Int bc=0; bc< nBeamChans; ++bc){
     786           0 :         blc[3]=bc;
     787           0 :         trc[3]=bc;
     788           0 :         pbSum=real(sum((*convFunctions_p[actualConvIndex_p])(blc,trc)))/Double(convSampling)/Double(convSampling);
     789           0 :         (*convFunctions_p[actualConvIndex_p])(blc,trc)=         (*convFunctions_p[actualConvIndex_p])(blc,trc)/pbSum;
     790           0 :         (*convWeights_p[actualConvIndex_p])(blc,trc)=   (*convWeights_p[actualConvIndex_p])(blc,trc)/pbSum;
     791             :       }
     792             : 
     793             : 
     794             : 
     795           0 :       convFunc_p.resize();//break any reference
     796           0 :       (*convSizes_p[actualConvIndex_p])[0]=convSize_p;
     797           0 :       doneMainConv_p[actualConvIndex_p]=true;
     798             :       
     799             :     }
     800             :     else{
     801           0 :       convSize_p=(*convSizes_p[actualConvIndex_p])[0];
     802             : 
     803             :     }
     804             : 
     805             :     //Apply the shift phase gradient
     806           0 :     convFunc.resize();
     807           0 :     weightConvFunc.resize();
     808           0 :     convFunc.assign(*(convFunctions_p[actualConvIndex_p]));
     809           0 :     weightConvFunc.assign(*(convWeights_p[actualConvIndex_p]));
     810             :     Bool copyconv, copywgt;
     811           0 :     Complex *cv=convFunc.getStorage(copyconv);
     812           0 :     Complex *wcv=weightConvFunc.getStorage(copywgt);
     813             :     //cerr << "Field " << vb.fieldId() << " spw " << vb.spectralWindow() << " phase grad: " << pixFieldDir << endl;
     814             :    
     815           0 :     for (Int nc=0; nc < nBeamChans; ++nc){ 
     816           0 :         Int planeoffset=nc*convSize_p*convSize_p;
     817           0 :         for (Int iy=0;iy<convSize_p;iy++) {
     818             :                 Double cy, sy;
     819             :                 Int offset;
     820             :                
     821           0 :                 SINCOS(Double(iy-convSize_p/2)*pixFieldDir(1), sy, cy);
     822           0 :                 Complex phy(cy,sy) ;
     823           0 :                 offset = iy*convSize_p+planeoffset;
     824           0 :                 for (Int ix=0;ix<convSize_p;ix++) {
     825             :                         Double cx, sx;
     826           0 :                         SINCOS(Double(ix-convSize_p/2)*pixFieldDir(0), sx, cx);
     827           0 :                         Complex phx(cx,sx) ;
     828           0 :                         cv[ix+offset]= cv[ix+offset]*phx*phy;
     829           0 :                         wcv[ix+offset]= wcv[ix+offset]*phx*phy;
     830             : 
     831             :                 }
     832             :         }
     833             :     }
     834           0 :     convFunc.putStorage(cv, copyconv);
     835           0 :     weightConvFunc.putStorage(wcv, copywgt);
     836           0 :     convsize.resize();
     837           0 :     convsize=*(convSizes_p[actualConvIndex_p]);
     838           0 :     convSupport.resize();
     839           0 :     convSupport=(*(convSupportBlock_p[actualConvIndex_p]));
     840             :     
     841             :     
     842           0 :   }
     843             : 
     844           0 :   void SimplePBConvFunc::setSkyJones(SkyJones* sj){
     845           0 :     sj_p=sj;
     846           0 :   }
     847             :   
     848             :   
     849           0 :   void SimplePBConvFunc::findUsefulChannels(Vector<Int>& chanMap, Vector<Double>& chanFreqs,  const vi::VisBuffer2& vb, const Vector<Double>& freq){
     850             :     
     851             :           
     852           0 :         Int spw=vb.spectralWindows()(0);
     853           0 :         bandName_p=vb.subtableColumns().spectralWindow().name()(spw);
     854           0 :         Vector<Double> spwfreq=vb.subtableColumns().spectralWindow().chanFreq()(spw);
     855           0 :         Double spwfreqwidth=abs(Vector<Double>(vb.subtableColumns().spectralWindow().chanWidth()(spw))(0));
     856           0 :         chanMap.resize(freq.nelements());
     857           0 :     Vector<Double> localfreq=vb.getFrequencies(0, MFrequency::TOPO);
     858           0 :     Double minfreq=min(freq);
     859           0 :     Double maxfreq=max(freq);
     860           0 :     Double origwidth=freq.nelements()==1 ? 1e12 : (maxfreq-minfreq)/(freq.nelements()-1);
     861             :     ///Fractional bandwidth which will trigger mutiple PB in one spw
     862             :     
     863           0 :     Double tol=(max(spwfreq))*0.5/100;
     864           0 :     if(tol < origwidth/2.0) tol=origwidth/2.0;
     865           0 :     Double topFreq=max(spwfreq);
     866           0 :     while (topFreq > maxfreq){
     867           0 :       topFreq -= tol;
     868             :     }
     869             :     // For large tol
     870           0 :     if(topFreq < minfreq)
     871           0 :        topFreq += tol;
     872             :     //Int nchan=Int(lround((max(freq)-min(freq))/tol));
     873           0 :     Double bottomFreq=topFreq;
     874           0 :     Int nchan=0;
     875             :     //cerr << std::setprecision(12) << "top " << bottomFreq << " minFreq " << minfreq << " maxFreq " << maxfreq << endl;
     876           0 :      while(bottomFreq > minfreq){
     877           0 :        ++nchan;
     878           0 :        bottomFreq -= tol;
     879             :      }
     880           0 :      if(nchan > 1){
     881           0 :        nchan-=1;
     882           0 :        bottomFreq+=tol;
     883             :      }
     884             :      
     885             :      //cerr  << "TOLERA " << tol << " nchan " << nchan << " bot " << bottomFreq << " vb.nchan " << vb.nChannels() << endl;
     886             :     //Number of beams that matters are the ones in the data
     887           0 :      if(nchan > vb.nChannels()){
     888           0 :       nchan=vb.nChannels();
     889           0 :       tol=spwfreqwidth;
     890           0 :       bottomFreq=min(localfreq);
     891             :      }
     892             :    
     893           0 :     chanFreqs.resize();
     894           0 :     if(nchan >= (Int)(freq.nelements()-1)) { indgen(chanMap); chanFreqs=freq; return;}
     895           0 :     if((nchan==0) || (freq.nelements()==1)) { chanFreqs=Vector<Double>(1, bottomFreq);chanMap.set(0); return;}
     896             : 
     897           0 :     chanFreqs.resize(nchan);
     898           0 :     for(Int k=0; k < nchan; ++k){
     899           0 :       chanFreqs[k]=k*tol+bottomFreq;
     900             :     }
     901             :     
     902             :   
     903           0 :     Int activechan=0;
     904           0 :     chanMap.set(0);
     905           0 :     for (uInt k=0; k < chanMap.nelements(); ++k){
     906           0 :       Double mindiff=DBL_MAX;
     907           0 :       Int nearestchan=0;
     908           0 :       while((activechan< nchan) && Double(abs(freq[k]-chanFreqs[activechan])) > Double(tol/Double(2.0))){
     909           0 :         if(mindiff > Double(abs(freq[k]-chanFreqs[activechan]))){
     910           0 :           mindiff=Double(abs(freq[k]-chanFreqs[activechan]));
     911           0 :           nearestchan=activechan;
     912             :         }
     913             :           
     914             :         //      cerr << "k " << k << " atcivechan " << activechan << " comparison " 
     915             :         //     << freq[k] << "    " << chanFreqs[activechan]  << endl;        
     916           0 :         ++activechan;
     917             :       }
     918           0 :       if(activechan != nchan){
     919           0 :         chanMap[k]=activechan;
     920             :       }
     921             :       //////////////////
     922             :       else{
     923             :         //cerr << std::setprecision(10) << "freq diffs " << freq[k]-chanFreqs << "  TOL " << tol/2.0 << endl;
     924           0 :         chanMap[k]=nearestchan;
     925             :       }
     926             :       ///////////////////////////
     927           0 :       activechan=0;
     928             :     }
     929             :     //cerr << "chanfreqs "  << chanFreqs << endl;
     930             :     //cerr << "USEFULchan " << chanMap << endl;
     931           0 :     return;
     932             :   }
     933             :   /*
     934             :   
     935             :     void SimplePBConvFunc::findUsefulChannels(Vector<Int>& chanMap, Vector<Double>& chanFreqs,  const vi::VisBuffer2& vb, const Vector<Double>& freq){
     936             :     
     937             :           
     938             :         Int spw=vb.spectralWindows()(0);
     939             :         bandName_p=vb.subtableColumns().spectralWindow().name()(spw);
     940             :         chanMap.resize(freq.nelements());
     941             :     Vector<Double> localfreq=vb.getFrequencies(0, MFrequency::TOPO);
     942             :     Double minfreq=min(freq);
     943             :     
     944             :     Double origwidth=freq.nelements()==1 ? 1e12 : (max(freq)-min(freq))/(freq.nelements()-1);
     945             :     ///Fractional bandwidth which will trigger mutiple PB in one spw
     946             :     Double tol=(max(freq))*0.5/100;
     947             :     
     948             :     Int nchan=Int(lround((max(freq)-min(freq))/tol));
     949             :    
     950             :     //cerr  << "TOLERA " << tol << " nchan " << nchan << " vb.nchan " << vb.nChannel() << endl;
     951             :     //Number of beams that matters are the ones in the data
     952             :     if(nchan > vb.nChannels())
     953             :       nchan=vb.nChannels();
     954             : 
     955             :     if(tol < origwidth) tol=origwidth;
     956             :     chanFreqs.resize();
     957             :     if(nchan >= (Int)(freq.nelements()-1)) { indgen(chanMap); chanFreqs=freq; return;}
     958             :     if((nchan==0) || (freq.nelements()==1)) { chanFreqs=Vector<Double>(1, freq[0]);chanMap.set(0); return;}
     959             : 
     960             :     //readjust the tolerance...
     961             :     tol=(max(freq)-min(freq)+origwidth)/Double(nchan);
     962             :     chanFreqs.resize(nchan);
     963             :     for (Int k=0; k < nchan; ++k)
     964             :       chanFreqs[k]=minfreq-origwidth+tol/2.0+tol*Double(k);
     965             :     Int activechan=0;
     966             :     chanMap.set(0);
     967             :     for (uInt k=0; k < chanMap.nelements(); ++k){
     968             :       Double mindiff=DBL_MAX;
     969             :       Int nearestchan=0;
     970             :       while((activechan< nchan) && Double(abs(freq[k]-chanFreqs[activechan])) > Double(tol/Double(2.0))){
     971             :         if(mindiff > Double(abs(freq[k]-chanFreqs[activechan]))){
     972             :           mindiff=Double(abs(freq[k]-chanFreqs[activechan]));
     973             :           nearestchan=activechan;
     974             :         }
     975             :           
     976             :         //      cerr << "k " << k << " atcivechan " << activechan << " comparison " 
     977             :         //     << freq[k] << "    " << chanFreqs[activechan]  << endl;        
     978             :         ++activechan;
     979             :       }
     980             :       if(activechan != nchan){
     981             :         chanMap[k]=activechan;
     982             :       }
     983             :       //////////////////
     984             :       else{
     985             :         //cerr << std::setprecision(10) << "freq diffs " << freq[k]-chanFreqs << "  TOL " << tol/2.0 << endl;
     986             :         chanMap[k]=nearestchan;
     987             :       }
     988             :       ///////////////////////////
     989             :       activechan=0;
     990             :     }
     991             :     //cerr << chanMap << endl;
     992             :     return;
     993             :   }
     994             :   */
     995           0 :   Bool SimplePBConvFunc::checkPBOfField(const vi::VisBuffer2& vb){
     996             :     //Int fieldid=vb.fieldId();
     997           0 :     String msid=vb.msName(true);
     998             :     /*
     999             :      if(convFunctionMap_p.ndefined() > 0){
    1000             :       if (((fluxScale_p.shape()[3] != nchan_p) || (fluxScale_p.shape()[2] != npol_p)) && calcFluxScale_p){
    1001             :         convFunctionMap_p.clear();
    1002             :       }
    1003             :     }
    1004             :     // if you rename the ms might be a problem
    1005             :     String mapid=msid+String("_")+String::toString(fieldid);
    1006             :     if(convFunctionMap_p.ndefined() == 0){
    1007             :       convFunctionMap_p.define(mapid, 0);    
    1008             :       actualConvIndex_p=0;
    1009             :       if(calcFluxScale_p){
    1010             :         // 0ne channel only is needed to keep track of pb coverage
    1011             :         if(fluxScale_p.shape().nelements()==0){
    1012             :           fluxScale_p=TempImage<Float>(IPosition(4,nx_p,ny_p,npol_p,1), csys_p);
    1013             :           fluxScale_p.set(0.0);
    1014             :         }
    1015             :         filledFluxScale_p=false;
    1016             :       }
    1017             :       return false;
    1018             :     }
    1019             :     
    1020             :     if(!convFunctionMap_p.isDefined(mapid)){
    1021             :       actualConvIndex_p=convFunctionMap_p.ndefined();
    1022             :       convFunctionMap_p.define(mapid, actualConvIndex_p);
    1023             :       return false;
    1024             :     }
    1025             :     else{
    1026             :       actualConvIndex_p=convFunctionMap_p(mapid);
    1027             :       convFunc_p.resize(); // break any reference
    1028             :       weightConvFunc_p.resize(); 
    1029             :       //Here we will need to use the right xyPlane for different PA range.
    1030             :       //convFunc_p.reference(convFunctions_p[actualConvIndex_p]->xyPlane(0));
    1031             :       //weightConvFunc_p.reference(convWeights_p[actualConvIndex_p]->xyPlane(0));
    1032             :       //Again this for one time of antenna only later should be fixed for all 
    1033             :       // antennas independently
    1034             :       convSupport_p=(*convSupportBlock_p[actualConvIndex_p])[0];
    1035             :       convSize_p=(*convSizes_p[actualConvIndex_p])[0];
    1036             : 
    1037             :   }
    1038             : */
    1039             :  
    1040           0 :  return true;
    1041             : 
    1042             : 
    1043             : 
    1044             :   }
    1045             :   
    1046             : 
    1047           0 :   ImageInterface<Float>&  SimplePBConvFunc::getFluxScaleImage(){
    1048             : 
    1049           0 :     if(!calcFluxScale_p)
    1050           0 :       throw(AipsError("Programmer error: Cannot get flux scale"));
    1051           0 :     if(!filledFluxScale_p){
    1052           0 :       IPosition blc=fluxScale_p.shape();
    1053           0 :       IPosition trc=fluxScale_p.shape();
    1054           0 :       blc(0)=0; blc(1)=0; trc(0)=nx_p-1; trc(1)=ny_p-1;
    1055             :       
    1056           0 :       for (Int j=0; j < fluxScale_p.shape()(2); ++j){
    1057           0 :         for (Int k=0; k < fluxScale_p.shape()(3) ; ++k){
    1058             :           
    1059           0 :           blc(2)=j; trc(2)=j;
    1060           0 :           blc(3)=k; trc(3)=k;
    1061           0 :           Slicer sl(blc, trc, Slicer::endIsLast);
    1062           0 :           SubImage<Float> fscalesub(fluxScale_p, sl, true);
    1063             :           Float planeMax;
    1064           0 :           LatticeExprNode LEN = max( fscalesub );
    1065           0 :           planeMax =  LEN.getFloat();
    1066           0 :           if(planeMax !=0){
    1067           0 :             fscalesub.copyData( (LatticeExpr<Float>) (fscalesub/planeMax));
    1068             :             
    1069             :           }
    1070             :         }
    1071             :       }
    1072             :       /*
    1073             :       if(0) {
    1074             :         ostringstream os2;
    1075             :         os2 << "ALL_" << "BEAMS" ;
    1076             :         PagedImage<Float> thisScreen2(fluxScale_p.shape(), fluxScale_p.coordinates(), String(os2));
    1077             :         thisScreen2.copyData(fluxScale_p);
    1078             :       }
    1079             :       */
    1080             : 
    1081           0 :       filledFluxScale_p=true;
    1082             :     }
    1083             :       
    1084             : 
    1085           0 :     return fluxScale_p;
    1086             :     
    1087             :   }
    1088             : 
    1089             : 
    1090           0 :   Bool SimplePBConvFunc::toRecord(RecordInterface& rec){
    1091           0 :     Int numConv=convFunctions_p.nelements();
    1092             :     // not saving the protected variables as they are generated by
    1093             :     // the first  call to storeImageParams 
    1094             :     try{
    1095           0 :       rec.define("name", "SimplePBConvFunc");
    1096           0 :       rec.define("numconv", numConv);
    1097             :       //cerr << "num of conv " << numConv << "  " << convFunctionMap_p.ndefined() << "  " <<convFunctions_p.nelements() << endl;
    1098           0 :       std::map<String, Int>::iterator it=vbConvIndex_p.begin();
    1099           0 :       for (Int k=0; k < numConv; ++k){
    1100           0 :         rec.define("convfunctions"+String::toString(k), *(convFunctions_p[k]));
    1101           0 :         rec.define("convweights"+String::toString(k), *(convWeights_p[k]));
    1102           0 :         rec.define("convsizes"+String::toString(k), *(convSizes_p[k]));
    1103           0 :         rec.define("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
    1104             :         //cerr << "k " << k << " key " << convFunctionMap_p.getKey(k) << " val " << convFunctionMap_p.getVal(k) << endl;
    1105           0 :         rec.define(String("key")+String::toString(k), it->first);
    1106           0 :         rec.define(String("val")+String::toString(k), it->second);
    1107           0 :         it++;
    1108             :       }
    1109           0 :       rec.define("pbclass", Int(pbClass_p));
    1110           0 :       rec.define("actualconvindex",  actualConvIndex_p);
    1111           0 :       rec.define("donemainconv", doneMainConv_p);
    1112           0 :       rec.define("usepointingtable", usePointingTable_p);
    1113             :       //The following is not needed ..can be regenerated
    1114             :       //rec.define("pointingpix", pointingPix_p);
    1115             :     }
    1116           0 :     catch(AipsError &x) {
    1117           0 :       return false;
    1118             :     }
    1119           0 :     return true;
    1120             :   }
    1121             : 
    1122           0 :   Bool SimplePBConvFunc::fromRecord(String& err, const RecordInterface& rec, Bool calcFluxneeded){
    1123           0 :      Int numConv=0;
    1124             :      //make sure storeImageParams is triggered
    1125           0 :      nchan_p=0;
    1126             :      
    1127             :      try{
    1128           0 :        if(!rec.isDefined("name") || rec.asString("name") != "SimplePBConvFunc"){
    1129           0 :          throw(AipsError("Wrong record to recover SimplePBConvFunc from"));
    1130             :         }
    1131           0 :        rec.get("numconv", numConv);
    1132           0 :        convFunctions_p.resize(numConv, true, false);
    1133           0 :        convSupportBlock_p.resize(numConv, true, false);
    1134           0 :        convWeights_p.resize(numConv, true, false);
    1135           0 :        convSizes_p.resize(numConv, true, false);
    1136           0 :        convFunctionMap_p.clear( );
    1137           0 :        vbConvIndex_p.erase(vbConvIndex_p.begin(), vbConvIndex_p.end());
    1138           0 :        for (Int k=0; k < numConv; ++k){
    1139           0 :          convFunctions_p[k]=new Array<Complex>();
    1140           0 :          convWeights_p[k]=new Array<Complex>();
    1141           0 :          convSizes_p[k]=new Vector<Int>();
    1142           0 :          convSupportBlock_p[k]=new Vector<Int>();
    1143           0 :          rec.get("convfunctions"+String::toString(k), *(convFunctions_p[k]));
    1144           0 :          rec.get("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
    1145           0 :          rec.get("convweights"+String::toString(k), *(convWeights_p[k]));
    1146           0 :          rec.get("convsizes"+String::toString(k), *(convSizes_p[k]));
    1147           0 :          String key;
    1148             :          Int val;
    1149           0 :          rec.get(String("key")+String::toString(k), key);
    1150           0 :          rec.get(String("val")+String::toString(k), val);
    1151           0 :          vbConvIndex_p[key]=val;
    1152           0 :          ant1PointVal_p.clear();
    1153           0 :          ant1PointingCache_p.resize();
    1154             :          //convFunctionMap_p.define(key,val);
    1155             :        }
    1156           0 :        pbClass_p=static_cast<PBMathInterface::PBClass>(rec.asInt("pbclass"));
    1157           0 :        rec.get("actualconvindex",  actualConvIndex_p);
    1158           0 :        rec.get("usepointingtable", usePointingTable_p);
    1159           0 :        pointingPix_p.resize();
    1160             :        //rec.get("pointingpix", pointingPix_p);
    1161           0 :        calcFluxScale_p=calcFluxneeded;
    1162             : 
    1163             :      }
    1164           0 :      catch(AipsError & x) {
    1165           0 :        err=x.getMesg();
    1166           0 :        return false;
    1167             :      }
    1168           0 :      return true;
    1169             :      
    1170             :   }
    1171           0 :   void SimplePBConvFunc::addPBToFlux(const vi::VisBuffer2& vb){
    1172           0 :     if(calcFluxScale_p){
    1173           0 :       if(fluxScale_p.shape().nelements()==0)
    1174             :         { //cerr << "nx_p " << nx_p << endl;
    1175           0 :         calcFluxScale_p=False;
    1176           0 :         return;
    1177             :       }
    1178           0 :       Vector<Int> pixdepoint(2, -100000);
    1179           0 :       convertArray(pixdepoint, thePix_p);
    1180           0 :       if((pixdepoint(0) >=0) && (pixdepoint(0) < pointingPix_p.shape()[0]) && (pixdepoint(1) >=0) && (pixdepoint(1) < pointingPix_p.shape()[1])  && !pointingPix_p(pixdepoint(0), pixdepoint(1))){
    1181           0 :          TempImage<Float> thispb(fluxScale_p.shape(), fluxScale_p.coordinates());
    1182           0 :          thispb.set(1.0);
    1183           0 :          sj_p->applySquare(thispb, thispb, vb, 0);
    1184           0 :          LatticeExpr<Float> le(fluxScale_p+thispb);
    1185           0 :          fluxScale_p.copyData(le);
    1186           0 :          pointingPix_p(pixdepoint(0), pixdepoint(1))=true;
    1187             :          //LatticeExprNode LEN = max(fluxScale_p);
    1188             :          //Float maxsca=LEN.getFloat();
    1189             :          //Tempporary fix when cubesky is chunking...do not add on 
    1190             :          //already defined position
    1191             :          //if(maxsca > 1.98){
    1192             :          //  cerr << "avoiding subtract " << endl;
    1193             :         //fluxScale_p.copyData(LatticeExpr<Float>(fluxScale_p-thispb));
    1194             : 
    1195             :          //}      
    1196             :       /*
    1197             :       if(0) {
    1198             :         ostringstream os1;
    1199             :         os1 << "SINGLE_" << vb.fieldId() ;
    1200             :         PagedImage<Float> thisScreen(fluxScale_p.shape(), fluxScale_p.coordinates(), String(os1));
    1201             :         thisScreen.copyData(thispb);
    1202             :         ostringstream os2;
    1203             :         os2 << "ALL_" << vb.fieldId() ;
    1204             :         PagedImage<Float> thisScreen2(fluxScale_p.shape(), fluxScale_p.coordinates(), String(os2));
    1205             :         thisScreen2.copyData(fluxScale_p);
    1206             :       }
    1207             :       */
    1208             :        }
    1209             :     }
    1210             : 
    1211             :   }
    1212             : 
    1213           0 :   void SimplePBConvFunc::sliceFluxScale(Int npol) {
    1214           0 :      IPosition fshp=fluxScale_p.shape();
    1215           0 :      if (fshp(2)>npol){
    1216           0 :        npol_p=npol;
    1217             :        // use first npol planes...
    1218           0 :        IPosition blc(4,0,0,0,0);
    1219           0 :        IPosition trc(4,fluxScale_p.shape()(0)-1, fluxScale_p.shape()(1)-1,npol-1,fluxScale_p.shape()(3)-1);
    1220           0 :        Slicer sl=Slicer(blc, trc, Slicer::endIsLast);
    1221             :        //writeable if possible
    1222           0 :        SubImage<Float> fluxScaleSub = SubImage<Float> (fluxScale_p, sl, true);
    1223           0 :        fluxScale_p = TempImage<Float>(fluxScaleSub.shape(),fluxScaleSub.coordinates());
    1224           0 :        LatticeExpr<Float> le(fluxScaleSub);
    1225           0 :        fluxScale_p.copyData(le);
    1226             :      }
    1227           0 :   }
    1228             : } //# END of name space REFIM
    1229             : } //# NAMESPACE CASA - END
    1230             : 
    1231             : 
    1232             : 
    1233             : 
    1234             : 
    1235             : 
    1236             : 

Generated by: LCOV version 1.16