LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - HetArrayConvFunc.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 817 0.0 %
Date: 2024-10-28 15:53:10 Functions: 0 27 0.0 %

          Line data    Source code
       1             : //# HetArrayConvFunc.cc: Implementation for HetArrayConvFunc
       2             : //# Copyright (C) 2008-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  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             : 
      29             : #include <casacore/casa/Arrays/ArrayMath.h>
      30             : #include <casacore/casa/Arrays/Array.h>
      31             : #include <casacore/casa/Arrays/MaskedArray.h>
      32             : #include <casacore/casa/Arrays/Vector.h>
      33             : #include <casacore/casa/Arrays/Slice.h>
      34             : #include <casacore/casa/Arrays/Matrix.h>
      35             : #include <casacore/casa/Arrays/Cube.h>
      36             : #include <casacore/scimath/Mathematics/FFTServer.h>
      37             : #include <casacore/measures/Measures/MeasTable.h>
      38             : #include <casacore/scimath/Mathematics/MathFunc.h>
      39             : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
      40             : #include <casacore/casa/Utilities/Assert.h>
      41             : #include <casacore/casa/Utilities/CompositeNumber.h>
      42             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      43             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      44             : 
      45             : #include <casacore/images/Images/ImageInterface.h>
      46             : #include <casacore/images/Images/PagedImage.h>
      47             : #include <casacore/images/Images/SubImage.h>
      48             : #include <casacore/images/Images/TempImage.h>
      49             : #include <imageanalysis/Utilities/SpectralImageUtil.h>
      50             : #include <casacore/casa/Logging/LogIO.h>
      51             : #include <casacore/casa/Logging/LogSink.h>
      52             : #include <casacore/casa/Logging/LogMessage.h>
      53             : 
      54             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      55             : #include <casacore/lattices/Lattices/SubLattice.h>
      56             : #include <casacore/lattices/LRegions/LCBox.h>
      57             : #include <casacore/lattices/Lattices/LatticeConcat.h>
      58             : #include <casacore/lattices/LEL/LatticeExpr.h>
      59             : #include <casacore/lattices/Lattices/LatticeCache.h>
      60             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      61             : 
      62             : 
      63             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      64             : 
      65             : #include <msvis/MSVis/VisBuffer2.h>
      66             : 
      67             : #include <synthesis/TransformMachines2/Utils.h>
      68             : #include <synthesis/TransformMachines/PBMath1DAiry.h>
      69             : #include <synthesis/TransformMachines/PBMath1DNumeric.h>
      70             : #include <synthesis/TransformMachines/PBMath2DImage.h>
      71             : #include <synthesis/TransformMachines/PBMath.h>
      72             : #include <synthesis/TransformMachines2/HetArrayConvFunc.h>
      73             : #include <synthesis/MeasurementEquations/VPManager.h>
      74             : 
      75             : #include <casacore/casa/OS/Timer.h>
      76             : 
      77             : 
      78             : 
      79             : using namespace casacore;
      80             : namespace casa { //# NAMESPACE CASA - BEGIN
      81             : 
      82             : namespace refim {
      83             : 
      84             : using namespace casacore;
      85             : using namespace casa;
      86             : using namespace casacore;
      87             : using namespace casa::refim;
      88             : 
      89             : 
      90           0 :   HetArrayConvFunc::HetArrayConvFunc() : convFunctionMap_p(0), nDefined_p(0),msId_p(-1), actualConvIndex_p(-1), vpTable_p("")
      91             : {
      92           0 :     calcFluxScale_p=true;
      93           0 :     init(PBMathInterface::AIRY);
      94           0 : }
      95             : 
      96           0 : HetArrayConvFunc::HetArrayConvFunc(const PBMathInterface::PBClass typeToUse, const String vpTable):
      97           0 :     convFunctionMap_p(0), nDefined_p(0), msId_p(-1), actualConvIndex_p(-1), vpTable_p(vpTable)
      98             : {
      99           0 :     calcFluxScale_p=true;
     100           0 :     init(typeToUse);
     101             : 
     102           0 : }
     103             : 
     104           0 : HetArrayConvFunc::HetArrayConvFunc(const RecordInterface& rec, Bool calcFluxneeded):convFunctionMap_p(0), nDefined_p(0), msId_p(-1), actualConvIndex_p(-1) {
     105           0 :     String err;
     106           0 :     fromRecord(err, rec, calcFluxneeded);
     107           0 : }
     108             : 
     109           0 : HetArrayConvFunc::~HetArrayConvFunc() {
     110             :     //
     111           0 : }
     112             : 
     113           0 : void HetArrayConvFunc::init(const PBMathInterface::PBClass typeTouse) {
     114           0 :     doneMainConv_p=false;
     115           0 :     filledFluxScale_p=false;
     116           0 :     pbClass_p=typeTouse;
     117           0 : }
     118             : 
     119             : 
     120             : 
     121           0 : void HetArrayConvFunc::findAntennaSizes(const vi::VisBuffer2& vb) {
     122             : 
     123           0 :       if(msId_p != vb.msId()) {
     124           0 :         msId_p=vb.msId();
     125             :         //MSColumns mscol(vb.ms());
     126           0 :         const MSAntennaColumns& ac=vb.subtableColumns().antenna();
     127           0 :         antIndexToDiamIndex_p.resize(ac.nrow());
     128           0 :         antIndexToDiamIndex_p.set(-1);
     129           0 :         Int diamIndex=antDiam2IndexMap_p.size( );
     130           0 :         Vector<Double> dishDiam=ac.dishDiameter().getColumn();
     131           0 :         Vector<String>dishName=ac.name().getColumn();
     132           0 :         String telescop=vb.subtableColumns().observation().telescopeName()(0);
     133             :         PBMath::CommonPB whichPB;
     134           0 :         if(pbClass_p==PBMathInterface::COMMONPB) {
     135           0 :             String band;
     136           0 :             String commonPBName;
     137             :             // This frequency is ONLY required to determine which PB model to use:
     138             :             // The VLA, the ATNF, and WSRT have frequency - dependent PB models
     139           0 :             Quantity freq( vb.subtableColumns().spectralWindow().refFrequency()(0), "Hz");
     140             : 
     141             : 
     142           0 :             PBMath::whichCommonPBtoUse( telescop, freq, band, whichPB, commonPBName );
     143             :             //Revert to using AIRY for unknown common telescope
     144           0 :             if(whichPB==PBMath::UNKNOWN)
     145           0 :                 pbClass_p=PBMathInterface::AIRY;
     146             : 
     147           0 :         }
     148           0 :         if(pbClass_p== PBMathInterface::AIRY) {
     149           0 :           LogIO os;
     150           0 :         os << LogOrigin("HetArrConvFunc", "findAntennaSizes")  << LogIO::NORMAL;
     151             :             ////////We'll be using dish diameter as key
     152           0 :             for (uInt k=0; k < dishDiam.nelements(); ++k) {
     153           0 :                 if( (diamIndex !=0) && antDiam2IndexMap_p.find(String::toString(dishDiam(k))) != antDiam2IndexMap_p.end( ) ) {
     154           0 :                     antIndexToDiamIndex_p(k)=antDiam2IndexMap_p[String::toString(dishDiam(k))];
     155             :                 }
     156             :                 else {
     157           0 :                     if(dishDiam[k] > 0.0) { //there may be stations with no dish on
     158           0 :                         antDiam2IndexMap_p.insert(std::pair<casacore::String, casacore::Int>(String::toString(dishDiam(k)), diamIndex));
     159           0 :                         antIndexToDiamIndex_p(k)=diamIndex;
     160           0 :                         antMath_p.resize(diamIndex+1);
     161           0 :                         if(pbClass_p== PBMathInterface::AIRY) {
     162             :                           //ALMA ratio of blockage to dish
     163           0 :                             Quantity qdiam= Quantity (dishDiam(k),"m");       
     164           0 :                             Quantity blockDiam= Quantity(dishDiam(k)/12.0*.75, "m");
     165           0 :                             Quantity support=Quantity(150, "arcsec");
     166             :                             ///For ALMA 12m dish it is effectively 10.7 m according to Todd Hunter
     167             :                             ///@ 2011-12-06
     168           0 :                             if((vb.subtableColumns().observation().telescopeName()(0) =="ALMA") || (vb.subtableColumns().observation().telescopeName()(0) =="ACA")){
     169           0 :                               Quantity fov(max(nx_p*dc_p.increment()(0), ny_p*dc_p.increment()(1)), dc_p.worldAxisUnits()(0));
     170           0 :                               if((abs(dishDiam[k] - 12.0) < 0.5)) {
     171           0 :                                 qdiam= Quantity(10.7, "m");
     172           0 :                                 blockDiam= Quantity(0.75, "m");
     173           0 :                                 support=Quantity(max(150.0, fov.getValue("arcsec")/5.0), "arcsec");
     174             :                                 
     175             :                               }
     176             :                               else{
     177             :                                 //2017 the ACA dishes are best represented by 6.25m:
     178             :                                
     179           0 :                                 qdiam= Quantity(6.25,"m");
     180           0 :                                 blockDiam = Quantity(0.75,"m");
     181           0 :                                 support=Quantity(max(300.0,fov.getValue("arcsec")/3.0) , "arcsec");
     182             :                               }
     183           0 :                             }
     184           0 :                              os << "Overriding PB with Airy of diam,blockage="<<qdiam<<","<<blockDiam<<" starting with antenna "<<k<<LogIO::POST; 
     185             :                             
     186             :                         
     187             :                     
     188             : 
     189           0 :                         antMath_p[diamIndex]=new PBMath1DAiry(qdiam, blockDiam,
     190             :                                                           support,
     191           0 :                                                           Quantity(100.0,"GHz"));
     192           0 :                         }
     193             : 
     194             :                 
     195             : 
     196             :                         //////Will no longer support this
     197             :                         /*else if(pbClass_p== PBMathInterface::IMAGE){
     198             :                           //Get the image name by calling code for the antenna name and array name
     199             :                           //For now hard wired to ALMA as this part of the code will not be accessed for non-ALMA
     200             :                           //see Imager::setMosaicFTMachine
     201             :                           // When ready to generalize then code that calls with telescope name, antenna name
     202             :                           //(via vb.msColumns) and/or diameter and frequency via vb.frequency (indexing will need to
     203             :                           //be upgraded to account for frequency too) should be done to return the
     204             :                           //right voltage pattern image.
     205             :                           String vpImageName="";
     206             :                           if (abs(dishDiam[k]-7.0) < 1.0)
     207             :                         Aipsrc::find(vpImageName, "alma.vp.7m", "");
     208             :                           else
     209             :                         Aipsrc::find(vpImageName, "alma.vp.12m", "") ;
     210             :                           //cerr << "first vpImagename " << vpImageName  << endl;
     211             :                           if(vpImageName==""){
     212             :                         String beamPath;
     213             :                         if(!MeasTable::AntennaResponsesPath(beamPath, "ALMA")){
     214             :                           throw(AipsError("Alma beam images requested cannot be found "));
     215             :                         }
     216             :                         else{
     217             :                           beamPath=beamPath.before(String("AntennaResponses"));
     218             :                           vpImageName= (abs(dishDiam[k]-7.0) < 1.0) ? beamPath
     219             :                             +String("/ALMA_AIRY_7M.VP") :
     220             :                             beamPath+String("/ALMA_AIRY_12M.VP");
     221             :                         }
     222             : 
     223             : 
     224             :                           }
     225             :                           //cerr << "Using the image VPs " << vpImageName << endl;
     226             :                           if(Table::isReadable(vpImageName))
     227             :                         antMath_p[diamIndex]=new PBMath2DImage(PagedImage<Complex>(vpImageName));
     228             :                           else
     229             :                         throw(AipsError(String("Cannot find voltage pattern image ") + vpImageName));
     230             :                         }
     231             :                         else{
     232             : 
     233             :                           throw(AipsError("Do not  deal with non airy dishes or images of VP yet "));
     234             :                         }
     235             :                         */
     236           0 :                         ++diamIndex;
     237             :             
     238             :                     }
     239             : 
     240             :                 }
     241             :             }
     242             : 
     243           0 :         }
     244           0 :         else if(pbClass_p== PBMathInterface::IMAGE) {
     245             : 
     246           0 :             VPManager *vpman=VPManager::Instance();
     247           0 :             if(vpTable_p != String(""))
     248           0 :                 vpman->loadfromtable(vpTable_p);
     249             :             ///else it is already loaded in the static object
     250           0 :             Vector<Record> recs;
     251           0 :             Vector<Vector<String> > antnames;
     252             : 
     253           0 :             if(vpman->imagepbinfo(antnames, recs)) {
     254           0 :                 Vector<Bool> dishDefined(dishName.nelements(), false);
     255           0 :                 Int nbeams=antnames.nelements();
     256             :                 ///will be keying on file image file name here
     257           0 :                 for (uInt k=0; k < dishDiam.nelements(); ++k) {
     258           0 :                     String key;
     259           0 :                     Bool beamDone=false;
     260           0 :                     Int recordToUse=0;
     261           0 :                     for (Int j =0; j < nbeams; ++j) {
     262           0 :                         key=recs[j].isDefined("realimage") ? recs[j].asString("realimage") : recs[j].asString("compleximage");
     263           0 :                         if(antnames[j][0]=="*" || anyEQ(dishName[k], antnames[j])) {
     264           0 :                             dishDefined[k]=true;
     265           0 :                             recordToUse=j;
     266             : 
     267           0 :                             if((diamIndex !=0) && antDiam2IndexMap_p.find(key) != antDiam2IndexMap_p.end( )) {
     268           0 :                                 antIndexToDiamIndex_p(k)=antDiam2IndexMap_p[key];
     269           0 :                                 beamDone=true;
     270             :                             }
     271             :                         }
     272             :                     }
     273           0 :                     if(!beamDone && dishDefined[k]) {
     274           0 :                         key=recs[recordToUse].isDefined("realimage") ? recs[recordToUse].asString("realimage") : recs[recordToUse].asString("compleximage");
     275           0 :                         antDiam2IndexMap_p.insert(std::pair<casacore::String, casacore::Int>(key, diamIndex));
     276           0 :                         antIndexToDiamIndex_p(k)=diamIndex;
     277           0 :                         antMath_p.resize(diamIndex+1);
     278           0 :                         if(recs[recordToUse].isDefined("realimage") && recs[recordToUse].isDefined("imagimage")) {
     279             :                           //PagedImage<Float> realim(recs[recordToUse].asString("realimage"));
     280             :                           // PagedImage<Float> imagim(recs[recordToUse].asString("imagim"));
     281             :                           //  antMath_p[diamIndex]=new PBMath2DImage(realim, imagim);
     282             : 
     283           0 :                           if(!Table::isReadable(recs[recordToUse].asString("realimage")))
     284           0 :                             throw(AipsError("real part of VP "+recs[recordToUse].asString("realimage")+ " is not readable"));
     285           0 :                           PagedImage<Float> realim(recs[recordToUse].asString("realimage"));
     286           0 :                           CountedPtr<ImageInterface<Float> >imagim;
     287           0 :                           if(recs[recordToUse].asString("imagimage").size()==0){
     288           0 :                             imagim=new TempImage<Float>(realim.shape(), realim.coordinates());
     289           0 :                             imagim->set(0.0);
     290             :                           }
     291             :                           else{
     292           0 :                             if(!Table::isReadable(recs[recordToUse].asString("imagimage")))
     293           0 :                               throw(AipsError("Imaginary part of VP "+recs[recordToUse].asString("imagimage")+ " is not readable"));
     294           0 :                             imagim= new PagedImage<Float> (recs[recordToUse].asString("imagimage"));
     295             :                           }
     296           0 :                             antMath_p[diamIndex]=new PBMath2DImage(realim, *imagim);
     297             : 
     298           0 :                         }
     299             :                         else {
     300             :                           //antMath_p[diamIndex]=new PBMath2DImage(PagedImage<Complex>(recs[recordToUse].asString("compleximage")));
     301             :                           
     302           0 :                            if(!Table::isReadable(recs[recordToUse].asString("compleximage")))
     303           0 :                              throw(AipsError("complex image of VP "+recs[recordToUse].asString("compleximage")+ " is not readable"));
     304           0 :                            antMath_p[diamIndex]=new PBMath2DImage(PagedImage<Complex>(recs[recordToUse].asString("compleximage")));
     305             :                          
     306             :                         }
     307           0 :                         ++diamIndex;
     308             :                     }
     309           0 :                 }
     310           0 :                 if(!allTrue(dishDefined)) {
     311             :                     //cerr << "dishDefined " << dishDefined << endl;
     312           0 :                     throw(AipsError("Some Antennas in the MS did not have a VP defined"));
     313             :                 }
     314           0 :             }
     315             :             else {
     316           0 :                 throw(AipsError("Mosaic does not support non-image voltage patterns yet"));
     317             :             }
     318             : 
     319             :             //Get rid of the static class
     320           0 :             vpman->reset();
     321           0 :         }
     322           0 :         else if(vpTable_p != String("")){
     323             :           ////When we get vpmanager to give beams on antenna name we
     324             :           //should change this key to antenna name and loop over all antenna names
     325           0 :       if((diamIndex !=0) && antDiam2IndexMap_p.find(telescop+String("_")+String::toString(dishDiam(0))) != antDiam2IndexMap_p.end( ) ) {
     326           0 :             antIndexToDiamIndex_p.set(antDiam2IndexMap_p[telescop+String("_")+String::toString(dishDiam(0))]);
     327             :           }
     328             :           else{
     329           0 :                  antDiam2IndexMap_p.insert(std::pair<casacore::String, casacore::Int>(telescop+"_"+String::toString(dishDiam(0)), diamIndex));
     330           0 :                  antIndexToDiamIndex_p.set(diamIndex);
     331           0 :              VPManager *vpman=VPManager::Instance();
     332           0 :              vpman->loadfromtable(vpTable_p);
     333           0 :              Record rec;
     334           0 :              vpman->getvp(rec, telescop);
     335           0 :              antMath_p.resize(diamIndex+1);
     336           0 :              antMath_p[diamIndex]=PBMath::pbMathInterfaceFromRecord(rec);
     337           0 :              vpman->reset();
     338           0 :           }
     339             :           
     340             :         }
     341           0 :         else if(pbClass_p==PBMathInterface::COMMONPB) {
     342             :             //cerr << "Doing the commonPB thing" << endl;
     343             :             ///Have to use telescop part as string as in multims case different
     344             :             //telescopes may have same dish size but different commonpb
     345             :             // VLA and EVLA for e.g.
     346           0 :             if((diamIndex !=0) && antDiam2IndexMap_p.find(telescop+String("_")+String::toString(dishDiam(0))) != antDiam2IndexMap_p.end( )) {
     347           0 :                 antIndexToDiamIndex_p.set(antDiam2IndexMap_p[telescop+String("_")+String::toString(dishDiam(0))]);
     348             :             }
     349             :             else {
     350           0 :                 antDiam2IndexMap_p.insert(std::pair<casacore::String, casacore::Int>(telescop+"_"+String::toString(dishDiam(0)), diamIndex));
     351           0 :                 antIndexToDiamIndex_p.set(diamIndex);
     352           0 :                 antMath_p.resize(diamIndex+1);
     353           0 :                 antMath_p[diamIndex]=PBMath::pbMathInterfaceForCommonPB(whichPB, True);
     354             :             }
     355             :         }
     356             :         else {
     357             : 
     358           0 :             throw(AipsError("Mosaic  supports image based or Airy voltage patterns or known common pb   for now"));
     359             : 
     360             :         }
     361             : 
     362             :         //cerr << "antIndexTodiamIndex " << antIndexToDiamIndex_p << endl;
     363           0 :     }
     364             : 
     365             : 
     366             : 
     367             : 
     368             : 
     369           0 : }
     370             : 
     371           0 : void  HetArrayConvFunc::reset() {
     372           0 :     doneMainConv_p=false;
     373           0 :     convFunctions_p.resize(0, true);
     374           0 :     convWeights_p.resize(0, true);
     375           0 :     convSizes_p.resize(0, true);
     376           0 :     convSupportBlock_p.resize(0, true);
     377           0 :     convFunctionMap_p.resize(0);
     378           0 :     vbConvIndex_p.clear();
     379           0 :     ft_p=FFT2D(true);
     380           0 : }
     381             : 
     382             : 
     383             : 
     384           0 : void HetArrayConvFunc::findConvFunction(const ImageInterface<Complex>& iimage,
     385             :                                         const vi::VisBuffer2& vb,
     386             :                                         const Int& convSamp, const Vector<Double>& visFreq,
     387             :                                         Array<Complex>& convFunc,
     388             :                                         Array<Complex>& weightConvFunc,
     389             :                                         Vector<Int>& convsize,
     390             :                                         Vector<Int>& convSupport,
     391             :                                         Vector<Int>& convFuncPolMap,
     392             :                                         Vector<Int>& convFuncChanMap,
     393             :                                         Vector<Int>& convFuncRowMap, Bool getConjConvFunc,
     394             :                                         const MVDirection& extraShift, const Bool useExtraShift)
     395             : {
     396             : 
     397           0 :     storeImageParams(iimage,vb);
     398           0 :     convFuncChanMap.resize(vb.nChannels());
     399           0 :     Vector<Double> beamFreqs;
     400           0 :     findUsefulChannels(convFuncChanMap, beamFreqs, vb, visFreq);
     401           0 :     Int nBeamChans=beamFreqs.nelements();
     402             :     /////For now not doing beam rotation or squints but to be enabled easily
     403           0 :     convFuncPolMap.resize(vb.nCorrelations());
     404           0 :     Int nBeamPols=1;
     405           0 :     convFuncPolMap.set(0);
     406           0 :     findAntennaSizes(vb);
     407           0 :     uInt ndish=antMath_p.nelements();
     408           0 :     if(ndish==0)
     409           0 :         throw(AipsError("Don't have dishsize"));
     410             :     Int ndishpair;
     411           0 :     if(ndish==1)
     412           0 :         ndishpair=1;
     413             :     else
     414           0 :         ndishpair=factorial(ndish)/factorial(ndish-2)/2 + ndish;
     415             : 
     416           0 :     convFunc.resize();
     417           0 :     weightConvFunc.resize();
     418           0 :     convFuncRowMap.resize();
     419           0 :     convsize.resize();
     420           0 :     convSupport.resize();
     421             : 
     422           0 :     Int isCached=checkPBOfField(vb, convFuncRowMap, extraShift, useExtraShift);
     423             :     //cout << "isCached " << isCached <<  endl;
     424           0 :     if(isCached==1 && (convFuncRowMap.shape()[0]==(ssize_t)vb.nRows())) {
     425             :         /*convFunc.reference(convFunc_p);
     426             :         weightConvFunc.reference(weightConvFunc_p);
     427             :         convsize=*convSizes_p[actualConvIndex_p];
     428             :         convSupport=convSupport_p;
     429             :          return;
     430             :         */
     431             :     }
     432           0 :     else if(isCached ==2) {
     433           0 :         convFunc.resize();
     434           0 :         weightConvFunc.resize();
     435           0 :         convsize.resize();
     436           0 :         convSupport.resize();
     437           0 :         convFuncRowMap.resize();
     438           0 :         return;
     439             : 
     440             :     }
     441             :     /////TESTOO elkey
     442           0 :     String elkey=String::toString(vb.msId())+String("_")+String::toString(vb.spectralWindows()[0])+String("_")+String::toString(visFreq.nelements());
     443             : 
     444             :     /////////////////
     445           0 :     actualConvIndex_p=convIndex(vb, visFreq.nelements());
     446             :     //cerr << "actual conv index " << actualConvIndex_p << " doneMainconv " << doneMainConv_p << endl;
     447           0 :     if(doneMainConv_p.shape()[0] < (actualConvIndex_p+1)) {
     448             :         //cerr << "resizing DONEMAIN " <<   doneMainConv_p.shape()[0] << endl;
     449           0 :         doneMainConv_p.resize(actualConvIndex_p+1, true);
     450           0 :         doneMainConv_p[actualConvIndex_p]=false;
     451           0 :         convFunctions_p.resize(actualConvIndex_p+1);
     452           0 :         convFunctions_p[actualConvIndex_p]=nullptr;
     453             :     }
     454             :     ///// In multi ms mode ndishpair may change when meeting a new ms
     455             :     //// redo the calculation then
     456           0 :     if(msId_p != vb.msId())//doneMainConv_p[actualConvIndex_p] && ((convSupport_p.nelements() != uInt(ndishpair)) || convFunctions_p[actualConvIndex_p]->shape()[3] != nBeamChans))
     457             :     {
     458           0 :         doneMainConv_p[actualConvIndex_p]=false;
     459             :         //cerr << "invalidating doneMainConv " <<  convFunctions_p[actualConvIndex_p]->shape()[3] << " =? " << nBeamChans << " convsupp " << convSupport_p.nelements() << endl;
     460             :     }
     461             : 
     462             :     ////Trap for cases when the selection seem to have changed
     463           0 :     if(doneMainConv_p[actualConvIndex_p]){
     464           0 :       if(nBeamChans > (*convFunctions_p[actualConvIndex_p]).shape()[3])
     465           0 :         doneMainConv_p[actualConvIndex_p]=False;
     466             :       
     467             :     }
     468             : 
     469             : 
     470             : 
     471             :     
     472             :     // Get the coordinate system
     473           0 :     CoordinateSystem coords(iimage.coordinates());
     474           0 :     Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
     475           0 :     AlwaysAssert(directionIndex>=0, AipsError);
     476             :     // Set up the convolution function.
     477           0 :     Int nx=nx_p;
     478           0 :     Int ny=ny_p;
     479           0 :     Int support=max(nx_p, ny_p)/10;
     480           0 :     Int convSampling=1;
     481           0 :     if(!doneMainConv_p[actualConvIndex_p]) {
     482           0 :         for (uInt ii=0; ii < ndish; ++ii) {
     483           0 :             support=max((antMath_p[ii])->support(coords), support);
     484             :         }
     485             :         
     486           0 :         support=Int(min(Float(support), max(Float(nx_p), Float(ny_p)))*2.0)/2;
     487           0 :         convSize_p=support*convSampling;
     488             :         // Make this a nice composite number, to speed up FFTs
     489           0 :         CompositeNumber cn(uInt(convSize_p*2.0));
     490           0 :         convSize_p  = cn.nextLargerEven(Int(convSize_p));
     491           0 :         convSize_p=(convSize_p/16)*16;  // need it to be divisible by 8 in places
     492             :         
     493           0 :     }
     494             : 
     495             : 
     496           0 :     DirectionCoordinate dc=dc_p;
     497             :     //where in the image in pixels is this pointing
     498           0 :     Vector<Double> pixFieldDir(2);
     499           0 :     if(doneMainConv_p.shape()[0] < (actualConvIndex_p+1)) {
     500             :         //cerr << "resizing DONEMAIN " <<   doneMainConv_p.shape()[0] << endl;
     501           0 :         doneMainConv_p.resize(actualConvIndex_p+1, true);
     502           0 :         doneMainConv_p[actualConvIndex_p]=false;
     503             :     }
     504             :     //no need to call toPix here as its been done already above in checkOFPB
     505             :     //thus the values are still current.
     506           0 :     pixFieldDir=thePix_p;
     507             :     //toPix(pixFieldDir, vb);
     508           0 :     MDirection fieldDir=direction1_p;
     509             :     //shift from center
     510           0 :     pixFieldDir(0)=pixFieldDir(0)- Double(nx / 2);
     511           0 :     pixFieldDir(1)=pixFieldDir(1)- Double(ny / 2);
     512             :     //phase gradient per pixel to apply
     513           0 :     pixFieldDir(0)=-pixFieldDir(0)*2.0*C::pi/Double(nx)/Double(convSamp);
     514           0 :     pixFieldDir(1)=-pixFieldDir(1)*2.0*C::pi/Double(ny)/Double(convSamp);
     515             : 
     516             :   
     517           0 :     if(!doneMainConv_p[actualConvIndex_p]) {
     518             :       //cerr << "doneMainConv_p " << actualConvIndex_p << endl;
     519             : 
     520           0 :         Vector<Double> sampling;
     521             :         
     522           0 :         sampling = dc.increment();
     523           0 :         sampling*=Double(convSampling);
     524           0 :         sampling(0)*=Double(nx)/Double(convSize_p);
     525           0 :         sampling(1)*=Double(ny)/Double(convSize_p);
     526           0 :         dc.setIncrement(sampling);
     527             : 
     528           0 :         Vector<Double> unitVec(2);
     529           0 :         unitVec=convSize_p/2;
     530           0 :         dc.setReferencePixel(unitVec);
     531             :         //make sure we are using the same units
     532           0 :         fieldDir.set(dc.worldAxisUnits()(0));
     533           0 :         dc.setReferenceValue(fieldDir.getAngle().getValue());
     534           0 :         coords.replaceCoordinate(dc, directionIndex);
     535           0 :         Int spind=coords.findCoordinate(Coordinate::SPECTRAL);
     536           0 :         SpectralCoordinate spCoord=coords.spectralCoordinate(spind);
     537           0 :         spCoord.setReferencePixel(Vector<Double>(1,0.0));
     538           0 :         spCoord.setReferenceValue(Vector<Double>(1, beamFreqs(0)));
     539           0 :         if(beamFreqs.nelements() >1)
     540           0 :           spCoord.setIncrement(Vector<Double>(1, beamFreqs(1)-beamFreqs(0)));
     541             :         //cerr << "spcoord " ;
     542             :         //spCoord.print(std::cerr);
     543           0 :         coords.replaceCoordinate(spCoord, spind);
     544           0 :         CoordinateSystem conjCoord=coords;
     545           0 :         Double centerFreq=SpectralImageUtil::worldFreq(csys_p, 0.0);
     546           0 :         SpectralCoordinate conjSpCoord=spCoord;
     547             :                 //cerr << "centreFreq " << centerFreq << " beamFreqs " << beamFreqs(0) << "  " << beamFreqs(1) << endl;
     548           0 :         conjSpCoord.setReferenceValue(Vector<Double>(1,SynthesisUtils::conjFreq(beamFreqs[0], centerFreq)));
     549             :         ///Increment should go in the reverse direction
     550             :         ////Do a tabular spectral coordinate for more than 1 channel 
     551           0 :         if(beamFreqs.nelements() >1){
     552           0 :           Vector<Double> conjFreqs(beamFreqs.nelements());
     553           0 :           for (uInt kk=0; kk< beamFreqs.nelements(); ++kk){
     554             :             //conjFreqs[kk]=sqrt(2*centerFreq*centerFreq-beamFreqs(kk)*beamFreqs(kk));
     555           0 :             conjFreqs[kk]=SynthesisUtils::conjFreq(beamFreqs[kk], centerFreq);
     556             :           }
     557           0 :           conjSpCoord=SpectralCoordinate(spCoord.frequencySystem(), conjFreqs, spCoord.restFrequency());
     558             :           //conjSpCoord.setIncrement(Vector<Double>(1, beamFreqs(0)-beamFreqs(1)));
     559           0 :         }
     560           0 :         conjCoord.replaceCoordinate(conjSpCoord, spind);
     561           0 :         IPosition pbShape(4, convSize_p, convSize_p, 1, nBeamChans);
     562             :         //TempImage<Complex> twoDPB(pbShape, coords);
     563             :         
     564             :         
     565           0 :         TempLattice<Complex> convFuncTemp(TiledShape(IPosition(5, convSize_p/4, convSize_p/4, nBeamPols, nBeamChans, ndishpair), IPosition(5, convSize_p/4, convSize_p/4, 1, 1, 1)), 0);
     566           0 :         TempLattice<Complex> weightConvFuncTemp(TiledShape(IPosition(5, convSize_p/4, convSize_p/4, nBeamPols, nBeamChans, ndishpair), IPosition(5, convSize_p/4, convSize_p/4, 1, 1, 1)), 0);
     567             :         //convFunc_p.resize(IPosition(5, convSize_p, convSize_p, nBeamPols, nBeamChans, ndishpair));
     568             : 
     569             :         // convFunc_p=0.0;
     570             :         //weightConvFunc_p.resize(IPosition(5, convSize_p, convSize_p, nBeamPols, nBeamChans, ndishpair));
     571             :         //weightConvFunc_p=0.0;
     572           0 :         IPosition begin(5, 0, 0, 0, 0, 0);
     573           0 :         IPosition end(5, convFuncTemp.shape()[0]-1,  convFuncTemp.shape()[1]-1, nBeamPols-1, nBeamChans-1, 0);
     574             :         //FFTServer<Float, Complex> fft(IPosition(2, convSize_p, convSize_p));
     575             :         //TempImage<Complex> pBScreen(TiledShape(pbShape, IPosition(4, convSize_p, convSize_p, 1, 1)), coords, 0);
     576             :         //TempImage<Complex> pB2Screen(TiledShape(pbShape, IPosition(4, convSize_p, convSize_p, 1, 1)), coords, 0);
     577           0 :         Long memtot=HostInfo::memoryFree();
     578           0 :         Double memtobeused= Double(memtot)*1024.0;
     579           0 :         if(memtot <= 2000000)
     580           0 :             memtobeused=0.0;
     581           0 :         TempImage<Complex> pBScreen(TiledShape(pbShape), coords, memtobeused/2.2);
     582             :                 
     583           0 :         TempImage<Complex> pB2Screen(TiledShape(pbShape), ((nchan_p==1) && getConjConvFunc) ?conjCoord : coords  , memtobeused/2.2);
     584           0 :         IPosition start(4, 0, 0, 0, 0);
     585           0 :         convSupport_p.resize(ndishpair);
     586             :         //////////////////
     587             :         /*Double wtime0=0.0;
     588             :         Double wtime1=0.0;
     589             :         Double wtime2=0.0;
     590             :         wtime0=omp_get_wtime()
     591             :         */;
     592             :         //////////////
     593           0 :         for (uInt k=0; k < ndish; ++k) {
     594             : 
     595           0 :             for (uInt j =k ; j < ndish; ++j) {
     596             :                 //Timer tim;
     597             :                 //Matrix<Complex> screen(convSize_p, convSize_p);
     598             :                 //screen=1.0;
     599             :                 //pBScreen.putSlice(screen, start);
     600             :                 //cerr << "k " << k << " shape " << pBScreen.shape() <<  " direction1 " << direction1_p << " direction2 " << direction2_p << endl;
     601             : 
     602             :                 //pBScreen.set(Complex(1.0, 0.0));
     603             :                 //one antenna
     604           0 :                 antMath_p[k]->setBandOrFeedName(bandName_p);
     605           0 :                 antMath_p[j]->setBandOrFeedName(bandName_p);
     606           0 :                 IPosition blcin(4, 0, 0, 0, 0);
     607           0 :                 IPosition trcin(4, convSize_p-1, convSize_p-1, 0, 0);
     608           0 :                 for (Int kk=0; kk < nBeamChans; ++kk) {
     609           0 :                     blcin[3]=kk;
     610           0 :                     trcin[3]=kk;
     611             :                     //wtime0=omp_get_wtime();
     612           0 :                     Slicer slin(blcin, trcin, Slicer::endIsLast);
     613           0 :                     SubImage<Complex> subim(pBScreen, slin, true);
     614           0 :                     subim.set(Complex(1.0, 0.0));
     615           0 :                     (antMath_p[k])->applyVP(subim, subim, direction1_p);
     616             : 
     617             :                     //Then the other
     618           0 :                     (antMath_p[j])->applyVP(subim, subim, direction2_p);
     619             :                     //tim.show("After Apply ");
     620             :                     //tim.mark();
     621             :                     //pB2Screen.set(Complex(1.0,0.0));
     622           0 :                     SubImage<Complex> subim2(pB2Screen, slin, true);
     623           0 :                                         subim2.set(Complex(1.0,0.0));
     624             :                     
     625           0 :                                         if(nchan_p >1 || !getConjConvFunc){
     626             :                                                 //one antenna
     627           0 :                                                 (antMath_p[k])->applyPB(subim2, subim2, direction1_p);
     628             :                                                 //Then the other
     629           0 :                                                 (antMath_p[j])->applyPB(subim2, subim2, direction2_p);
     630             :                                         }
     631             :                                         else{
     632             :                                                 //direct frequency PB
     633             :                                                 //cerr << "orig coords " << subim.coordinates().toWorld(IPosition(4,0,0,0,0)) << " conj coords " <<  subim2.coordinates().toWorld(IPosition(4,0,0,0,0)) << endl;
     634             :                                                 //cerr << "incr " << subim.coordinates().increment() << "   " << subim2.coordinates().increment() << endl;
     635           0 :                                                 subim2.copyData(subim);
     636             :                                                 //Now do the conjugate freq multiplication
     637           0 :                                                 (antMath_p[k])->applyVP(subim2, subim2, direction1_p);
     638             : 
     639             :                                                 //Then the other
     640           0 :                                                 (antMath_p[j])->applyVP(subim2, subim2, direction2_p);
     641             :                                                 
     642             :                                                 /*
     643             :                                                 //one antenna
     644             :                                                 (antMath_p[k])->applyPB(subim2, subim2, direction1_p);
     645             :                                                 //Then the other
     646             :                                                 (antMath_p[j])->applyPB(subim2, subim2, direction2_p);
     647             :                                                 */
     648             :                                         }
     649             :                     //tim.show("After Apply2 ");
     650             :                     //tim.mark();
     651             :                                         //wtime1+=omp_get_wtime()-wtime0;
     652             :                     //subim.copyData((LatticeExpr<Complex>) (iif(abs(subim)> 5e-2, subim, 0)));
     653             :                     //subim2.copyData((LatticeExpr<Complex>) (iif(abs(subim2)> 25e-4, subim2, 0)));
     654             : 
     655             :                                         //wtime0=omp_get_wtime();
     656             : 
     657             :                     //make sure fft2d plan shape is the same or else recalculate it
     658           0 :                     auto [ftx, fty] = ft_p.getShape();
     659           0 :                     if(ftx >0 && fty >0 && (ftx != subim.shape()(0)) && (fty != subim.shape()(1))){
     660           0 :                       ft_p = FFT2D(true);
     661             :                     }
     662             : 
     663           0 :                     ft_p.c2cFFTInDouble(subim);
     664           0 :                     ft_p.c2cFFTInDouble(subim2);
     665             :                                         //ft_p.c2cFFT(subim);
     666             :                                         //ft_p.c2cFFT(subim2);
     667             :                                         //wtime2+=omp_get_wtime()-wtime0;
     668             :                     //  tim.show("after ffts ");
     669             : 
     670             : 
     671           0 :                 }
     672             :                 //cerr << "Apply " << wtime1 << "  fft " << wtime2 << endl;
     673             :                 /*
     674             :                 if(nBeamChans >1){
     675             :                   Slicer slin(blcin, trcin, Slicer::endIsLast);
     676             :                   SubImage<Complex> origPB(pBScreen, slin, false);
     677             :                   IPosition elshape= origPB.shape();
     678             :                   Matrix<Complex> i1=origPB.get(true);
     679             :                   SubImage<Complex> origPB2(pB2Screen, slin, false);
     680             :                   Matrix<Complex> i2=origPB2.get(true);
     681             :                   Int cenX=i1.shape()(0)/2;
     682             :                   Int cenY=i1.shape()(1)/2;
     683             : 
     684             :                   for (Int kk=0; kk < (nBeamChans-1); ++kk){
     685             :                     Double fratio=beamFreqs(kk)/beamFreqs(nBeamChans-1);
     686             :                     cerr << "fratio " << fratio << endl;
     687             :                     blcin[3]=kk;
     688             :                     trcin[3]=kk;
     689             :                     //Slicer slout(blcin, trcin, Slicer::endIsLast);
     690             :                     Matrix<Complex> o1(i1.shape(), Complex(0.0));
     691             :                     Matrix<Complex> o2(i2.shape(), Complex(0.0));
     692             :                     for (Int yy=0;  yy < i1.shape()(1); ++yy){
     693             :                       //Int nyy= (Double(yy-cenY)*fratio) + cenY;
     694             :                       Double nyy= (Double(yy-cenY)/fratio) + cenY;
     695             :                       Double cyy=ceil(nyy);
     696             :                       Double fyy= floor(nyy);
     697             :                       Int iy=nyy > fyy+0.5 ? cyy : fyy;
     698             :                       if(cyy <2*cenY && fyy >=0.0)
     699             :                  for(Int xx=0; xx < i1.shape()(0); ++ xx){
     700             :                    //Int nxx= Int(Double(xx-cenX)*fratio) + cenX;
     701             :                    Double nxx= Int(Double(xx-cenX)/fratio) + cenX;
     702             :                     Double cxx=ceil(nxx);
     703             :                     Double fxx= floor(nxx);
     704             :                     Int ix=nxx > fxx+0.5 ? cxx : fxx ;
     705             :                    if(cxx < 2*cenX && fxx >=0.0 ){
     706             :                      //Double dist=sqrt((nxx-cxx)*(nxx-cxx)+(nyy-cyy)*(nyy-cyy))/sqrt(2.0);
     707             :                      //o1(xx, yy)=float(1-dist)*i1(fxx, fyy)+ dist*i1(cxx,cyy);
     708             :                      o1(xx, yy)=i1( ix, iy);
     709             :                      //o2(xx, yy)=i2(nxx, nyy);
     710             :                      //o2(xx, yy)=float(1-dist)*i2(fxx, fyy)+ dist*i2(cxx,cyy);
     711             :                      o2(xx, yy)=i2(ix, iy);
     712             :                    }
     713             :                  }
     714             :                     }
     715             :                     pBScreen.putSlice(o1.reform(elshape), blcin);
     716             :                     pB2Screen.putSlice(o2.reform(elshape), blcin);
     717             :                   }
     718             : 
     719             :                 }
     720             :                 */
     721             : 
     722             :                 //tim.show("after apply+apply2+masking+fft ");
     723             :                 //tim.mark();
     724             :                 //LatticeFFT::cfft2d(pBScreen);
     725             :                 //LatticeFFT::cfft2d(pB2Screen);
     726             : 
     727             :                 //Matrix<Complex> lala=pBScreen.get(true);
     728             :                 //fft.fft0(lala, true);
     729             :                 //fft.flip(lala, false, false);
     730             :                 // pBScreen.put(lala.reform(IPosition(4, convSize_p, convSize_p, 1, 1)));
     731             :                 //lala=pB2Screen.get(true);
     732             :                 //fft.fft0(lala, true);
     733             :                 //fft.flip(lala, false, false);
     734             :                 //pB2Screen.put(lala.reform(IPosition(4, convSize_p, convSize_p, 1, 1)));
     735             : 
     736             :                 //////////*****************
     737             :                 /*if(0){
     738             :                   ostringstream os1;
     739             :                   os1 << "PB_field_" << Int(thePix_p[0]) << "_" << Int(thePix_p[1]) << "_antpair_" << k <<"_"<<j ;
     740             :                   PagedImage<Float> thisScreen(pbShape, coords, String(os1));
     741             :                   LatticeExpr<Float> le(abs(pBScreen));
     742             :                   thisScreen.copyData(le);
     743             :                   }*/
     744             :                 ////////*****************/
     745             : 
     746             :                 //tim.show("after FFT ");
     747             :                 //tim.mark();
     748           0 :                 Int plane=0;
     749           0 :                 for (uInt jj=0; jj < k; ++jj)
     750           0 :                     plane=plane+ndish-jj-1;
     751           0 :                 plane=plane+j;
     752           0 :                 begin[4]=plane;
     753           0 :                 end[4]=plane;
     754           0 :                 Slicer slplane(begin, end, Slicer::endIsLast);
     755             :                 //cerr <<  "SHAPES " << convFunc_p(begin, end).shape() << "  " << pBScreen.get(false).shape() << " begin and end " << begin << "    " << end << endl;
     756             :                 //convFunc_p(begin, end).copyMatchingPart(pBScreen.get(false));
     757             :                 //weightConvFunc_p(begin, end).copyMatchingPart(pB2Screen.get(false));
     758           0 :                 IPosition blcQ(4, pbShape(0)/8*3, pbShape(1)/8*3, 0, 0);
     759           0 :                 IPosition trcQ(4,  blcQ[0]+ pbShape(0)/4-1, blcQ[1]+pbShape(1)/4-1 , nBeamPols-1, nBeamChans-1);
     760             : 
     761             :                 //cerr << "blcQ " << blcQ << " trcQ " << trcQ << " pbShape " << pbShape << endl;
     762           0 :                 Slicer slQ(blcQ, trcQ, Slicer::endIsLast);
     763             :                 {
     764           0 :                     SubImage<Complex>  pBSSub(pBScreen, slQ, false);
     765           0 :                     SubLattice<Complex> cFTempSub(convFuncTemp,  slplane, true);
     766           0 :                     LatticeConcat<Complex> lc(4);
     767           0 :                     lc.setLattice(pBSSub);
     768             :                     //cerr << "SHAPES " << cFTempSub.shape() << "   " <<  lc.shape() << endl;
     769           0 :                     cFTempSub.copyData(lc);
     770             :                     //cFTempSub.copyData(pBScreen);
     771           0 :                 }
     772             :                 {
     773           0 :                     SubImage<Complex>  pB2SSub(pB2Screen, slQ, false);
     774           0 :                     SubLattice<Complex> cFTempSub2(weightConvFuncTemp,  slplane, true);
     775           0 :                     LatticeConcat<Complex> lc(4);
     776           0 :                     lc.setLattice(pB2SSub);
     777           0 :                     cFTempSub2.copyData(lc);
     778             :                     // cFTempSub2.copyData(pB2Screen);
     779             :                     //weightConvFuncTemp.putSlice(pB2Screen.get(false), begin);
     780             : 
     781           0 :                 }
     782             :                 //        supportAndNormalize(plane, convSampling);
     783           0 :                 supportAndNormalizeLatt( plane, convSampling, convFuncTemp,  weightConvFuncTemp);
     784             : 
     785             : 
     786             : 
     787             :                 // tim.show("After search of support ");
     788           0 :             }
     789             : 
     790             :         }
     791             : 
     792             : 
     793           0 :         doneMainConv_p[actualConvIndex_p]=true;
     794           0 :         convFunctions_p.resize(actualConvIndex_p+1);
     795           0 :         convWeights_p.resize(actualConvIndex_p+1);
     796           0 :         convSupportBlock_p.resize(actualConvIndex_p+1);
     797             :         //Using conjugate change support to be larger of either
     798           0 :         if((nchan_p == 1) && getConjConvFunc) {
     799           0 :           Int conjsupp=conjSupport(beamFreqs) ;
     800           0 :           if(conjsupp > max(convSupport_p)){
     801           0 :             convSupport_p=conjsupp;
     802             :           }
     803             : 
     804             :         }
     805           0 :         convFunctions_p[actualConvIndex_p]= new Array<Complex>();
     806           0 :         convWeights_p[actualConvIndex_p]= new Array<Complex>();
     807           0 :         convSupportBlock_p[actualConvIndex_p]=new Vector<Int>();
     808           0 :         Int newConvSize=2*(max(convSupport_p)+2)*convSampling;
     809           0 :         Int newRealConvSize=newConvSize* Int(Double(convSamp)/Double(convSampling));
     810           0 :         Int lattSize=convFuncTemp.shape()(0);
     811           0 :         (*convSupportBlock_p[actualConvIndex_p])=convSupport_p;
     812           0 :         LogIO os(LogOrigin("HetArrConvFunc", "findConvFunction", WHERE));
     813           0 :         os << "convolution function support: " << convSupport_p<< "ELKEY " << elkey  << " actualConvInd "<< actualConvIndex_p <<  " pointer " << this << LogIO::POST;
     814             : 
     815           0 :         if(newConvSize < lattSize) {
     816           0 :             IPosition blc(5, (lattSize/2)-(newConvSize/2),
     817           0 :                           (lattSize/2)-(newConvSize/2),0,0,0);
     818           0 :             IPosition trc(5, (lattSize/2)+(newConvSize/2-1),
     819           0 :                           (lattSize/2)+(newConvSize/2-1), nBeamPols-1, nBeamChans-1,ndishpair-1);
     820           0 :             IPosition shp(5, newConvSize, newConvSize, nBeamPols, nBeamChans, ndishpair);
     821             : 
     822           0 :             convFunctions_p[actualConvIndex_p]= new Array<Complex>(IPosition(5, newRealConvSize, newRealConvSize, nBeamPols, nBeamChans, ndishpair ));
     823           0 :             convWeights_p[actualConvIndex_p]= new Array<Complex>(IPosition(5, newRealConvSize, newRealConvSize, nBeamPols, nBeamChans, ndishpair ));
     824           0 :             (*convFunctions_p[actualConvIndex_p])=resample(convFuncTemp.getSlice(blc,shp),Double(convSamp)/Double(convSampling));
     825           0 :             convSize_p=newRealConvSize;
     826           0 :             (*convWeights_p[actualConvIndex_p])=resample(weightConvFuncTemp.getSlice(blc, shp),Double(convSamp)/Double(convSampling));
     827             :             //cerr << "nchan " << nchan_p << " getconj " << getConjConvFunc << endl;
     828             :        
     829           0 :         }
     830             :         else {
     831           0 :             newRealConvSize=lattSize* Int(Double(convSamp)/Double(convSampling));
     832           0 :             convFunctions_p[actualConvIndex_p]= new Array<Complex>(IPosition(5, newRealConvSize, newRealConvSize, nBeamPols, nBeamChans, ndishpair ));
     833           0 :             convWeights_p[actualConvIndex_p]= new Array<Complex>(IPosition(5, newRealConvSize, newRealConvSize, nBeamPols, nBeamChans, ndishpair ));
     834             : 
     835           0 :             (*convFunctions_p[actualConvIndex_p])=resample(convFuncTemp.get(),  Double(convSamp)/Double(convSampling));
     836           0 :             (*convWeights_p[actualConvIndex_p])=resample(weightConvFuncTemp.get(),  Double(convSamp)/Double(convSampling));
     837           0 :             convSize_p=newRealConvSize;
     838             :         }
     839             : 
     840             : 
     841           0 :         if((nchan_p == 1) && getConjConvFunc) {
     842           0 :           fillConjConvFunc(beamFreqs);
     843             :           /////////////////////////TESTOOO
     844             :           /*PagedImage<Complex> SCREEN2(TiledShape(convFunctions_p[actualConvIndex_p]->shape()), TMP, "CONJU"+String::toString(actualConvIndex_p));
     845             :           SCREEN2.put(*convFunctionsConjFreq_p[actualConvIndex_p]  );
     846             :           */
     847             :           ////////////////////////
     848             :         }
     849             : 
     850           0 :         convFunc_p.resize();
     851           0 :         weightConvFunc_p.resize();
     852             : 
     853           0 :     }
     854             :     else {
     855           0 :         convSize_p=max(*convSizes_p[actualConvIndex_p]);
     856           0 :         convSupport_p.resize();
     857           0 :         convSupport_p=*convSupportBlock_p[actualConvIndex_p];
     858             :     }
     859             :     /*
     860             :     rowMap.resize(vb.nRow());
     861             :     for (Int k=0; k < vb.nRow(); ++k){
     862             :       //plane of convfunc that match this pair of antennas
     863             :       rowMap(k)=antIndexToDiamIndex_p(vb.antenna1()(k))*ndish+
     864             :     antIndexToDiamIndex_p(vb.antenna2()(k));
     865             : 
     866             :     }
     867             :     */
     868             :     ////////////////TESTOOO
     869             :     //           CoordinateSystem TMP = coords;
     870             :     //    CoordinateUtil::addLinearAxes(TMP, Vector<String>(1,"gulu"), IPosition(1,nBeamChans)); 
     871             :     //    PagedImage<Complex> SCREEN(TiledShape(convFunctions_p[actualConvIndex_p]->shape()), TMP, "NONCONJUVI2"+String::toString(actualConvIndex_p));
     872             :     //    SCREEN.put(*convFunctions_p[actualConvIndex_p]  );
     873             :     //     PagedImage<Complex> SCREEN3(TiledShape(convWeights_p[actualConvIndex_p]->shape()), TMP, "FTWEIGHTVI2"+String::toString(actualConvIndex_p));
     874             :     //    SCREEN3.put(*convWeights_p[actualConvIndex_p]  );
     875             :         
     876             :     /////////////////
     877             : 
     878           0 :     makerowmap(vb, convFuncRowMap);
     879             :     ///need to deal with only the maximum of different baselines available in this
     880             :     ///vb
     881           0 :     ndishpair=max(convFuncRowMap)+1;
     882             : 
     883             :     //convSupportBlock_p.resize(actualConvIndex_p+1);
     884           0 :     convSizes_p.resize(actualConvIndex_p+1);
     885             :     //convSupportBlock_p[actualConvIndex_p]=new Vector<Int>(ndishpair);
     886             :     //(*convSupportBlock_p[actualConvIndex_p])=convSupport_p;
     887           0 :     convSizes_p[actualConvIndex_p]=new Vector<Int> (ndishpair);
     888             : 
     889             :     /*    convFunctions_p[actualConvIndex_p]->resize(convSize_p, convSize_p, ndishpair);
     890             :     *(convFunctions_p[actualConvIndex_p])=convSave_p;
     891             :     convWeights_p[actualConvIndex_p]->resize(convSize_p, convSize_p, ndishpair);
     892             :     *(convWeights_p[actualConvIndex_p])=weightSave_p;
     893             :     */
     894             : 
     895           0 :     convFunc_p.resize();
     896           0 :         if((nchan_p == 1) && getConjConvFunc) {
     897             :           // cerr << this << " recovering " << actualConvIndex_p <<  "   " <<convFunctionsConjFreq_p.size() << endl;
     898           0 :           if(Int(convFunctionsConjFreq_p.size()) <= actualConvIndex_p){
     899           0 :             fillConjConvFunc(beamFreqs);
     900             :             
     901             :           }
     902           0 :                 convFunc_p=(*convFunctionsConjFreq_p[actualConvIndex_p]);
     903             :         }
     904             :         else{
     905             :                 
     906           0 :                 convFunc_p=(*convFunctions_p[actualConvIndex_p]);
     907             :         }
     908             :         
     909           0 :     weightConvFunc_p.resize();
     910           0 :     weightConvFunc_p=(*convWeights_p[actualConvIndex_p]);
     911             : 
     912             : 
     913             :     // cerr << "convfunc shapes " <<  convFunc_p.shape() <<  "   " << weightConvFunc_p.shape() << "  " << convSize_p << " pol " << nBeamPols << "  chan " << nBeamChans << " ndishpair " << ndishpair << endl;
     914             :      /////Due to a bug in buildCoordSysCore...sometimes an image bigger
     915             :     ///than the spw selection chosen  is made
     916           0 :      if(nBeamChans > convFunc_p.shape()[3])
     917           0 :        nBeamChans = convFunc_p.shape()[3];
     918             :     //convSupport_p.resize();
     919             :     //convSupport_p=(*convSupportBlock_p[actualConvIndex_p]);
     920             :     Bool delc;
     921             :     Bool delw;
     922           0 :     Double dirX=pixFieldDir(0);
     923           0 :     Double dirY=pixFieldDir(1);
     924           0 :     Complex *convstor=convFunc_p.getStorage(delc);
     925           0 :     Complex *weightstor=weightConvFunc_p.getStorage(delw);
     926           0 :     Int elconvsize=convSize_p;
     927             : 
     928           0 :     #pragma omp parallel default(none) firstprivate(convstor, weightstor, dirX, dirY, elconvsize, ndishpair, nBeamChans, nBeamPols)
     929             :     {
     930             :       
     931             :         #pragma omp for
     932             :         for(Int iy=0; iy<elconvsize; ++iy) {
     933             :             applyGradientToYLine(iy,  convstor, weightstor, dirX, dirY, elconvsize, ndishpair, nBeamChans, nBeamPols);
     934             : 
     935             :         }
     936             :     }///End of pragma
     937             : 
     938           0 :     convFunc_p.putStorage(convstor, delc);
     939           0 :     weightConvFunc_p.putStorage(weightstor, delw);
     940             : 
     941             : 
     942             : 
     943             :     //For now all have the same size convsize;
     944           0 :     convSizes_p[actualConvIndex_p]->set(convSize_p);
     945             : 
     946             :     //We have to get the references right now
     947             :     //    convFunc_p.resize();
     948             :     //convFunc_p.reference(*convFunctions_p[actualConvIndex_p]);
     949             :     //weightConvFunc_p.resize();
     950             :     //weightConvFunc_p.reference(*convWeights_p[actualConvIndex_p]);
     951             : 
     952           0 :     convFunc.reference(convFunc_p);
     953           0 :     weightConvFunc.reference(weightConvFunc_p);
     954           0 :     convsize=*convSizes_p[actualConvIndex_p];
     955           0 :     convSupport=convSupport_p;
     956             : 
     957             : 
     958           0 : }
     959           0 :   void HetArrayConvFunc::rephaseConvFunc(const ImageInterface<Complex>& iimage, 
     960             :                                         const vi::VisBuffer2& vb,const Int& convSampling,Array<Complex>& convFunc, 
     961             :                                          Array<Complex>& weightConvFunc, const vector<Int>& polmap, const vector<Int>& chanmap, const vector<Int>& rowmap, const MVDirection& extraShift, const Bool useExtraShift){
     962           0 :     storeImageParams(iimage,vb);
     963           0 :      toPix(vb, extraShift, useExtraShift);
     964           0 :     Vector<Double> pixFieldDir(2);
     965           0 :     pixFieldDir=thePix_p;
     966           0 :      pixFieldDir(0)=pixFieldDir(0)- Double(nx_p / 2);
     967           0 :     pixFieldDir(1)=pixFieldDir(1)- Double(ny_p / 2);
     968           0 :     pixFieldDir(0)=-pixFieldDir(0)*2.0*C::pi/Double(nx_p)/Double(convSampling);
     969           0 :     pixFieldDir(1)=-pixFieldDir(1)*2.0*C::pi/Double(ny_p)/Double(convSampling);
     970           0 :     Int nconvrow=convFunc.shape()(4);
     971           0 :     Int nconvchan=convFunc.shape()(3);
     972           0 :     Int nconvpol=convFunc.shape()(2);
     973           0 :     Int convsize=convFunc.shape()(0);
     974             :     Bool delc;
     975             :     Bool delw;
     976           0 :     Double dirX=pixFieldDir(0);
     977           0 :     Double dirY=pixFieldDir(1);
     978           0 :     Complex *convstor=convFunc.getStorage(delc);
     979           0 :     Complex *weightstor=weightConvFunc.getStorage(delw);
     980             :     //Vector<Int> pmap(polmap);
     981             :     //Vector<Int> cmap(chanmap);
     982             :     //Vector<Int> rmap(rowmap);
     983           0 : #pragma omp parallel default(none) firstprivate(convstor, weightstor, dirX, dirY, convsize, nconvrow, nconvchan, nconvpol) shared(polmap, chanmap, rowmap)
     984             :     {
     985             :       
     986             :         #pragma omp for
     987             :         for(Int iy=0; iy<convsize; ++iy) {
     988             :           applyGradientToYLine(iy,  convstor, weightstor, dirX, dirY, convsize, nconvrow, nconvchan, nconvpol, polmap, chanmap, rowmap);
     989             : 
     990             :         }
     991             :     }///End of pragma
     992           0 :     convFunc.putStorage(convstor, delc);
     993           0 :     weightConvFunc.putStorage(weightstor, delw);
     994             :     
     995           0 :   }
     996             : 
     997             : typedef unsigned long long ooLong;
     998             : 
     999           0 : void HetArrayConvFunc::applyGradientToYLine(const Int iy, Complex*& convFunctions, Complex*& convWeights, const Double pixXdir, const Double pixYdir, Int convSize, const Int ndishpair, const Int nChan, const Int nPol) {
    1000             :     Double cy, sy;
    1001             : 
    1002           0 :     SINCOS(Double(iy-convSize/2)*pixYdir, sy, cy);
    1003           0 :     Complex phy(cy,sy) ;
    1004           0 :     for (Int ix=0; ix<convSize; ix++) {
    1005             :         Double cx, sx;
    1006           0 :         SINCOS(Double(ix-convSize/2)*pixXdir, sx, cx);
    1007           0 :         Complex phx(cx,sx) ;
    1008           0 :         for (Int ipol=0; ipol< nPol; ++ipol) {
    1009             :             //Int poloffset=ipol*nChan*ndishpair*convSize*convSize;
    1010           0 :             for (Int ichan=0; ichan < nChan; ++ichan) {
    1011             :                 //Int chanoffset=ichan*ndishpair*convSize*convSize;
    1012           0 :                 for(Int iz=0; iz <ndishpair; ++iz) {
    1013           0 :                     ooLong index=((ooLong(iz*nChan+ichan)*nPol+ipol)*ooLong(convSize)+ooLong(iy))*ooLong(convSize)+ooLong(ix);
    1014           0 :                     convFunctions[index]= convFunctions[index]*phx*phy;
    1015           0 :                     convWeights[index]= convWeights[index]*phx*phy;
    1016             :                 }
    1017             :             }
    1018             :         }
    1019             : 
    1020             :     }
    1021           0 : }
    1022           0 : void HetArrayConvFunc::applyGradientToYLine(const Int iy, Complex*& convFunctions, Complex*& convWeights, const Double pixXdir, const Double pixYdir, Int convSize, const Int ndishpair, const Int nChan, const Int nPol, const vector<Int>& polmap, const vector<Int>& chanmap, const vector<Int>& rowmap ) {
    1023             :     Double cy, sy;
    1024             : 
    1025           0 :     SINCOS(Double(iy-convSize/2)*pixYdir, sy, cy);
    1026           0 :     Complex phy(cy,sy) ;
    1027           0 :     for (Int ix=0; ix<convSize; ix++) {
    1028             :         Double cx, sx;
    1029           0 :         SINCOS(Double(ix-convSize/2)*pixXdir, sx, cx);
    1030           0 :         Complex phx(cx,sx) ;
    1031           0 :         for (uint p=0; p< polmap.size(); ++p) {
    1032             :         //for (uint p=0; p < nPol; ++p) {
    1033           0 :             Int ipol=polmap[p];
    1034             :             //Int ipol=p;
    1035           0 :             for (uint c=0; c < chanmap.size(); ++c) {
    1036             :             //for (uint c=0; c < nChan; ++c) {
    1037           0 :                 Int ichan=chanmap[c];
    1038             :                 //Int ichan=c;
    1039           0 :                 for (uint z=0; z < rowmap.size(); ++z) {
    1040             :                 //for (uint z=0; z < ndishpair; ++z) {
    1041           0 :                     Int iz=rowmap[z];
    1042             :                     //Int iz=z;
    1043           0 :                     ooLong index=((ooLong(iz*nChan+ichan)*nPol+ipol)*ooLong(convSize)+ooLong(iy))*ooLong(convSize)+ooLong(ix);
    1044           0 :                     convFunctions[index]= convFunctions[index]*phx*phy;
    1045           0 :                     convWeights[index]= convWeights[index]*phx*phy;
    1046             :                 }
    1047             :             }
    1048             :         }
    1049             : 
    1050             :     }
    1051           0 : }
    1052             : 
    1053           0 : Int  HetArrayConvFunc::conjSupport(const casacore::Vector<casacore::Double>& freqs){
    1054           0 :   Double centerFreq=SpectralImageUtil::worldFreq(csys_p, 0.0);
    1055           0 :   Double maxRatio=-1.0;
    1056           0 :   for (Int k=0; k < freqs.shape()[0]; ++k) {
    1057             :     //Double conjFreq=(centerFreq-freqs[k])+centerFreq;
    1058           0 :     Double conjFreq=SynthesisUtils::conjFreq(freqs[k], centerFreq);
    1059           0 :     if(maxRatio < conjFreq/freqs[k] )
    1060           0 :       maxRatio=conjFreq/freqs[k];
    1061             :   }
    1062           0 :   return  Int(max(convSupport_p)*sqrt(maxRatio)/2.0)*2;
    1063             : }
    1064           0 : void HetArrayConvFunc::fillConjConvFunc(const Vector<Double>& freqs) {
    1065             :     //cerr << "Actualconv index " << actualConvIndex_p << endl;
    1066           0 :     convFunctionsConjFreq_p.resize(actualConvIndex_p+1);
    1067           0 :     Double centerFreq=SpectralImageUtil::worldFreq(csys_p, 0.0);
    1068           0 :     IPosition shp=convFunctions_p[actualConvIndex_p]->shape();
    1069           0 :     convFunctionsConjFreq_p[actualConvIndex_p]=new Array<Complex>(shp, Complex(0.0));
    1070             :     //cerr << "convsize " << convSize_p << " convsupport " << convSupport_p << endl;
    1071             :     /*
    1072             :     Double maxRatio=-1.0;
    1073             :     for (Int k=0; k < freqs.shape()[0]; ++k) {
    1074             :       Double conjFreq=(centerFreq-freqs[k])+centerFreq;
    1075             :       if(maxRatio < conjFreq/freqs[k] )
    1076             :         maxRatio=conjFreq/freqs[k];
    1077             :     }
    1078             :     */
    1079           0 :     IPosition blc(5,0,0,0,0,0);
    1080           0 :     IPosition trc=shp-1;
    1081             :     /*
    1082             :     IPosition trcOut=trc;
    1083             :     IPosition trcOut(0)= Int(shp(0)*maxRatio/2.0)*2-1;
    1084             :     IPosition trcOut(1)= Int(shp(1)*maxRatio/2.0)*2-1;
    1085             :     */
    1086           0 :     for (Int k=0; k < freqs.shape()[0]; ++k) {
    1087             :       //Double conjFreq=(centerFreq-freqs[k])+centerFreq;
    1088           0 :       Double conjFreq=SynthesisUtils::conjFreq(freqs[k], centerFreq);
    1089           0 :         blc[3]=k;
    1090           0 :         trc[3]=k;
    1091             :         //cerr << "blc " << blc << " trc "<< trc << " ratio " << conjFreq/freqs[k] << endl; 
    1092             :         //Matrix<Complex> convSlice((*convFunctions_p[actualConvIndex_p])(blc, trc).reform(IPosition(2, shp[0], shp[1])));
    1093           0 :         Array<Complex> convSlice((*convFunctions_p[actualConvIndex_p])(blc, trc));
    1094             :         //Array<Complex> weightSlice((*convWeights_p[actualConvIndex_p])(blc,trc));
    1095           0 :         Array<Complex> conjFreqSlice(resample(convSlice, conjFreq/freqs[k]));
    1096           0 :         Double ratio1= Double(Int(Double(convSlice.shape()(0))*conjFreq/freqs[k]/2.0)*2)/Double(convSlice.shape()(0));
    1097           0 :         Double ratio2= Double(Int(Double(convSlice.shape()(1))*conjFreq/freqs[k]/2.0)*2)/Double(convSlice.shape()(1));
    1098             :         //cerr << "resample shape " << conjFreqSlice.shape()  << " ratio " << ratio1*ratio2 << " trc " << trc << endl; 
    1099           0 :         Array<Complex> conjSlice=(*convFunctionsConjFreq_p[actualConvIndex_p])(blc, trc);
    1100           0 :         if(conjFreq > freqs[k]) {
    1101           0 :             IPosition end=shp-1;
    1102           0 :             IPosition beg(5,0,0,0,0,0);
    1103           0 :             beg(0)=(conjFreqSlice.shape()(0)-shp(0))/2;
    1104           0 :             beg(1)=(conjFreqSlice.shape()(1)-shp(1))/2;
    1105           0 :                         end(0)=beg(0)+shp(0)-1;
    1106           0 :                         end(1)=beg(1)+shp(1)-1;
    1107           0 :             end[3]=0;
    1108           0 :             conjSlice=conjFreqSlice(beg, end);
    1109           0 :         }
    1110             :         else {
    1111           0 :             IPosition end=conjFreqSlice.shape()-1;
    1112           0 :             end[3]=0;
    1113           0 :             IPosition beg(5,0,0,0,0,0);
    1114           0 :             beg(0)=(shp(0)-conjFreqSlice.shape()(0))/2;
    1115           0 :             beg(1)=(shp(1)-conjFreqSlice.shape()(1))/2;
    1116           0 :                         end(0)+=beg(0);
    1117           0 :                         end(1)+=beg(1);
    1118           0 :             conjSlice(beg, end)=conjFreqSlice;
    1119           0 :         }
    1120             :         //cerr << "SUMS " << sum(real(convSlice)) << "   new " << sum(real(conjSlice))/ratio1/ratio2 << endl; //" weight " << sum(real(weightSlice))/ratio1/ratio2<< endl;
    1121           0 :         Complex renorm( 1.0/(ratio1*ratio2),0.0);
    1122           0 :         conjSlice=conjSlice*renorm;
    1123             :         //weightSlice=weightSlice*Complex(1.0/(ratio1*ratio2),0.0);
    1124             : 
    1125           0 :     }
    1126             :    
    1127             : 
    1128           0 : }
    1129           0 : Bool HetArrayConvFunc::toRecord(RecordInterface& rec) {
    1130             : 
    1131             :     try {
    1132           0 :         rec.define("name", "HetArrayConvFunc");
    1133           0 :         Int numConv=convFunctions_p.nelements();
    1134           0 :         rec.define("ndefined", numConv);
    1135             :         //rec.define("convfunctionmap", convFunctionMap_p);
    1136           0 :         std::map<String, Int>::iterator it=vbConvIndex_p.begin();
    1137           0 :         for (Int64 k=0; k < numConv; ++k) {
    1138           0 :             rec.define("convfunctions"+String::toString(k), *(convFunctions_p[k]));
    1139           0 :             rec.define("convweights"+String::toString(k), *(convWeights_p[k]));
    1140           0 :             rec.define("convsizes"+String::toString(k), *(convSizes_p[k]));
    1141           0 :             rec.define("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
    1142           0 :             rec.define(String("key")+String::toString(k), it->first);
    1143           0 :             rec.define(String("val")+String::toString(k), it->second);
    1144           0 :             it++;
    1145             :         }
    1146           0 :         rec.define("actualconvindex",  actualConvIndex_p);
    1147           0 :         rec.define("donemainconv", doneMainConv_p);
    1148           0 :         rec.define("vptable", vpTable_p);
    1149           0 :         rec.define("pbclass", Int(pbClass_p));
    1150             : 
    1151             :     }
    1152           0 :     catch(AipsError& x) {
    1153           0 :         return false;
    1154           0 :     }
    1155           0 :     return true;
    1156             : 
    1157             : }
    1158             : 
    1159           0 : Bool HetArrayConvFunc::fromRecord(String& err, const RecordInterface& rec, Bool calcfluxscale) {
    1160             :     //Force pbmath stuff and saved image stuff
    1161           0 :     nchan_p=0;
    1162           0 :     msId_p=-1;
    1163             :     try {
    1164           0 :         if(!rec.isDefined("name") || rec.asString("name") != "HetArrayConvFunc") {
    1165           0 :             throw(AipsError("Wrong record to recover HetArray from"));
    1166             :         }
    1167           0 :         nDefined_p=rec.asInt("ndefined");
    1168             :         //rec.get("convfunctionmap", convFunctionMap_p);
    1169           0 :         convFunctions_p.resize(nDefined_p, true, false);
    1170           0 :         convSupportBlock_p.resize(nDefined_p, true, false);
    1171           0 :         convWeights_p.resize(nDefined_p, true, false);
    1172           0 :         convSizes_p.resize(nDefined_p, true, false);
    1173           0 :         vbConvIndex_p.erase(vbConvIndex_p.begin(), vbConvIndex_p.end());
    1174           0 :         for (Int64 k=0; k < nDefined_p; ++k) {
    1175           0 :             convFunctions_p[k]=new Array<Complex>();
    1176           0 :             convWeights_p[k]=new Array<Complex>();
    1177           0 :             convSizes_p[k]=new Vector<Int>();
    1178           0 :             convSupportBlock_p[k]=new Vector<Int>();
    1179           0 :             rec.get("convfunctions"+String::toString(k), *(convFunctions_p[k]));
    1180           0 :             rec.get("convweights"+String::toString(k), *(convWeights_p[k]));
    1181           0 :             rec.get("convsizes"+String::toString(k), *(convSizes_p[k]));
    1182           0 :             rec.get("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
    1183           0 :             String key;
    1184             :             Int val;
    1185           0 :             rec.get(String("key")+String::toString(k), key);
    1186           0 :             rec.get(String("val")+String::toString(k), val);
    1187           0 :             vbConvIndex_p[key]=val;
    1188           0 :         }
    1189             :         //Now that we are calculating all phase gradients on the fly ..
    1190             :         ///we should clean up some and get rid of the cached variables
    1191             : 
    1192           0 :         convSize_p= nDefined_p > 0 ? (*(convSizes_p[0]))[0] : 0;
    1193             :         //convSave_p.resize();
    1194             :         //rec.get("convsave", convSave_p);
    1195             :         //weightSave_p.resize();
    1196             :         //rec.get("weightsave", weightSave_p);
    1197           0 :         rec.get("vptable", vpTable_p);
    1198           0 :         rec.get("donemainconv", doneMainConv_p);
    1199             :         //convSupport_p.resize();
    1200             :         //rec.get("convsupport", convSupport_p);
    1201           0 :         pbClass_p=static_cast<PBMathInterface::PBClass>(rec.asInt("pbclass"));
    1202           0 :         calcFluxScale_p=calcfluxscale;
    1203             :     }
    1204           0 :     catch(AipsError& x) {
    1205           0 :         err=x.getMesg();
    1206           0 :         return false;
    1207           0 :     }
    1208             : 
    1209           0 :     return true;
    1210             : }
    1211             : 
    1212             : 
    1213           0 : void HetArrayConvFunc::supportAndNormalize(Int plane, Int convSampling) {
    1214             : 
    1215           0 :     LogIO os;
    1216           0 :     os << LogOrigin("HetArrConvFunc", "suppAndNorm")  << LogIO::NORMAL;
    1217             :     // Locate support
    1218           0 :     Int convSupport=-1;
    1219           0 :     IPosition begin(5, 0, 0, 0, 0, plane);
    1220           0 :     IPosition end(5, convFunc_p.shape()[0]-1,  convFunc_p.shape()[1]-1, 0, 0, plane);
    1221           0 :     Matrix<Complex> convPlane(convFunc_p(begin, end).reform(IPosition(2,convFunc_p.shape()[0], convFunc_p.shape()[1]))) ;
    1222           0 :     Float maxAbsConvFunc=max(amplitude(convPlane));
    1223           0 :     Float minAbsConvFunc=min(amplitude(convPlane));
    1224           0 :     Bool found=false;
    1225           0 :     Int trial=0;
    1226           0 :     for (trial=convSize_p/2-2; trial>0; trial--) {
    1227             :         //Searching down a diagonal
    1228           0 :         if(abs(convPlane(convSize_p/2-trial,convSize_p/2-trial)) >  (1.0e-2*maxAbsConvFunc) ) {
    1229           0 :             found=true;
    1230           0 :             trial=Int(sqrt(2.0*Float(trial*trial)));
    1231             :            
    1232           0 :             break;
    1233             :         }
    1234             :     }
    1235           0 :     if(!found) {
    1236           0 :         if((maxAbsConvFunc-minAbsConvFunc) > (1.0e-2*maxAbsConvFunc))
    1237           0 :             found=true;
    1238             :         // if it drops by more than 2 magnitudes per pixel
    1239           0 :         trial=( (10*convSampling) < convSize_p) ? 5*convSampling : (convSize_p/2 - 4*convSampling);
    1240             :     }
    1241             : 
    1242             : 
    1243           0 :     if(found) {
    1244           0 :         if(trial < 5*convSampling)
    1245           0 :             trial= ( (10*convSampling) < convSize_p) ? 5*convSampling : (convSize_p/2 - 4*convSampling);
    1246           0 :         convSupport=Int(0.5+Float(trial)/Float(convSampling))+1;
    1247             :         //support is really over the edge
    1248           0 :         if( (convSupport*convSampling) >= convSize_p/2) {
    1249           0 :             convSupport=convSize_p/2/convSampling-1;
    1250             :         }
    1251             :     }
    1252             :     else {
    1253             :         /*
    1254             :         os << "Convolution function is misbehaved - support seems to be zero\n"
    1255             :            << "Reasons can be: \nThe image definition not covering one or more of the pointings selected \n"
    1256             :            << "Or no unflagged data in a given pointing"
    1257             : 
    1258             :            << LogIO::EXCEPTION;
    1259             :         */
    1260             :         //OTF may have flagged stuff ...
    1261           0 :         convSupport=0;
    1262             :     }
    1263             :     //cerr << "trial " << trial << " convSupport " << convSupport << " convSize " << convSize_p << endl;
    1264           0 :     convSupport_p(plane)=convSupport;
    1265           0 :     Double pbSum=0.0;
    1266             :     /*
    1267             :     Double pbSum1=0.0;
    1268             : 
    1269             :     for (Int iy=-convSupport;iy<=convSupport;iy++) {
    1270             :       for (Int ix=-convSupport;ix<=convSupport;ix++) {
    1271             :         Complex val=convFunc_p.xyPlane(plane)(ix*convSampling+convSize_p/2,
    1272             :                                           iy*convSampling+convSize_p/2);
    1273             : 
    1274             :         pbSum1+=sqrt(real(val)*real(val)+ imag(val)*imag(val));
    1275             :       }
    1276             :     }
    1277             : 
    1278             :     */
    1279           0 :     if(convSupport >0) {
    1280           0 :         IPosition blc(2, -convSupport*convSampling+convSize_p/2, -convSupport*convSampling+convSize_p/2);
    1281           0 :         IPosition trc(2, convSupport*convSampling+convSize_p/2, convSupport*convSampling+convSize_p/2);
    1282           0 :         for (Int chan=0; chan < convFunc_p.shape()[3]; ++chan) {
    1283           0 :             begin[3]=chan;
    1284           0 :             end[3]=chan;
    1285           0 :             convPlane.resize();
    1286           0 :             convPlane.reference(convFunc_p(begin, end).reform(IPosition(2,convFunc_p.shape()[0], convFunc_p.shape()[1])));
    1287           0 :             pbSum=real(sum(convPlane(blc,trc)))/Double(convSampling)/Double(convSampling);
    1288           0 :             if(pbSum>0.0) {
    1289           0 :                 (convPlane)=convPlane*Complex(1.0/pbSum,0.0);
    1290           0 :                 convPlane.resize();
    1291           0 :                 convPlane.reference(weightConvFunc_p(begin, end).reform(IPosition(2,convFunc_p.shape()[0], convFunc_p.shape()[1])));
    1292             :                  
    1293           0 :                 (convPlane) =(convPlane)*Complex(1.0/pbSum,0.0);
    1294             :             }
    1295             :             else {
    1296             :                 os << "Convolution function integral is not positive"
    1297           0 :                    << LogIO::EXCEPTION;
    1298             :             }
    1299             :         }
    1300           0 :     }
    1301             :     else {
    1302             :         //no valid convolution for this pointing
    1303           0 :         for (Int chan=0; chan < convFunc_p.shape()[3]; ++chan) {
    1304           0 :             begin[3]=chan;
    1305           0 :             end[3]=chan;
    1306           0 :             convFunc_p(begin, end).set(Complex(0.0));
    1307           0 :             weightConvFunc_p(begin, end).set(Complex(0.0));
    1308             :             //convFunc_p.xyPlane(plane).set(0.0);
    1309             :             //weightConvFunc_p.xyPlane(plane).set(0.0);
    1310             :         }
    1311             :     }
    1312             : 
    1313           0 : }
    1314             : 
    1315           0 : void HetArrayConvFunc::supportAndNormalizeLatt(Int plane, Int convSampling, TempLattice<Complex>& convFuncLat,
    1316             :         TempLattice<Complex>& weightConvFuncLat) {
    1317             : 
    1318           0 :     LogIO os;
    1319           0 :     os << LogOrigin("HetArrConvFunc", "suppAndNorm")  << LogIO::NORMAL;
    1320             :     // Locate support
    1321           0 :     Int convSupport=-1;
    1322             :     ///Use largest channel as highest freq thus largest conv func
    1323           0 :     IPosition begin(5, 0, 0, 0, convFuncLat.shape()(3)-1, plane);
    1324           0 :     IPosition shape(5, convFuncLat.shape()[0],  convFuncLat.shape()[1], 1, 1, 1);
    1325             :     //Int convSize=convSize_p;
    1326           0 :     Int convSize=shape(0);
    1327             :     ///use FT weightconvlat as it is wider
    1328           0 :     Matrix<Complex> convPlane=weightConvFuncLat.getSlice(begin, shape, true);
    1329             :     Float maxAbsConvFunc, minAbsConvFunc;
    1330           0 :     IPosition minpos, maxpos;
    1331           0 :     minMax(minAbsConvFunc, maxAbsConvFunc, minpos, maxpos, amplitude(convPlane));
    1332           0 :      Bool found=false;
    1333           0 :     Int trial=0;
    1334           0 :     Float cutlevel=2.5e-2;
    1335             :     //numeric needs a larger ft
    1336           0 :     for (uInt k=0; k < antMath_p.nelements() ; ++k){
    1337           0 :       if((antMath_p[k]->whichPBClass()) == PBMathInterface::NUMERIC)
    1338           0 :         cutlevel=5e-3;
    1339             :     }
    1340             : 
    1341           0 :     for (trial=0; trial< (convSize-max(maxpos.asVector())-2); ++trial) {
    1342             :       ///largest along either axis
    1343             :       //cerr << "rat1 " << abs(convPlane(maxpos[0]-trial,maxpos[1]))/maxAbsConvFunc << " rat2 " << abs(convPlane(maxpos[0],maxpos[1]-trial))/maxAbsConvFunc << endl;
    1344           0 :       if((abs(convPlane(maxpos[0]-trial, maxpos[1])) <  (cutlevel*maxAbsConvFunc)) &&(abs(convPlane(maxpos[0],maxpos[1]-trial)) <  (cutlevel*maxAbsConvFunc)) )
    1345             :         {
    1346             : 
    1347           0 :             found=true;
    1348             :             //trial=Int(sqrt(2.0*Float(trial*trial)));
    1349             :             
    1350           0 :             break;
    1351             :         }
    1352             :     }
    1353           0 :     if(!found) {
    1354           0 :       if((maxAbsConvFunc-minAbsConvFunc) > (cutlevel*maxAbsConvFunc))
    1355           0 :             found=true;
    1356             :         // if it drops by more than 2 magnitudes per pixel
    1357             :         //trial=( (10*convSampling) < convSize) ? 5*convSampling : (convSize/2 - 4*convSampling);
    1358           0 :       trial=convSize/2 - 4*convSampling;
    1359             :     }
    1360             : 
    1361           0 :     if(found) {
    1362           0 :         if(trial < 5*convSampling)
    1363           0 :             trial= ( (10*convSampling) < convSize) ? 5*convSampling : (convSize/2 - 4*convSampling);
    1364           0 :         convSupport=(Int(0.5+Float(trial)/Float(convSampling)))+1 ;
    1365             :         //cerr << "convsupp " << convSupport << endl;
    1366             :         //support is really over the edge
    1367           0 :         if( (convSupport*convSampling) >= convSize/2) {
    1368           0 :             convSupport=convSize/2/convSampling-1;
    1369             :         }
    1370             :     }
    1371             :     else {
    1372             :         /*
    1373             :         os << "Convolution function is misbehaved - support seems to be zero\n"
    1374             :            << "Reasons can be: \nThe image definition not covering one or more of the pointings selected \n"
    1375             :            << "Or no unflagged data in a given pointing"
    1376             : 
    1377             :            << LogIO::EXCEPTION;
    1378             :         */
    1379             :         //OTF may have flagged stuff ...
    1380           0 :         convSupport=0;
    1381             :     }
    1382           0 :     convSupport_p(plane)=convSupport;
    1383           0 :     Double pbSum=0.0;
    1384             :     /*
    1385             :     Double pbSum1=0.0;
    1386             : 
    1387             :     for (Int iy=-convSupport;iy<=convSupport;iy++) {
    1388             :       for (Int ix=-convSupport;ix<=convSupport;ix++) {
    1389             :         Complex val=convFunc_p.xyPlane(plane)(ix*convSampling+convSize_p/2,
    1390             :                                           iy*convSampling+convSize_p/2);
    1391             : 
    1392             :         pbSum1+=sqrt(real(val)*real(val)+ imag(val)*imag(val));
    1393             :       }
    1394             :     }
    1395             : 
    1396             :     */
    1397             :     //cerr << "convSize_p " << convSize_p <<  " convSize " << convSize << endl;
    1398           0 :     if(convSupport >0) {
    1399           0 :         IPosition blc(2, -convSupport*convSampling+convSize/2, -convSupport*convSampling+convSize/2);
    1400           0 :         IPosition trc(2, convSupport*convSampling+convSize/2, convSupport*convSampling+convSize/2);
    1401           0 :         for (Int chan=0; chan < convFuncLat.shape()[3]; ++chan) {
    1402           0 :             begin[3]=chan;
    1403             :             //end[3]=chan;
    1404           0 :             convPlane.resize();
    1405           0 :             convPlane=convFuncLat.getSlice(begin, shape, true);
    1406           0 :             pbSum=real(sum(convPlane(blc,trc)))/Double(convSampling)/Double(convSampling);
    1407           0 :             if(pbSum>0.0) {
    1408           0 :                 (convPlane)=convPlane*Complex(1.0/pbSum,0.0);
    1409           0 :                 convFuncLat.putSlice(convPlane, begin);
    1410           0 :                 convPlane.resize();
    1411           0 :                 convPlane=weightConvFuncLat.getSlice(begin, shape, true);
    1412           0 :                 Double pbSum1=0.0;
    1413           0 :                 pbSum1=real(sum(convPlane(blc,trc)))/Double(convSampling)/Double(convSampling);
    1414           0 :                 (convPlane) =(convPlane)*Complex(1.0/pbSum1,0.0);
    1415           0 :                 weightConvFuncLat.putSlice(convPlane, begin);
    1416             :             }
    1417             :             else {
    1418             :                 os << "Convolution function integral is not positive"
    1419           0 :                    << LogIO::EXCEPTION;
    1420             :             }
    1421             :         }
    1422           0 :     }
    1423             :     else {
    1424             :         //no valid convolution for this pointing
    1425           0 :         for (Int chan=0; chan < convFuncLat.shape()[3]; ++chan) {
    1426           0 :             begin[3]=chan;
    1427             :             //end[3]=chan;
    1428           0 :             convPlane.resize(shape[0], shape[1]);
    1429           0 :             convPlane.set(Complex(0.0));
    1430           0 :             convFuncLat.putSlice(convPlane, begin);
    1431           0 :             weightConvFuncLat.putSlice(convPlane, begin);
    1432             :             //convFunc_p.xyPlane(plane).set(0.0);
    1433             :             //weightConvFunc_p.xyPlane(plane).set(0.0);
    1434             :         }
    1435             :     }
    1436             : 
    1437           0 : }
    1438             : 
    1439           0 : Int HetArrayConvFunc::factorial(Int n) {
    1440           0 :     Int fact=1;
    1441           0 :     for (Int k=1; k<=n; ++k)
    1442           0 :         fact *=k;
    1443           0 :     return fact;
    1444             : }
    1445             : 
    1446             : 
    1447           0 : Int HetArrayConvFunc::checkPBOfField(const vi::VisBuffer2& vb,
    1448             :                                      Vector<Int>& /*rowMap*/, const MVDirection& extraShift, const Bool useExtraShift) {
    1449             : 
    1450           0 :   toPix(vb, extraShift, useExtraShift);
    1451           0 :     Vector<Int> pixdepoint(2);
    1452           0 :     convertArray(pixdepoint, thePix_p);
    1453           0 :     if((pixdepoint(0) < 0) ||  pixdepoint(0) >= nx_p || pixdepoint(1) < 0 ||
    1454           0 :             pixdepoint(1) >=ny_p) {
    1455             :         //cout << "in pix de point off " << pixdepoint << endl;
    1456           0 :         return 2;
    1457             :     }
    1458           0 :     String pointingid=String::toString(pixdepoint(0))+"_"+String::toString(pixdepoint(1));
    1459           0 :     String msid=vb.msName(true);
    1460             : 
    1461             :    
    1462           0 :     if(convFunctionMap_p.nelements() == 0) {
    1463           0 :         convFunctionMap_p.resize(nx_p*ny_p);
    1464           0 :         convFunctionMap_p.set(-1);
    1465           0 :         convFunctionMap_p[pixdepoint[1]*nx_p+pixdepoint[0]]=0;
    1466           0 :         nDefined_p=1;
    1467           0 :         actualConvIndex_p=0;
    1468           0 :         return -1;
    1469             :     }
    1470             : 
    1471           0 :     if(convFunctionMap_p[pixdepoint[1]*nx_p+pixdepoint[0]] <0) {
    1472           0 :         actualConvIndex_p=nDefined_p;
    1473           0 :         convFunctionMap_p[pixdepoint[1]*nx_p+pixdepoint[0]]=nDefined_p;
    1474             :         // ++nDefined_p;
    1475           0 :         nDefined_p=1;
    1476           0 :         return -1;
    1477             :     }
    1478             :     else {
    1479           0 :         actualConvIndex_p=0;
    1480           0 :         return -1;
    1481             :     }
    1482             : 
    1483             :     return 1;
    1484             : 
    1485             : 
    1486           0 : }
    1487             : 
    1488           0 : void HetArrayConvFunc::makerowmap(const vi::VisBuffer2& vb,
    1489             :                                   Vector<Int>& rowMap) {
    1490             : 
    1491           0 :     uInt ndish=antMath_p.nelements();
    1492           0 :     rowMap.resize(vb.nRows());
    1493           0 :     for (rownr_t k=0; k < vb.nRows(); ++k) {
    1494           0 :         Int index1=antIndexToDiamIndex_p(vb.antenna1()(k));
    1495           0 :         Int index2=antIndexToDiamIndex_p(vb.antenna2()(k));
    1496           0 :         if(index2 < index1) {
    1497           0 :             index1=index2;
    1498           0 :             index2=antIndexToDiamIndex_p(vb.antenna1()(k));
    1499             :         }
    1500           0 :         Int plane=0;
    1501           0 :         for (Int jj=0; jj < index1; ++jj)
    1502           0 :             plane=plane+ndish-jj-1;
    1503           0 :         plane=plane+index2;
    1504             :         //plane of convfunc that match this pair of antennas
    1505           0 :         rowMap(k)=plane;
    1506             : 
    1507             :     }
    1508             : 
    1509           0 : }
    1510             : 
    1511           0 : Array<Complex> HetArrayConvFunc::resample(const Array<Complex>& inarray, const Double factor) {
    1512             : 
    1513           0 :     Double nx=Double(inarray.shape()(0));
    1514           0 :     Double ny=Double(inarray.shape()(1));
    1515           0 :     IPosition shp=inarray.shape();
    1516           0 :     shp(0)=Int(nx*factor/2.0)*2;
    1517           0 :     shp(1)=Int(ny*factor/2.0)*2;
    1518           0 :     Int newNx=shp(0);
    1519           0 :     Int newNy=shp(1);
    1520             :     
    1521           0 :     Array<Complex> out(shp, Complex(0.0));
    1522             :    // cerr << "SHP " << shp << endl;
    1523             :     
    1524           0 :    IPosition incursor=IPosition(inarray.shape().nelements(),1);
    1525           0 :     incursor[0]=nx;
    1526           0 :     incursor[1]=ny;
    1527           0 :     IPosition outcursor=IPosition(inarray.shape().nelements(),1);
    1528           0 :     outcursor[0]=shp[0];
    1529           0 :     outcursor[1]=shp[1];
    1530           0 :     ArrayIterator<Complex> inIt(inarray, IPosition(2,0,1), True);
    1531           0 :     ArrayIterator<Complex> outIt(out, IPosition(2,0,1),True);
    1532           0 :     inIt.origin();
    1533           0 :     outIt.origin();
    1534             :     //for (zzz=0; zzz< shp.(4); ++zzz){
    1535             :     //  for(yyy=0; yyy< shp.(3); ++yyy){
    1536             :     // for(xxx=0; xxx< shp.(2); ++xxx){
    1537           0 :     while(!inIt.pastEnd()) {
    1538             :        // cerr << "Iter shape " << inIt.array().shape() << endl;
    1539           0 :         Matrix<Complex> inmat;
    1540           0 :         inmat=inIt.array();    
    1541             :         //Matrix<Float> leReal=real(Matrix<Complex>(inIt.array()));
    1542             :         //Matrix<Float> leImag=imag(Matrix<Complex>(inIt.array()));
    1543           0 :         Matrix<Float> leReal=real(inmat);
    1544           0 :         Matrix<Float> leImag=imag(inmat);
    1545             :         Bool leRealCopy, leImagCopy;
    1546           0 :         Float *realptr=leReal.getStorage(leRealCopy);
    1547           0 :         Float *imagptr=leImag.getStorage(leImagCopy);
    1548             :         Bool isCopy;
    1549           0 :         Matrix<Complex> outMat(outIt.array());
    1550           0 :         Complex *intPtr=outMat.getStorage(isCopy);
    1551             :         Float realval, imagval;
    1552             : #ifdef _OPENMP
    1553           0 :         omp_set_nested(0);
    1554             : #endif
    1555           0 :         #pragma omp parallel for default(none) private(realval, imagval) firstprivate(intPtr, realptr, imagptr, nx, ny, newNx, newNy) shared(leReal, leImag)
    1556             : 
    1557             :         for (Int k =0; k < newNy; ++k) {
    1558             :             Double y =Double(k)/Double(newNy)*Double(ny);
    1559             : 
    1560             :             for (Int j=0; j < newNx; ++j) {
    1561             :                 //      Interpolate2D interp(Interpolate2D::LANCZOS);
    1562             :                 Double x=Double(j)/Double(newNx)*Double(nx);
    1563             :                 //interp.interp(realval, where, leReal);
    1564             :                 realval=interpLanczos(x , y, nx, ny,
    1565             :                                       realptr);
    1566             :                 imagval=interpLanczos(x , y, nx, ny,
    1567             :                                       imagptr);
    1568             :                 //interp.interp(imagval, where, leImag);
    1569             :                 intPtr[k*Int(newNx)+j]=Complex(realval, imagval);
    1570             :             }
    1571             : 
    1572             :         }
    1573           0 :         outMat.putStorage(intPtr, isCopy);
    1574           0 :         leReal.putStorage(realptr, leRealCopy);
    1575           0 :         leImag.putStorage(imagptr, leImagCopy);
    1576           0 :         inIt.next();
    1577           0 :         outIt.next();
    1578           0 :     }
    1579           0 :     return out;
    1580           0 : }
    1581           0 : Matrix <Complex> HetArrayConvFunc::resample2(const Matrix<Complex>& inarray, const Double factor) {
    1582             : 
    1583           0 :     Double nx=Double(inarray.shape()(0));
    1584           0 :     Double ny=Double(inarray.shape()(1));
    1585           0 :     IPosition shp=inarray.shape();
    1586           0 :     shp(0)=Int(nx*factor/2.0)*2;
    1587           0 :     shp(1)=Int(ny*factor/2.0)*2;
    1588             : 
    1589             :     
    1590           0 :     Matrix<Complex> outMat(shp, Complex(0.0));
    1591             :     
    1592             :     
    1593             :    
    1594             :      {
    1595             :         //cerr << "Iter shape " << inarray.shape() << endl;
    1596             :         
    1597           0 :         Matrix<Float> leReal=real(inarray);
    1598           0 :         Matrix<Float> leImag=imag(inarray);
    1599             :         Bool leRealCopy, leImagCopy;
    1600           0 :         Float *realptr=leReal.getStorage(leRealCopy);
    1601           0 :         Float *imagptr=leImag.getStorage(leImagCopy);
    1602             :         Bool isCopy;
    1603           0 :         Complex *intPtr=outMat.getStorage(isCopy);
    1604             :         Float realval, imagval;
    1605             : #ifdef _OPENMP
    1606             : //        omp_set_nested(0);
    1607             : #endif
    1608             :  //       #pragma omp parallel for default(none) private(realval, imagval) firstprivate(intPtr, realptr, imagptr, nx, ny) shared(leReal, leImag)
    1609             : 
    1610           0 :         for (Int k =0; k < shp(1); ++k) {
    1611           0 :             Double y =Double(k)/Double(shp(1))*Double(ny);
    1612             : 
    1613           0 :             for (Int j=0; j < Int(nx*factor); ++j) {
    1614             :                 //      Interpolate2D interp(Interpolate2D::LANCZOS);
    1615           0 :                 Double x=Double(j)/Double(factor);
    1616             :                 //interp.interp(realval, where, leReal);
    1617           0 :                 realval=interpLanczos(x , y, nx, ny,
    1618             :                                       realptr);
    1619           0 :                 imagval=interpLanczos(x , y, nx, ny,
    1620             :                                       imagptr);
    1621             :                 //interp.interp(imagval, where, leImag);
    1622           0 :                 intPtr[k*Int(nx*factor)+j]=Complex(realval, imagval);
    1623             :             }
    1624             : 
    1625             :         }
    1626           0 :         outMat.putStorage(intPtr, isCopy);
    1627           0 :         leReal.putStorage(realptr, leRealCopy);
    1628           0 :         leImag.putStorage(imagptr, leImagCopy);
    1629             :         
    1630             :      
    1631           0 :     }
    1632           0 :     return outMat;
    1633           0 : }
    1634           0 : Float HetArrayConvFunc::sinc(const Float x)  {
    1635           0 :     if (x == 0) {
    1636           0 :         return 1;
    1637             :     }
    1638           0 :     return sin(C::pi * x) / (C::pi * x);
    1639             : }
    1640           0 : Float HetArrayConvFunc::interpLanczos( const Double& x , const Double& y, const Double& nx, const Double& ny,   const Float* data, const Float a) {
    1641           0 :     Double floorx = floor(x);
    1642           0 :     Double floory = floor(y);
    1643           0 :     Float result=0.0;
    1644           0 :     if (floorx < a || floorx >= nx - a || floory < a || floory >= ny - a) {
    1645           0 :         result = 0;
    1646           0 :         return result;
    1647             :     }
    1648           0 :     for (Float i = floorx - a + 1; i <= floorx + a; ++i) {
    1649           0 :         for (Float j = floory - a + 1; j <= floory + a; ++j) {
    1650           0 :             result += Float(Double(data[Int(j*nx+i)]) * sinc(x - i)*sinc((x-i)/ a) * sinc(y - j)*sinc((y-j)/ a));
    1651             :         }
    1652             :     }
    1653           0 :     return result;
    1654             : }
    1655             : 
    1656           0 : ImageInterface<Float>&  HetArrayConvFunc::getFluxScaleImage() {
    1657           0 :   if(!calcFluxScale_p)
    1658           0 :     throw(AipsError("Programmer Error: flux image cannot be retrieved"));
    1659           0 :   if(!filledFluxScale_p) {
    1660             :     //The best flux image for a heterogenous array is the weighted coverage
    1661           0 :     fluxScale_p=TempImage<Float>(IPosition(4, nx_p, ny_p, npol_p, nchan_p), csys_p);
    1662           0 :     fluxScale_p.copyData(*(convWeightImage_p));
    1663           0 :     IPosition blc(4,nx_p, ny_p, npol_p, nchan_p);
    1664           0 :     IPosition trc(4, ny_p, ny_p, npol_p, nchan_p);
    1665           0 :     blc(0)=0;
    1666           0 :     blc(1)=0;
    1667           0 :     trc(0)=nx_p-1;
    1668           0 :     trc(1)=ny_p-1;
    1669             : 
    1670           0 :     for (Int j=0; j < npol_p; ++j) {
    1671           0 :       for (Int k=0; k < nchan_p ; ++k) {
    1672             : 
    1673           0 :         blc(2)=j;
    1674           0 :         trc(2)=j;
    1675           0 :         blc(3)=k;
    1676           0 :         trc(3)=k;
    1677           0 :         Slicer sl(blc, trc, Slicer::endIsLast);
    1678           0 :         SubImage<Float> fscalesub(fluxScale_p, sl, true);
    1679             :         Float planeMax;
    1680           0 :         LatticeExprNode LEN = max( fscalesub );
    1681           0 :         planeMax =  LEN.getFloat();
    1682           0 :         if(planeMax !=0) {
    1683           0 :           fscalesub.copyData( (LatticeExpr<Float>) (fscalesub/planeMax));
    1684             : 
    1685             :         }
    1686           0 :       }
    1687             :     }
    1688           0 :     filledFluxScale_p=true;
    1689           0 :   }
    1690             : 
    1691             : 
    1692           0 :   return fluxScale_p;
    1693             : 
    1694             : }
    1695             : 
    1696           0 : void HetArrayConvFunc::sliceFluxScale(Int npol) {
    1697           0 :     IPosition fshp=fluxScale_p.shape();
    1698           0 :     if (fshp(2)>npol) {
    1699           0 :         npol_p=npol;
    1700             :         // use first npol planes...
    1701           0 :         IPosition blc(4,0,0,0,0);
    1702           0 :         IPosition trc(4,fluxScale_p.shape()(0)-1, fluxScale_p.shape()(1)-1,npol-1,fluxScale_p.shape()(3)-1);
    1703           0 :         Slicer sl=Slicer(blc, trc, Slicer::endIsLast);
    1704             :         //writeable if possible
    1705           0 :         SubImage<Float> fluxScaleSub = SubImage<Float> (fluxScale_p, sl, true);
    1706           0 :         SubImage<Float> convWeightImageSub = SubImage<Float> (*convWeightImage_p, sl, true);
    1707           0 :         fluxScale_p = TempImage<Float>(fluxScaleSub.shape(),fluxScaleSub.coordinates());
    1708           0 :         convWeightImage_p = new TempImage<Float> (convWeightImageSub.shape(),convWeightImageSub.coordinates());
    1709           0 :         LatticeExpr<Float> le(fluxScaleSub);
    1710           0 :         fluxScale_p.copyData(le);
    1711           0 :         LatticeExpr<Float> le2(convWeightImageSub);
    1712           0 :         convWeightImage_p->copyData(le2);
    1713           0 :     }
    1714           0 : }
    1715             : } // namespace refim end
    1716             : } //# NAMESPACE CASA - END
    1717             : 
    1718             : 
    1719             : 
    1720             : 

Generated by: LCOV version 1.16