LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - Utils.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 848 0.0 %
Date: 2024-10-29 13:38:20 Functions: 0 68 0.0 %

          Line data    Source code
       1             : // -*- C++ -*-
       2             : //# Utils.cc: Implementation of global functions from Utils.h 
       3             : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
       4             : //# Associated Universities, Inc. Washington DC, USA.
       5             : //#
       6             : //# This library is free software; you can redistribute it and/or modify it
       7             : //# under the terms of the GNU Library General Public License as published by
       8             : //# the Free Software Foundation; either version 2 of the License, or (at your
       9             : //# option) any later version.
      10             : //#
      11             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      12             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      14             : //# License for more details.
      15             : //#
      16             : //# You should have received a copy of the GNU Library General Public License
      17             : //# along with this library; if not, write to the Free Software Foundation,
      18             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      19             : //#
      20             : //# Correspondence concerning AIPS++ should be addressed as follows:
      21             : //#        Internet email: casa-feedback@nrao.edu.
      22             : //#        Postal address: AIPS++ Project Office
      23             : //#                        National Radio Astronomy Observatory
      24             : //#                        520 Edgemont Road
      25             : //#                        Charlottesville, VA 22903-2475 USA
      26             : //#
      27             : //# $Id$
      28             : #include <casacore/ms/MeasurementSets/MSRange.h>
      29             : #include <msvis/MSVis/VisBuffer2.h>
      30             : #include <casacore/casa/Logging/LogIO.h>
      31             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      32             : #include <casacore/measures/Measures/MEpoch.h>
      33             : #include <casacore/measures/Measures/MeasTable.h>
      34             : #include <synthesis/TransformMachines2/Utils.h>
      35             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      36             : #include <synthesis/Utilities/FFT2D.h>
      37             : #include <casacore/casa/Utilities/Assert.h>
      38             : #include <casacore/casa/Arrays/Vector.h>
      39             : #include <casacore/casa/Arrays/ArrayMath.h>
      40             : #include <casacore/lattices/LEL/LatticeExpr.h>
      41             : #include <casacore/images/Images/PagedImage.h>
      42             : #include <casacore/images/Images/ImageRegrid.h>
      43             : #include <casacore/casa/Containers/Record.h>
      44             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      45             : #include <casacore/lattices/Lattices/TiledLineStepper.h> 
      46             : #include <casacore/lattices/Lattices/LatticeStepper.h> 
      47             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      48             : #include <casacore/casa/OS/Timer.h>
      49             : 
      50             : #include <casacore/casa/System/Aipsrc.h>
      51             : #include <msvis/MSVis/VisibilityIterator2.h>
      52             : 
      53             : using namespace casacore;
      54             : namespace casa{
      55             :   using namespace vi;
      56             :   namespace refim{
      57             :   //
      58             :   //--------------------------------------------------------------------------------------------
      59             :   //  
      60           0 :   void storeImg(String fileName,ImageInterface<Complex>& theImg, Bool writeReIm)
      61             :   {
      62           0 :     PagedImage<Complex> ctmp(theImg.shape(), theImg.coordinates(), fileName);
      63           0 :     LatticeExpr<Complex> le(theImg);
      64           0 :     ctmp.copyData(le);
      65           0 :     if (writeReIm)
      66             :       {
      67           0 :         ostringstream reName,imName;
      68           0 :         reName << "re" << fileName;
      69           0 :         imName << "im" << fileName;
      70             :         {
      71           0 :           PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), reName);
      72             :           //LatticeExpr<Float> le(abs(theImg));
      73           0 :           LatticeExpr<Float> le(real(theImg));
      74           0 :           tmp.copyData(le);
      75           0 :         }
      76             :         {
      77           0 :           PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), imName);
      78           0 :           LatticeExpr<Float> le(arg(theImg));
      79           0 :           tmp.copyData(le);
      80           0 :         }
      81           0 :       }
      82           0 :   }
      83             :   
      84           0 :   void storeImg(String fileName,ImageInterface<Float>& theImg)
      85             :   {
      86           0 :     PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), fileName);
      87           0 :     LatticeExpr<Float> le(theImg);
      88           0 :     tmp.copyData(le);
      89           0 :   }
      90             : 
      91           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
      92             :                          const Array<Complex>& theImg)
      93             :   {
      94           0 :     PagedImage<Complex> ctmp(theImg.shape(), coord, fileName);
      95           0 :     ctmp.put(theImg);
      96           0 :   }
      97           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
      98             :                          const Array<DComplex>& theImg)
      99             :   {
     100           0 :     PagedImage<DComplex> ctmp(theImg.shape(), coord, fileName);
     101           0 :     ctmp.put(theImg);
     102           0 :   }
     103           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
     104             :                          const Array<Float>& theImg)
     105             :   {
     106           0 :     PagedImage<Float> ctmp(theImg.shape(), coord, fileName);
     107           0 :     ctmp.put(theImg);
     108           0 :   }
     109             :   //
     110             :   //---------------------------------------------------------------------
     111             :   //
     112             :   // Get the time stamp for the for the current visibility integration.
     113             :   // Since VisTimeAverager() does not accumulate auto-correlations (it
     114             :   // should though!), and the VisBuffer can potentially have
     115             :   // auto-correlation placeholders, vb.time()(0) may not be correct (it
     116             :   // will be in fact zero when AC rows are present).  So look for the
     117             :   // first timestamp of a row corresponding to an unflagged
     118             :   // cross-correlation.
     119             :   //
     120           0 :   Double getCurrentTimeStamp(const VisBuffer2& vb)
     121             :   {
     122             :     //LogIO os(LogOrigin("Utils", "getCurrentTimeStamp", WHERE));
     123             : 
     124           0 :     Int N=vb.nRows();
     125           0 :     for(Int i=0;i<N;i++)
     126             :       {
     127           0 :         if ((!vb.flagRow()(i)) && (vb.antenna1()(i) != vb.antenna2()(i)))
     128           0 :           return vb.time()(i);
     129             :       }
     130             :     //os << "No unflagged row found!  This is a major problem/bug" << LogIO::WARN;
     131           0 :     return 0.0;
     132             :   }
     133             :   //
     134             :   //---------------------------------------------------------------------
     135             :   // Compute the Parallactic Angle for the give VisBuffer
     136             :   //
     137           0 :   void getHADec(MeasurementSet& ms, const VisBuffer2& vb, 
     138             :                 Double& HA, Double& RA, Double& Dec)
     139             :   {
     140           0 :     MEpoch last;
     141           0 :     Double time = getCurrentTimeStamp(vb);
     142             :     
     143           0 :     Unit Second("s"), Day("d");
     144           0 :     MEpoch epoch(Quantity(time,Second),MEpoch::TAI);
     145           0 :     MPosition pos;
     146           0 :     MSObservationColumns msoc(ms.observation());
     147           0 :     String ObsName=msoc.telescopeName()(vb.arrayId()(0));
     148             :     
     149           0 :     if (!MeasTable::Observatory(pos,ObsName))
     150           0 :       throw(AipsError("Observatory position for "+ ObsName + " not found"));
     151             :     
     152           0 :     MeasFrame frame(epoch,pos);
     153           0 :     MEpoch::Convert toLAST = MEpoch::Convert(MEpoch::Ref(MEpoch::TAI,frame),
     154           0 :                                              MEpoch::Ref(MEpoch::LAST,frame));
     155           0 :     RA=vb.direction1()(0).getAngle().getValue()(0);    
     156           0 :     if (RA < 0.0) RA += M_PI*2.0;
     157           0 :     Dec=vb.direction1()(0).getAngle().getValue()(1);    
     158             : 
     159           0 :     last = toLAST(epoch);
     160           0 :     Double LST   = last.get(Day).getValue();
     161           0 :     LST -= floor(LST); // Extract the fractional day
     162           0 :     LST *= 2*C::pi;// Convert to Raidan
     163             : 
     164           0 :     cout << "LST = " << LST << " " << LST/(2*C::pi) << endl;
     165             :     
     166           0 :     HA = LST - RA;
     167           0 :   }
     168             :   //
     169             :   //---------------------------------------------------------------------
     170             :   // Compute the Parallactic Angle for the give VisBuffer
     171             :   //
     172           0 :   Double getPA(const vi::VisBuffer2& vb)
     173             :   {
     174           0 :     return (Double)(vb.feedPa(getCurrentTimeStamp(vb))(0));
     175             :     // Double pa=0;
     176             :     // Int n=0;
     177             :     // Vector<Float> antPA = vb.feed_pa(getCurrentTimeStamp(vb));
     178             :     // for (uInt i=0;i<antPA.nelements();i++)
     179             :     //   {
     180             :     //  if (!vb.msColumns().antenna().flagRow()(i))
     181             :     //    {pa += antPA(i); n++;break;}
     182             :     //   }
     183             :     // //    pa = sum(antPA)/(antPA.nelements()-1);
     184             :     // if (n==0) 
     185             :     //   throw(AipsError("No unflagged antenna found in getPA()."));
     186             :     // return pa/n;
     187             :   }
     188             :   //
     189             :   //---------------------------------------------------------------------
     190             :   //
     191             :   // Make stokes axis, given the polarization types.
     192             :   //
     193           0 :   void makeStokesAxis(Int npol_p, Vector<String>& polType, Vector<Int>& whichStokes)
     194             :   {
     195             :     //    Vector<String> polType=msc.feed().polarizationType()(0);
     196             :     StokesImageUtil::PolRep polRep_p;
     197           0 :     LogIO os(LogOrigin("Utils", "makeStokesAxis", WHERE));
     198             : 
     199           0 :     if (polType(0)!="X" && polType(0)!="Y" &&
     200           0 :         polType(0)!="R" && polType(0)!="L") 
     201             :       {
     202             :         os << "Warning: Unknown stokes types in feed table: ["
     203           0 :            << polType(0) << ", " << polType(1) << "]" << endl
     204           0 :            << "Results open to question!" << LogIO::POST;
     205             :       }
     206             :   
     207           0 :     if (polType(0)=="X" || polType(0)=="Y") 
     208             :       {
     209           0 :         polRep_p=StokesImageUtil::LINEAR;
     210           0 :         os << "Preferred polarization representation is linear" << LogIO::POST;
     211             :       }
     212             :     else 
     213             :       {
     214           0 :         polRep_p=StokesImageUtil::CIRCULAR;
     215           0 :         os << "Preferred polarization representation is circular" << LogIO::POST;
     216             :       }
     217             : 
     218             :     //    Vector<Int> whichStokes(npol_p);
     219           0 :     switch(npol_p) 
     220             :       {
     221           0 :       case 1:
     222           0 :         whichStokes.resize(1);
     223           0 :         whichStokes(0)=Stokes::I;
     224           0 :         os <<  "Image polarization = Stokes I" << LogIO::POST;
     225           0 :         break;
     226           0 :       case 2:
     227           0 :         whichStokes.resize(2);
     228           0 :         whichStokes(0)=Stokes::I;
     229           0 :         if (polRep_p==StokesImageUtil::LINEAR) 
     230             :           {
     231           0 :             whichStokes(1)=Stokes::Q;
     232           0 :             os <<  "Image polarization = Stokes I,Q" << LogIO::POST;
     233             :           }
     234             :       else 
     235             :         {
     236           0 :           whichStokes(1)=Stokes::V;
     237           0 :           os <<  "Image polarization = Stokes I,V" << LogIO::POST;
     238             :         }
     239           0 :         break;
     240           0 :       case 3:
     241           0 :         whichStokes.resize(3);
     242           0 :         whichStokes(0)=Stokes::I;
     243           0 :         whichStokes(1)=Stokes::Q;
     244           0 :         whichStokes(1)=Stokes::U;
     245           0 :         os <<  "Image polarization = Stokes I,Q,U" << LogIO::POST;
     246           0 :         break;
     247           0 :       case 4:
     248           0 :         whichStokes.resize(4);
     249           0 :         whichStokes(0)=Stokes::I;
     250           0 :         whichStokes(1)=Stokes::Q;
     251           0 :         whichStokes(2)=Stokes::U;
     252           0 :         whichStokes(3)=Stokes::V;
     253           0 :         os <<  "Image polarization = Stokes I,Q,U,V" << LogIO::POST;
     254           0 :         break;
     255           0 :       default:
     256             :         os << LogIO::SEVERE << "Illegal number of Stokes parameters: " << npol_p
     257           0 :            << LogIO::POST;
     258             :       };
     259           0 :   }
     260             :   //
     261             :   //--------------------------------------------------------------------------------------------
     262             :   //  
     263           0 :   Bool isVBNaN(const VisBuffer2 &vb,String& mesg)
     264             :   {
     265           0 :     IPosition ndx(3,0);
     266           0 :     Int N = vb.nRows();
     267           0 :     for(ndx(2)=0;ndx(2)<N;ndx(2)++)
     268           0 :       if (std::isnan(vb.visCubeModel()(ndx).real()) ||
     269           0 :           std::isnan(vb.visCubeModel()(ndx).imag())
     270             :           )
     271             :         {
     272           0 :           ostringstream os;
     273           0 :           os << ndx(2) << " " << vb.antenna1()(ndx(2)) << "-" << vb.antenna2()(ndx(2)) << " "
     274           0 :              << vb.flagCube()(ndx) << " " 
     275             :             //<< vb.flag()(0,ndx(2)) << " " 
     276           0 :              << vb.weight();
     277           0 :           mesg = os.str().c_str();
     278           0 :           return true;
     279           0 :         }
     280           0 :     return false;
     281           0 :   }
     282             :   //
     283             :   //--------------------------------------------------------------------------------------------
     284             :   //  
     285             :   /////////////////////////////////////////////////////////////////////////////
     286             :   //
     287             :   // IChangeDetector  - an interface class to detect changes in the VisBuffer
     288             :   //     Exact meaning of the "change" is defined in the derived classes
     289             :   //     (e.g. a change in the parallactic angle)
     290             :   
     291             :   // return true if a change occurs somewhere in the buffer
     292             :   using namespace vi;
     293           0 :   Bool IChangeDetector::changed(const VisBuffer2 &vb) const
     294             :   {
     295           0 :      for (rownr_t i=0;i<vb.nRows();++i)
     296           0 :           if (changed(vb,i)) return true;
     297           0 :      return false;
     298             :   }
     299             : 
     300             :   // return true if a change occurs somewhere in the buffer starting from row1
     301             :   // up to row2 (row2=-1 means up to the end of the buffer). The row number,
     302             :   // where the change occurs is returned in the row2 parameter
     303           0 :   Bool IChangeDetector::changedBuffer(const VisBuffer2 &vb, Int row1, 
     304             :                    Int &row2) const
     305             :   {
     306           0 :     if (row1<0) row1=0;
     307           0 :     int jrow = row2;
     308           0 :     if (jrow < 0) jrow = vb.nRows()-1;
     309           0 :     DebugAssert(jrow<(int)vb.nRows(),AipsError);
     310             :     
     311             :     // It is not important now to have a separate function for a "block"
     312             :     // operation. Because an appropriate caching is implemented inside
     313             :     // VisBuffer, changed(vb,row) can be called in the
     314             :     // loop without a perfomance penalty. This method returns the 
     315             :     // first row where the change occured rather than the last unchanged 
     316             :     // row as it was for BeamSkyJones::changedBuffer
     317             :       
     318           0 :     for (int ii=row1;ii<=jrow;++ii)
     319           0 :          if (changed(vb,ii)) {
     320           0 :              row2 = ii;
     321           0 :              return true;
     322             :          }
     323           0 :     return false;
     324             :   }
     325             :   
     326             :   // a virtual destructor to make the compiler happy
     327           0 :   IChangeDetector::~IChangeDetector() {}
     328             :   
     329             :   //
     330             :   /////////////////////////////////////////////////////////////////////////////
     331             : 
     332             :   /////////////////////////////////////////////////////////////////////////////
     333             :   //
     334             :   // ParAngleChangeDetector - a class to detect a change in the parallatic 
     335             :   //                          angle
     336             :   //
     337             :   
     338             :   // set up the tolerance, which determines how much the position angle should
     339             :   // change to report the change by this class
     340           0 :   ParAngleChangeDetector::ParAngleChangeDetector(const Quantity &pa_tolerance) 
     341           0 :                : pa_tolerance_p(pa_tolerance.getValue("rad")),
     342           0 :                     last_pa_p(1000.) {}  // 1000 is >> 2pi, so it is changed
     343             :                                          // after construction
     344             :   
     345             :   // Set the value of the PA tolerance
     346           0 :   void ParAngleChangeDetector::setTolerance(const Quantity &pa_tolerance)
     347             :   {
     348           0 :     pa_tolerance_p = (pa_tolerance.getValue("rad"));
     349           0 :   }
     350             :   // reset to the state which exist just after construction
     351           0 :   void ParAngleChangeDetector::reset()
     352             :   {
     353           0 :       last_pa_p=1000.; // it is >> 2pi, which would force a changed state
     354           0 :   }
     355             :      
     356             :   // return parallactic angle tolerance
     357           0 :   Quantity ParAngleChangeDetector::getParAngleTolerance() const
     358             :   {
     359           0 :       return Quantity(pa_tolerance_p,"rad");
     360             :   }
     361             :   
     362             :   // return true if a change occurs in the given row since the last call 
     363             :   // of update
     364           0 :   Bool ParAngleChangeDetector::changed(const VisBuffer2 &vb, Int row) const
     365             :   {
     366           0 :      if (row<0) row=0;
     367             :      //     const Double feed1_pa=vb.feed1_pa()[row];
     368           0 :      Double feed1_pa=getPA(vb);
     369           0 :      if (abs(feed1_pa-last_pa_p) > pa_tolerance_p) 
     370             :        {
     371             : //       cout << "Utils: " << feed1_pa*57.295 << " " << last_pa_p*57.295 << " " << abs(feed1_pa-last_pa_p)*57.295 << " " << ttt*57.295 << " " << vb.time()(0)-4.51738e+09 << endl;
     372           0 :          return true;
     373             :        }
     374             :      //     const Double feed2_pa=vb.feed2_pa()[row];
     375           0 :      Double feed2_pa = getPA(vb);
     376           0 :      if (abs(feed2_pa-last_pa_p) > pa_tolerance_p) 
     377             :        {
     378             : //       cout << "Utils: " << feed2_pa*57.295 << " " 
     379             : //            << last_pa_p*57.295 << " " 
     380             : //            << abs(feed2_pa-last_pa_p)*57.295 << " " << ttt*57.295 << vb.time()(0)-4.51738e+09 <<endl;
     381           0 :          return true;
     382             :        }
     383           0 :      return false;
     384             :   }
     385             :   
     386             :   // start looking for a change from the given row of the VisBuffer
     387           0 :   void ParAngleChangeDetector::update(const VisBuffer2 &vb, Int row) 
     388             :   {
     389           0 :      if (row<0) row=0;
     390           0 :      const Double feed1_pa=vb.feedPa1()[row];
     391           0 :      const Double feed2_pa=vb.feedPa2()[row];
     392           0 :      if (abs(feed1_pa-feed2_pa)>pa_tolerance_p) {
     393           0 :          LogIO os;
     394           0 :          os<<LogIO::WARN << LogOrigin("ParAngleChangeDetector","update") 
     395             :            <<"The parallactic angle is different at different stations"
     396           0 :            <<LogIO::POST<<LogIO::WARN <<LogOrigin("ParAngleChangeDetector","update")
     397           0 :            <<"The result may be incorrect. Continuing anyway."<<LogIO::POST;
     398           0 :      }
     399           0 :      last_pa_p=(feed1_pa+feed2_pa)/2.;
     400           0 :   }
     401             : 
     402           0 :   Int getPhaseCenter(MeasurementSet& ms, MDirection& dir0, Int whichField)
     403             :   {
     404           0 :     MSFieldColumns msfc(ms.field());
     405           0 :     if (whichField < 0)
     406             :       {
     407           0 :         MSRange msr(ms);
     408             :         //
     409             :         // An array of shape [2,1,1]!
     410             :         //
     411           0 :         Vector<Int> fieldId;
     412           0 :         fieldId = msr.range(MSS::FIELD_ID).asArrayInt(RecordFieldId(0));
     413             :         
     414           0 :         Array<Double> phaseDir = msfc.phaseDir().getColumn();
     415             :         
     416           0 :         if (fieldId.nelements() <= 0)
     417           0 :           throw(AipsError("getPhaseCenter: No fields found in the selected MS."));
     418             :         
     419           0 :         IPosition ndx0(3,0,0,0),ndx1(3,1,0,0);
     420             :         
     421             :         Double maxRA, maxDec, RA,Dec,RA0,Dec0, dist0;
     422           0 :         maxRA = maxDec=0;
     423           0 :         for(uInt i=0;i<fieldId.nelements();i++)
     424             :           {
     425           0 :             RA   = phaseDir(IPosition(3,0,0,fieldId(i)));
     426           0 :             Dec  = phaseDir(IPosition(3,1,0,fieldId(i)));
     427           0 :             maxRA += RA; maxDec += Dec;
     428             :           }
     429           0 :         RA0=maxRA/fieldId.nelements(); Dec0=maxDec/fieldId.nelements();
     430             :         
     431           0 :         dist0=10000;
     432           0 :         Int field0=0;
     433           0 :         for(uInt i=0;i<fieldId.nelements();i++)
     434             :           {
     435           0 :             RA   = RA0-phaseDir(IPosition(3,0,0,fieldId(i)));
     436           0 :             Dec  = Dec0-phaseDir(IPosition(3,1,0,fieldId(i)));
     437           0 :             Double dist=sqrt(RA*RA + Dec*Dec);
     438           0 :             if (dist < dist0) {field0=fieldId(i);dist0=dist;};
     439             :           }
     440           0 :         dir0=msfc.phaseDirMeasCol()(field0)(IPosition(1,0));
     441             :         //dir0=msfc.phaseDirMeasCol()(6)(IPosition(1,0));
     442           0 :         return field0;
     443           0 :       }
     444             :     else
     445             :       {
     446           0 :         dir0=msfc.phaseDirMeasCol()(whichField)(IPosition(1,0));
     447           0 :         return whichField;
     448             :       }
     449           0 :   }
     450             :   //
     451             :   //------------------------------------------------------------------
     452             :   //
     453           0 :   Bool findMaxAbsLattice(const ImageInterface<Float>& lattice,
     454             :                          Float& maxAbs,IPosition& posMaxAbs) 
     455             :   {
     456           0 :     posMaxAbs = IPosition(lattice.shape().nelements(), 0);
     457           0 :     maxAbs=0.0;
     458             : 
     459           0 :     const IPosition tileShape = lattice.niceCursorShape();
     460           0 :     TiledLineStepper ls(lattice.shape(), tileShape, 0);
     461             :     {
     462           0 :       RO_LatticeIterator<Float> li(lattice, ls);
     463           0 :       for(li.reset();!li.atEnd();li++)
     464             :         {
     465           0 :           IPosition posMax=li.position();
     466           0 :           IPosition posMin=li.position();
     467           0 :           Float maxVal=0.0;
     468           0 :           Float minVal=0.0;
     469             :           
     470           0 :           minMax(minVal, maxVal, posMin, posMax, li.cursor());
     471           0 :           if((maxVal)>(maxAbs)) 
     472             :             {
     473           0 :               maxAbs=maxVal;
     474           0 :               posMaxAbs=li.position();
     475           0 :               posMaxAbs(0)=posMax(0);
     476             :             }
     477           0 :         }
     478           0 :     }
     479             : 
     480           0 :     return true;
     481           0 :   };
     482             :   //
     483             :   //------------------------------------------------------------------
     484             :   //
     485           0 :   Bool findMaxAbsLattice(const ImageInterface<Float>& masklat,
     486             :                          const Lattice<Float>& lattice,
     487             :                          Float& maxAbs,IPosition& posMaxAbs, 
     488             :                          Bool flip)
     489             :   {
     490             :     
     491           0 :     AlwaysAssert(masklat.shape()==lattice.shape(), AipsError);
     492             : 
     493           0 :     Array<Float> msk;
     494             :   
     495           0 :     posMaxAbs = IPosition(lattice.shape().nelements(), 0);
     496           0 :     maxAbs=0.0;
     497             :     //maxAbs=-1.0e+10;
     498           0 :     const IPosition tileShape = lattice.niceCursorShape();
     499           0 :     TiledLineStepper ls(lattice.shape(), tileShape, 0);
     500           0 :     TiledLineStepper lsm(masklat.shape(), tileShape, 0);
     501             :     {
     502           0 :       RO_LatticeIterator<Float> li(lattice, ls);
     503           0 :       RO_LatticeIterator<Float> lim(masklat, lsm);
     504           0 :       for(li.reset(),lim.reset();!li.atEnd();li++,lim++) 
     505             :         {
     506           0 :           IPosition posMax=li.position();
     507           0 :           IPosition posMin=li.position();
     508           0 :           Float maxVal=0.0;
     509           0 :           Float minVal=0.0;
     510             :           
     511           0 :           msk = lim.cursor();
     512           0 :           if(flip) msk = (Float)1.0 - msk;
     513             :           
     514             :           //minMaxMasked(minVal, maxVal, posMin, posMax, li.cursor(),lim.cursor());
     515           0 :           minMaxMasked(minVal, maxVal, posMin, posMax, li.cursor(),msk);
     516             :           
     517             :           
     518           0 :           if((maxVal)>(maxAbs)) 
     519             :             {
     520           0 :               maxAbs=maxVal;
     521           0 :               posMaxAbs=li.position();
     522           0 :               posMaxAbs(0)=posMax(0);
     523             :             }
     524           0 :         }
     525           0 :     }
     526             : 
     527           0 :     return true;
     528           0 :   }
     529             :   //
     530             :   
     531             :  
     532             :   //---------------------------------------------------------------
     533             :   //Rotate a complex array using a the given coordinate system and the
     534             :   //angle in radians.  Default interpolation method is "CUBIC".
     535             :   //Axeses corresponding to Linear coordinates in the given
     536             :   //CoordinateSystem object are rotated.  Rotation is done using
     537             :   //ImageRegrid object, about the pixel given by (N+1)/2 where N is
     538             :   //the number of pixels along the axis.
     539             :   //
     540           0 :   void SynthesisUtils::rotateComplexArray(LogIO& logio, Array<Complex>& inArray, 
     541             :                                           CoordinateSystem& inCS,
     542             :                                           Array<Complex>& outArray,
     543             :                                           Double dAngleRad,
     544             :                                           String interpMethod,
     545             :                                           Bool modifyInCS)
     546             :   {
     547             : //     logio << LogOrigin("SynthesisUtils", "rotateComplexArray")
     548             : //        << "Rotating CF using " << interpMethod << " interpolation." 
     549             : //        << LogIO::POST;
     550             :     (void)logio;
     551             :     //
     552             :     // If no rotation required, just copy the inArray to outArray.
     553             :     //
     554             :     //    if (abs(dAngleRad) < 0.1)
     555             :     
     556             :     // IPosition tt;
     557             :     // inCS.list(logio,MDoppler::RADIO,tt,tt);
     558             : 
     559           0 :     if (abs(dAngleRad) == 0.0)
     560             :       {
     561           0 :         outArray.reference(inArray);
     562             :         //      outArray.assign(inArray);
     563           0 :         return;
     564             :       }
     565             :     //
     566             :     // Re-grid inImage onto outImage
     567             :     //
     568           0 :     Vector<Int> pixelAxes;
     569           0 :     Int coordInd = -1;
     570             :     // Extract LINRAR coords from inCS.
     571             :     // Extract axes2
     572             : 
     573           0 :     if(modifyInCS){
     574           0 :       Vector<Double> refPix = inCS.referencePixel();
     575           0 :       refPix(0) = (Int)((inArray.shape()(0))/2.0);
     576           0 :       refPix(1) = (Int)((inArray.shape()(1))/2.0);
     577           0 :       inCS.setReferencePixel(refPix);
     578           0 :     }
     579             : 
     580           0 :     coordInd = inCS.findCoordinate(Coordinate::LINEAR);
     581           0 :     Bool haveLinear = true;
     582             : 
     583           0 :     if(coordInd == -1){ // no linear coordinate found, look for DIRECTION instead
     584           0 :       coordInd = inCS.findCoordinate(Coordinate::DIRECTION);
     585           0 :       haveLinear = false;
     586             :     }
     587             : 
     588           0 :     pixelAxes=inCS.pixelAxes(coordInd);
     589           0 :     IPosition axes2(pixelAxes);
     590             :     // Set linear transformation matrix in inCS.
     591             : //     CoordinateSystem outCS =
     592             : //       ImageRegrid<Complex>::makeCoordinateSystem (logio, outCS, inCS, axes2);
     593             : 
     594           0 :     CoordinateSystem outCS(inCS);
     595             : 
     596           0 :     Matrix<Double> xf = outCS.coordinate(coordInd).linearTransform();
     597           0 :     Matrix<Double> rotm(2,2);
     598           0 :     rotm(0,0) = cos(dAngleRad); rotm(0,1) = sin(dAngleRad);
     599           0 :     rotm(1,0) = -rotm(0,1);     rotm(1,1) = rotm(0,0);
     600             : 
     601             :     // Double s = sin(dAngleRad);
     602             :     // Double c = cos(dAngleRad);
     603             :     // rotm(0,0) =  c; rotm(0,1) = s;
     604             :     // rotm(1,0) = -s; rotm(1,1) = c;
     605             : 
     606             :     // Create new linear transform matrix
     607           0 :     Matrix<Double> xform(2,2);
     608           0 :     xform(0,0) = rotm(0,0)*xf(0,0)+rotm(0,1)*xf(1,0);
     609           0 :     xform(0,1) = rotm(0,0)*xf(0,1)+rotm(0,1)*xf(1,1);
     610           0 :     xform(1,0) = rotm(1,0)*xf(0,0)+rotm(1,1)*xf(1,0);
     611           0 :     xform(1,1) = rotm(1,0)*xf(0,1)+rotm(1,1)*xf(1,1);
     612             : 
     613           0 :     if(haveLinear){
     614           0 :       LinearCoordinate linCoords = outCS.linearCoordinate(coordInd);
     615           0 :       linCoords.setLinearTransform(xform);
     616           0 :       outCS.replaceCoordinate(linCoords, coordInd);
     617           0 :     }
     618             :     else{
     619           0 :       DirectionCoordinate dirCoords = outCS.directionCoordinate(coordInd);
     620           0 :       dirCoords.setLinearTransform(xform);
     621           0 :       outCS.replaceCoordinate(dirCoords, coordInd);
     622           0 :     }      
     623             :     
     624           0 :     outArray.resize(inArray.shape());
     625           0 :     outArray.set(0);
     626             :     //
     627             :     // Make an image out of inArray and inCS --> inImage
     628             :     //
     629             :     //    TempImage<Complex> inImage(inArray.shape(), inCS);
     630             :     {
     631           0 :       TempImage<Float> inImage(inArray.shape(),inCS);
     632           0 :       TempImage<Float> outImage(outArray.shape(), outCS);
     633           0 :       ImageRegrid<Float> ir;
     634           0 :       Interpolate2D::Method interpolationMethod = Interpolate2D::stringToMethod(interpMethod);
     635             :       //------------------------------------------------------------------------
     636             :       // Rotated the real part
     637             :       //
     638           0 :       inImage.copyData(LatticeExpr<Float>(real(ArrayLattice<Complex>(inArray))));
     639           0 :       outImage.set(0.0);
     640             : 
     641           0 :       ir.regrid(outImage, interpolationMethod, axes2, inImage);
     642           0 :       setReal(outArray,outImage.get());
     643             :       //------------------------------------------------------------------------
     644             :       // Rotated the imaginary part
     645             :       //
     646           0 :       inImage.copyData(LatticeExpr<Float>(imag(ArrayLattice<Complex>(inArray))));
     647           0 :       outImage.set(0.0);
     648             : 
     649           0 :       ir.regrid(outImage, interpolationMethod, axes2, inImage);
     650           0 :       setImag(outArray,outImage.get());
     651           0 :     }
     652           0 :   }
     653             :   //
     654             :   //---------------------------------------------------------------
     655             :   //
     656           0 :   void SynthesisUtils::findLatticeMax(const ImageInterface<Complex>& lattice,
     657             :                                       Vector<Float>& maxAbs,
     658             :                                       Vector<IPosition>& posMaxAbs) 
     659             :   {
     660           0 :     IPosition lshape(lattice.shape());
     661           0 :     IPosition ndx(lshape);
     662           0 :     Int nPol=lshape(2);
     663           0 :     posMaxAbs.resize(nPol);
     664           0 :     for(Int i=0;i<nPol;i++)
     665           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     666           0 :     maxAbs.resize(nPol);
     667           0 :     ndx=0;
     668             :     
     669           0 :     for(Int s2=0;s2<lshape(2);s2++)
     670           0 :       for(Int s3=0;s3<lshape(3);s3++)
     671             :         {
     672           0 :           ndx(2) = s2; ndx(3)=s3;
     673             :           {
     674             :             //
     675             :             // Locate the pixel with the peak value.  That's the
     676             :             // origin in pixel co-ordinates.
     677             :             //
     678           0 :             maxAbs(s2)=0;
     679           0 :             posMaxAbs(s2) = 0;
     680           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     681           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     682           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     683           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     684             :           }
     685             :         }
     686           0 :   }
     687             :   //
     688             :   //---------------------------------------------------------------
     689             :   //
     690           0 :   void SynthesisUtils::findLatticeMax(const Array<Complex>& lattice,
     691             :                                       Vector<Float>& maxAbs,
     692             :                                       Vector<IPosition>& posMaxAbs) 
     693             :   {
     694           0 :     IPosition lshape(lattice.shape());
     695           0 :     IPosition ndx(lshape);
     696           0 :     Int nPol=lshape(2);
     697           0 :     posMaxAbs.resize(nPol);
     698           0 :     for(Int i=0;i<nPol;i++)
     699           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     700           0 :     maxAbs.resize(nPol);
     701           0 :     ndx=0;
     702             :     
     703           0 :     for(Int s2=0;s2<lshape(2);s2++)
     704           0 :       for(Int s3=0;s3<lshape(3);s3++)
     705             :         {
     706           0 :           ndx(2) = s2; ndx(3)=s3;
     707             :           {
     708             :             //
     709             :             // Locate the pixel with the peak value.  That's the
     710             :             // origin in pixel co-ordinates.
     711             :             //
     712           0 :             maxAbs(s2)=0;
     713           0 :             posMaxAbs(s2) = 0;
     714           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     715           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     716           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     717           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     718             :           }
     719             :         }
     720           0 :   }
     721             :   //
     722             :   //---------------------------------------------------------------
     723             :   //
     724           0 :   void SynthesisUtils::findLatticeMax(const ImageInterface<Float>& lattice,
     725             :                                       Vector<Float>& maxAbs,
     726             :                                       Vector<IPosition>& posMaxAbs) 
     727             :   {
     728           0 :     IPosition lshape(lattice.shape());
     729           0 :     IPosition ndx(lshape);
     730           0 :     Int nPol=lshape(2);
     731           0 :     posMaxAbs.resize(nPol);
     732           0 :     for(Int i=0;i<nPol;i++)
     733           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     734           0 :     maxAbs.resize(nPol);
     735           0 :     ndx=0;
     736             :     
     737           0 :     for(Int s2=0;s2<lshape(2);s2++)
     738           0 :       for(Int s3=0;s3<lshape(3);s3++)
     739             :         {
     740           0 :           ndx(2) = s2; ndx(3)=s3;
     741             :           {
     742             :             //
     743             :             // Locate the pixel with the peak value.  That's the
     744             :             // origin in pixel co-ordinates.
     745             :             //
     746           0 :             maxAbs(s2)=0;
     747           0 :             posMaxAbs(s2) = 0;
     748           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     749           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     750           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     751           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     752             :           }
     753             :         }
     754           0 :   }
     755             :   //
     756             :   //---------------------------------------------------------------
     757             :   // Get the value of the named variable from ~/.aipsrc (or ~/.casarc)
     758             :   // or from a env. variable (in this precidence order).
     759             :   //
     760             :   template <class T>
     761           0 :     T SynthesisUtils::getenv(const char *name, const T defaultVal)
     762             :     {
     763           0 :       T val=defaultVal;
     764           0 :       stringstream defaultStr;
     765           0 :       defaultStr << defaultVal;
     766             :       {
     767           0 :         char *valStr=NULL;
     768           0 :         std::string tt(name);
     769             :         unsigned long pos;
     770           0 :         while((pos=tt.find(".")) != tt.npos)
     771           0 :           tt.replace(pos, 1, "_");
     772             : 
     773           0 :         if ((valStr = std::getenv(tt.c_str())) != NULL)
     774             :           {
     775           0 :             stringstream toT2(valStr);
     776           0 :             toT2 >> val;
     777           0 :           }
     778           0 :       }
     779             :       // If environment variable was not found (val remained set to the
     780             :       // defaulVal), look in ~/.aipsrc.
     781           0 :       if (val==defaultVal)
     782             :         {
     783           0 :           uint handle = Aipsrc::registerRC(name, defaultStr.str().c_str());    
     784           0 :           String strVal = Aipsrc::get(handle);
     785           0 :           stringstream toT(strVal);
     786           0 :           toT >> val;
     787           0 :         }
     788           0 :       return val;
     789           0 :     }
     790             :     template 
     791             :     Int SynthesisUtils::getenv(const char *name, const Int defaultVal);
     792             :     template 
     793             :     Bool SynthesisUtils::getenv(const char *name, const Bool defaultVal);
     794             :     template 
     795             :     Float SynthesisUtils::getenv(const char *name, const Float defaultVal);
     796             :     template 
     797             :     double SynthesisUtils::getenv(const char *name, const double defaultVal);
     798             :   template 
     799             :     String SynthesisUtils::getenv(const char *name, const String defaultVal);
     800             : 
     801           0 :   Float SynthesisUtils::libreSpheroidal(Float nu) 
     802             :   {
     803             :     Double top, bot, nuend, delnusq;
     804             :     uInt part;
     805           0 :     if (nu <= 0) return 1.0;
     806             :     else 
     807           0 :       if (nu >= 1.0) 
     808           0 :         return 0.0;
     809             :       else 
     810             :         {
     811           0 :           uInt np = 5;
     812           0 :           uInt nq = 3;
     813           0 :           Matrix<Double> p(np, 2);
     814           0 :           Matrix<Double> q(nq, 2);
     815           0 :           p(0,0) = 8.203343e-2;
     816           0 :           p(1,0) = -3.644705e-1;
     817           0 :           p(2,0) =  6.278660e-1;
     818           0 :           p(3,0) = -5.335581e-1; 
     819           0 :           p(4,0) =  2.312756e-1;
     820           0 :           p(0,1) =  4.028559e-3;
     821           0 :           p(1,1) = -3.697768e-2; 
     822           0 :           p(2,1) = 1.021332e-1;
     823           0 :           p(3,1) = -1.201436e-1;
     824           0 :           p(4,1) = 6.412774e-2;
     825           0 :           q(0,0) = 1.0000000e0;
     826           0 :           q(1,0) = 8.212018e-1;
     827           0 :           q(2,0) = 2.078043e-1;
     828           0 :           q(0,1) = 1.0000000e0;
     829           0 :           q(1,1) = 9.599102e-1;
     830           0 :           q(2,1) = 2.918724e-1;
     831             : 
     832           0 :           part = 0;
     833           0 :           nuend = 0.0;
     834           0 :           if ((nu >= 0.0) && (nu < 0.75)) 
     835             :             {
     836           0 :               part = 0;
     837           0 :               nuend = 0.75;
     838             :             } 
     839           0 :           else if ((nu >= 0.75) && (nu <= 1.00)) 
     840             :             {
     841           0 :               part = 1;
     842           0 :               nuend = 1.0;
     843             :             }
     844             :           
     845           0 :           top = p(0,part);
     846           0 :           delnusq = pow(nu,2.0) - pow(nuend,2.0);
     847           0 :           for (uInt k=1; k<np; k++) 
     848           0 :             top += p(k, part) * pow(delnusq, (Double)k);
     849             : 
     850           0 :           bot = q(0, part);
     851           0 :           for (uInt k=1; k<nq; k++) 
     852           0 :             bot += q(k,part) * pow(delnusq, (Double)k);
     853             :           
     854           0 :           if (bot != 0.0) return (top/bot);
     855           0 :           else            return 0.0;
     856           0 :         }
     857             :   }
     858           0 :     Double SynthesisUtils::getRefFreq(const VisBuffer2& /*vb*/)
     859             :   {
     860           0 :     throw(AipsError("SynthesisUtils::getRefFreq() depricated due to VI2/VB2 move"));
     861             :     // return max((vb.getVi()->ms())//vb.msColumns()
     862             :     //        .spectralWindow().chanFreq().getColumn());
     863             :   }
     864             :   
     865           0 :   void SynthesisUtils::makeFTCoordSys(const CoordinateSystem& coords,
     866             :                                       const Int& convSize,
     867             :                                       const Vector<Double>& ftRef,
     868             :                                       CoordinateSystem& ftCoords)
     869             :   {
     870             :     Int directionIndex;
     871             : 
     872           0 :     ftCoords = coords;
     873           0 :     directionIndex=ftCoords.findCoordinate(Coordinate::DIRECTION);
     874             :     //  The following line follows the (lame) logic that if a
     875             :     //  DIRECTION axis was not found, the coordinate system must be of
     876             :     //  the FT domain already
     877           0 :     if (directionIndex == -1) return;
     878             : 
     879           0 :     DirectionCoordinate dc;//=coords.directionCoordinate(directionIndex);
     880             :     //  AlwaysAssert(directionIndex>=0, AipsError);
     881           0 :     dc=coords.directionCoordinate(directionIndex);
     882           0 :     Vector<Bool> axes(2); axes(0)=axes(1)=true;//axes(2)=true;
     883           0 :     Vector<Int> shape(2,convSize);
     884             : 
     885           0 :     Vector<Double>ref(4);
     886           0 :     ref(0)=ref(1)=ref(2)=ref(3)=0;
     887           0 :     dc.setReferencePixel(ref);
     888           0 :     Coordinate* ftdc=dc.makeFourierCoordinate(axes,shape);
     889           0 :     Vector<Double> refVal;
     890           0 :     refVal=ftdc->referenceValue();
     891             :     //    refVal(0)=refVal(1)=0;
     892             :     //    ftdc->setReferenceValue(refVal);
     893           0 :     ref(0)=ftRef(0);
     894           0 :     ref(1)=ftRef(1);
     895           0 :     ftdc->setReferencePixel(ref);
     896             : 
     897           0 :     ftCoords.replaceCoordinate(*ftdc, directionIndex);
     898             :     // LogIO logio;
     899             :     // IPosition tt;
     900             :     // coords.list(logio,MDoppler::RADIO,tt,tt);
     901             :     // ftCoords.list(logio,MDoppler::RADIO,tt,tt);
     902             : 
     903           0 :     delete ftdc; ftdc=0;
     904           0 :   }
     905             : 
     906             :   //
     907             :   // Given a list of Spw,MinFreq,MaxFreq,FreqStep (the output product
     908             :   // of MSSelection), expand the list to a list of channel freqs. and
     909             :   // conjugate freqs. per SPW.
     910             :   //
     911           0 :   void SynthesisUtils::expandFreqSelection(const Matrix<Double>& freqSelection, 
     912             :                                            Matrix<Double>& expandedFreqList,
     913             :                                            Matrix<Double>& expandedConjFreqList)
     914             :   {
     915           0 :     Int nSpw = freqSelection.shape()(0), maxSlots=0;
     916             :     Double freq;
     917             : 
     918           0 :     for (Int s=0;s<nSpw;s++)
     919           0 :         maxSlots=max(maxSlots,SynthesisUtils::nint((freqSelection(s,2)-freqSelection(s,1))/freqSelection(s,3))+1);
     920             : 
     921           0 :     expandedFreqList.resize(nSpw,maxSlots);
     922           0 :     expandedConjFreqList.resize(nSpw,maxSlots);
     923             : 
     924           0 :     for (Int s=0,cs=(nSpw-1);s<nSpw;s++,cs--)
     925           0 :       for (Int i=0,ci=(maxSlots-1);i<maxSlots;i++,ci--)
     926             :         {
     927           0 :           freq = freqSelection(s,1)+i*freqSelection(s,3);
     928           0 :           expandedFreqList(s,i) = (freq <= freqSelection(s,2)) ? freq : 0;
     929           0 :           freq = freqSelection(cs,2) - ci*freqSelection(cs,3);
     930           0 :           expandedConjFreqList(s,ci) = (freq >= freqSelection(cs,1)) ? freq : 0;
     931             :         }
     932           0 :   }
     933             : 
     934             :   //
     935             :   // The result will be in-place in c1
     936             :   //
     937             :   template
     938             :   void SynthesisUtils::libreConvolver(Array<Complex>& c1, const Array<Complex>& c2);
     939             :   
     940             : 
     941             :   template <class T>
     942           0 :   void SynthesisUtils::libreConvolver(Array<T>& c1, const Array<T>& c2)
     943             :   {
     944           0 :     Array<T> c2tmp;
     945           0 :     c2tmp.assign(c2);
     946             : 
     947           0 :     if (c1.shape().product() > c2tmp.shape().product())
     948           0 :       c2tmp.resize(c1.shape(),true);
     949             :     else
     950           0 :       c1.resize(c2tmp.shape(),true);
     951             : 
     952             : 
     953           0 :     ArrayLattice<T> c2tmp_lat(c2tmp), c1_lat(c1);
     954             : 
     955           0 :     LatticeFFT::cfft2d(c1_lat,false);
     956           0 :     LatticeFFT::cfft2d(c2tmp_lat,false);
     957             :     //cerr << "########## " << c1.shape() << " " << c2tmp.shape() << endl;
     958           0 :     c1 = sqrt(c1);
     959           0 :     c2tmp=sqrt(c2tmp);
     960           0 :     c1 *= conj(c2tmp);
     961           0 :     LatticeFFT::cfft2d(c1_lat);
     962           0 :   }
     963             : 
     964             : 
     965           0 :   Double SynthesisUtils::nearestValue(const Vector<Double>& list, const Double& val, Int& index)
     966             :   {
     967           0 :     Vector<Double> diff = fabs(list - val);
     968           0 :     Double minVal=1e20; 
     969           0 :     Int i=0;
     970             : 
     971           0 :     for (index=0;index<(Int)diff.nelements();index++)
     972           0 :       if (diff[index] < minVal) {minVal=diff[index];i=index;}
     973           0 :     index=i;
     974           0 :     return list(index);
     975             : 
     976             :     // The algorithm below has a N*log(N) cost.
     977             :     //
     978             :     // Bool dummy;
     979             :     // Sort sorter(diff.getStorage(dummy), sizeof(Double));
     980             :     // sorter.sortKey((uInt)0,TpDouble);
     981             :     // Int nch=list.nelements();
     982             :     // Vector<uInt> sortIndx;
     983             :     // sorter.sort(sortIndx, nch);
     984             :     
     985             :     // index=sortIndx(0);
     986             :     // return list(index);
     987             : 
     988             : 
     989             :     // Works only for regularly samplied list
     990             :     //
     991             :     // Int ndx=min(freqValues_p.nelements()-1,max(0,SynthesisUtils::nint((freqVal-freqValues_p[0])/freqValIncr_p)));
     992             :     // return ndx;
     993           0 :   }
     994             : 
     995             :   template <class T>
     996           0 :   T SynthesisUtils::stdNearestValue(const vector<T>& list, const T& val, Int& index)
     997             :   {
     998             :     // auto const it = std::lower_bound(list.begin(), list.end(), val);
     999             :     // if (it == list.begin()) return list[0];
    1000             :     // else return list[*(it-1)];
    1001             : 
    1002           0 :     vector<T> diff=list;
    1003           0 :     for (uInt i=0;i<list.size();i++)
    1004           0 :       diff[i] = fabs(list[i] - val);
    1005             :     
    1006           0 :     T minVal=std::numeric_limits<T>::max();//1e20; 
    1007           0 :     Int i=0;
    1008             : 
    1009           0 :     for (index=0;index<(Int)diff.size();index++)
    1010           0 :       if (diff[index] < minVal) {minVal=diff[index];i=index;}
    1011           0 :     index=i;
    1012           0 :     return list[index];
    1013           0 :   }
    1014             : 
    1015           0 :   CoordinateSystem SynthesisUtils::makeUVCoords(const CoordinateSystem& imageCoordSys,
    1016             :                                                 const IPosition& shape)
    1017             :   {
    1018           0 :     CoordinateSystem FTCoords = imageCoordSys;
    1019             :     
    1020           0 :     Int dirIndex=FTCoords.findCoordinate(Coordinate::DIRECTION);
    1021           0 :     DirectionCoordinate dc=imageCoordSys.directionCoordinate(dirIndex);
    1022           0 :     Vector<Bool> axes(2); axes=true;
    1023           0 :     Vector<Int> dirShape(2); dirShape(0)=shape(0);dirShape(1)=shape(1);
    1024           0 :     Coordinate* FTdc=dc.makeFourierCoordinate(axes,dirShape);
    1025           0 :     FTCoords.replaceCoordinate(*FTdc,dirIndex);
    1026           0 :     delete FTdc;
    1027             :     
    1028           0 :     return FTCoords;
    1029           0 :   }
    1030             : 
    1031           0 :   Vector<Int> SynthesisUtils::mapSpwIDToDDID(const VisBuffer2& vb, const Int& spwID)
    1032             :   {
    1033           0 :     Vector<Int> ddidList;
    1034             :     //Int nDDRows = vb.msColumns().dataDescription().nrow();
    1035           0 :     Int nDDRows = (vb.ms()).dataDescription().nrow();
    1036           0 :     for (Int i=0; i<nDDRows; i++)
    1037             :       {
    1038           0 :         if((vb.subtableColumns()).dataDescription().spectralWindowId().get(i) == spwID)
    1039             :           {
    1040           0 :             Int n=ddidList.nelements();
    1041           0 :             ddidList.resize(n+1,true);
    1042           0 :             ddidList(n) = i;
    1043             :           }
    1044             :       }
    1045           0 :     return ddidList;
    1046           0 :   }
    1047             : 
    1048           0 :   Vector<Int> SynthesisUtils::mapSpwIDToPolID(const VisBuffer2& vb, const Int& spwID)
    1049             :   {
    1050           0 :     Vector<Int> polIDList, ddIDList;
    1051           0 :     ddIDList = SynthesisUtils::mapSpwIDToDDID(vb, spwID);
    1052           0 :     Int n=ddIDList.nelements();
    1053           0 :     polIDList.resize(n);
    1054           0 :     for (Int i=0; i<n; i++)
    1055           0 :       polIDList(i) = (vb.subtableColumns()).dataDescription().polarizationId().get(ddIDList(i));
    1056             :       
    1057           0 :     return polIDList;
    1058           0 :   }
    1059             : 
    1060             : 
    1061             :   // 
    1062             :   // Calcualte the BLC, TRC of the intersection of two rectangles (courtesy U.Rau)
    1063             :   //
    1064           0 :   void SynthesisUtils::calcIntersection(const Int blc1[2], const Int trc1[2], 
    1065             :                                         const Float blc2[2], const Float trc2[2],
    1066             :                                         Float blc[2], Float trc[2])
    1067             :   {
    1068             :     //    cerr << blc1[0] << " " << blc1[1] << " " << trc1[0] << " " << trc1[1] << " " << blc2[0] << " " << blc2[1] << " " << trc2[0] << " " << trc2[1] << endl;
    1069             :     Float dblc, dtrc;
    1070           0 :     for (Int i=0;i<2;i++)
    1071             :       {
    1072           0 :         dblc = blc2[i] - blc1[i];
    1073           0 :         dtrc = trc2[i] - trc1[i];
    1074             : 
    1075           0 :         if ((dblc >= 0) and (dtrc >= 0))
    1076             :           {
    1077           0 :             blc[i] = blc1[i] + dblc;
    1078           0 :             trc[i] = trc2[i] - dtrc;
    1079             :           }
    1080           0 :         else if ((dblc >= 0) and (dtrc < 0))
    1081             :           {
    1082           0 :             blc[i] = blc1[i] + dblc;
    1083           0 :             trc[i] = trc1[i] + dtrc;
    1084             :           }
    1085           0 :         else if ((dblc < 0) and (dtrc >= 0))
    1086             :           {
    1087           0 :             blc[i] = blc2[i] - dblc;
    1088           0 :             trc[i] = trc2[i] - dtrc;
    1089             :           }
    1090             :         else
    1091             :           {
    1092           0 :             blc[i] = blc2[i] - dblc;
    1093           0 :             trc[i] = trc1[i] + dtrc;
    1094             :           }
    1095             :       }
    1096           0 :   }
    1097             :   //
    1098             :   // Check if the two rectangles interset (courtesy U.Rau).
    1099             :   //
    1100           0 :   Bool SynthesisUtils::checkIntersection(const Int blc1[2], const Int trc1[2], const Float blc2[2], const Float trc2[2])
    1101             :   {
    1102             :     // blc1[2] = {xmin1, ymin1}; 
    1103             :     // blc2[2] = {xmin2, ymin2};
    1104             :     // trc1[2] = {xmax1, ymax1};
    1105             :     // trc2[2] = {xmax2, ymax2};
    1106             : 
    1107           0 :     if ((blc1[0] > trc2[0]) || (trc1[0] < blc2[0]) || (blc1[1] > trc2[1]) || (trc1[1] < blc2[1])) 
    1108           0 :       return false;
    1109             :     else
    1110           0 :       return true;
    1111             : // def checkintersect(  xmin1, ymin1, xmax1, ymax1,   xmin2, ymin2, xmax2, ymax2 ):
    1112             : //     if  xmin1 > xmax2  or xmax1 < xmin2 or ymin1 > ymax2 or ymax1 < ymin2 :
    1113             : //         return false
    1114             : //     else : 
    1115             : //         return true
    1116             :   }
    1117             : 
    1118             :   // template<class Iterator>
    1119             :   // Iterator SynthesisUtils::Unique(Iterator first, Iterator last)
    1120             :   // {
    1121             :   //   while (first != last)
    1122             :   //     {
    1123             :   //       Iterator next(first);
    1124             :   //       last = std::remove(++next, last, *first);
    1125             :   //       first = next;
    1126             :   //     }
    1127             :     
    1128             :   //   return last;
    1129             :   // }
    1130             : 
    1131           0 :   String SynthesisUtils::mjdToString(casacore::Time& time)
    1132             :   {
    1133           0 :     String tStr;
    1134           0 :     tStr = String::toString(time.year()) + "/" +
    1135           0 :       String::toString(time.month()) + "/" +
    1136           0 :       String::toString(time.dayOfMonth()) + "/" +
    1137           0 :       String::toString(time.hours()) + ":" +
    1138           0 :       String::toString(time.minutes()) + ":";
    1139           0 :     ostringstream fsec;
    1140           0 :     fsec << setprecision(2) << time.dseconds();
    1141           0 :     tStr = tStr + String(fsec.str());
    1142             :     //      String::toString(time.dseconds());
    1143           0 :     return tStr;
    1144           0 :   }
    1145             : 
    1146             :   template <class Iterator>
    1147           0 :   Iterator SynthesisUtils::Unique(Iterator first, Iterator last)
    1148             :   {
    1149           0 :     while (first != last)
    1150             :       {
    1151           0 :         Iterator next(first);
    1152           0 :         last = std::remove(++next, last, *first);
    1153           0 :         first = next;
    1154             :       }
    1155             :     
    1156           0 :     return last;
    1157             :   }
    1158             : 
    1159           0 :   void SynthesisUtils::showCS(const CoordinateSystem& cs, std::ostream &os, const String& msg)
    1160             :   {
    1161           0 :     LogIO log_l(LogOrigin("SynthesisUtils","showCS"));
    1162           0 :     IPosition dummy;
    1163           0 :     Vector<String> csList;
    1164           0 :     if (msg!="")
    1165           0 :       os << "CoordSys: ";
    1166           0 :     csList = cs.list(log_l,MDoppler::RADIO,dummy,dummy);
    1167           0 :     os << csList << std::endl;
    1168           0 :   }
    1169           0 :  const casacore::Array<Complex> SynthesisUtils::getCFPixels(const casacore::String& Dir,
    1170             :                                                             const casacore::String& fileName)
    1171             :   {
    1172             :     try
    1173             :       {
    1174           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1175           0 :         return thisCF.get();
    1176           0 :       }
    1177           0 :     catch (AipsError &x)
    1178             :       {
    1179           0 :         LogIO log_l(LogOrigin("SynthesisUtils","getCFPixels"));
    1180           0 :         log_l << x.getMesg() << LogIO::EXCEPTION;
    1181           0 :       }
    1182           0 :     return casacore::Array<Complex>(); // Just to keep the complier happy.  Program control should never get here.
    1183             :   }
    1184             :   
    1185           0 :  void SynthesisUtils::putCFPixels(const casacore::String& Dir,
    1186             :                                   const casacore::String& fileName,
    1187             :                                   const casacore::Array<Complex>& srcpix)
    1188             :   {
    1189             :     try
    1190             :       {
    1191           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1192           0 :         return thisCF.put(srcpix);
    1193           0 :       }
    1194           0 :     catch (AipsError &x)
    1195             :       {
    1196           0 :         LogIO log_l(LogOrigin("SynthesisUtils","putCFPixels"));
    1197           0 :         log_l << x.getMesg() << LogIO::EXCEPTION;
    1198           0 :       }
    1199             :   }
    1200             :   
    1201           0 :  const casacore::IPosition SynthesisUtils::getCFShape(const casacore::String& Dir,
    1202             :                                                       const casacore::String& fileName)
    1203             :   {
    1204             :     try
    1205             :       {
    1206           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1207           0 :         return thisCF.shape();
    1208           0 :       }
    1209           0 :     catch (AipsError &x)
    1210             :       {
    1211           0 :         LogIO log_l(LogOrigin("SynthesisUtils","getCFShape"));
    1212           0 :         log_l << x.getMesg() << LogIO::EXCEPTION;
    1213           0 :       }
    1214           0 :     return casacore::IPosition(); // Just to keep the complier happy.  Program control should never get here.
    1215             :   }
    1216             :   
    1217           0 :   casacore::TableRecord SynthesisUtils::getCFParams(const casacore::String& Dir,
    1218             :                                                     const casacore::String& fileName,
    1219             :                                                     casacore::IPosition& cfShape,
    1220             :                                                     casacore::Array<Complex>& pixelBuffer,
    1221             :                                                     casacore::CoordinateSystem& coordSys, 
    1222             :                                                     casacore::Double& sampling,
    1223             :                                                     casacore::Double& paVal,
    1224             :                                                     casacore::Int& xSupport, casacore::Int& ySupport,
    1225             :                                                     casacore::Double& fVal, casacore::Double& wVal, casacore::Int& mVal,
    1226             :                                                     casacore::Double& conjFreq, casacore::Int& conjPoln,
    1227             :                                                     casacore::Bool loadPixels,
    1228             :                                                     casacore::Bool loadMiscInfo)
    1229             :   {
    1230             :     try
    1231             :       {
    1232             :         //casacore::Table tThisCF(Dir+'/'+fileName);
    1233           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1234           0 :         cfShape = thisCF.shape();
    1235           0 :         if (loadPixels) pixelBuffer.assign(thisCF.get());
    1236           0 :         casacore::TableRecord miscinfo;
    1237           0 :         if (loadMiscInfo)
    1238             :           {
    1239           0 :             miscinfo= thisCF.miscInfo();
    1240             : 
    1241           0 :             miscinfo.get("ParallacticAngle", paVal);
    1242           0 :             miscinfo.get("MuellerElement", mVal);
    1243           0 :             miscinfo.get("WValue", wVal);
    1244           0 :             miscinfo.get("Xsupport", xSupport);
    1245           0 :             miscinfo.get("Ysupport", ySupport);
    1246           0 :             miscinfo.get("Sampling", sampling);
    1247           0 :             miscinfo.get("ConjFreq", conjFreq);
    1248           0 :             miscinfo.get("ConjPoln", conjPoln);
    1249           0 :             casacore::Int index= thisCF.coordinates().findCoordinate(casacore::Coordinate::SPECTRAL);
    1250           0 :             coordSys = thisCF.coordinates();
    1251           0 :             casacore::SpectralCoordinate spCS = coordSys.spectralCoordinate(index);
    1252           0 :             fVal=static_cast<Float>(spCS.referenceValue()(0));
    1253           0 :           }
    1254           0 :         return miscinfo;
    1255           0 :       }
    1256           0 :     catch(AipsError& x)
    1257             :       {
    1258           0 :         throw(AipsError(String("Error in SynthesisUtils::getCFParams(): ")
    1259           0 :                                       +x.getMesg()));
    1260           0 :       }
    1261             :   };
    1262             : 
    1263             : 
    1264           0 :   void SynthesisUtils::rotate2(const double& actualPA, CFCell& baseCFC, CFCell& cfc, const double& rotAngleIncr)
    1265             :     {
    1266           0 :       LogIO log_l(LogOrigin("SynthesisUtils", "rotate2"));
    1267             : 
    1268             :       // // If the A-Term is a No-Op, the resulting CF is rotationally
    1269             :       // // symmetric.
    1270             :       // if (isNoOp()) return;
    1271             : 
    1272             :       (void)baseCFC;
    1273             : 
    1274             :       //double actualPA = getPA(vb);
    1275           0 :       double currentCFPA = cfc.pa_p.getValue("rad");
    1276             :       //Double baseCFCPA=baseCFC.pa_p.getValue("rad");
    1277             : 
    1278           0 :       double dPA = currentCFPA-actualPA;
    1279             : 
    1280           0 :       if (fabs(dPA) > fabs(rotAngleIncr))
    1281             :         {
    1282           0 :           casacore::Array<TT> inData;
    1283             :           //inData.assign(*baseCFC.getStorage());
    1284             :           //dPA = baseCFCPA-actualPA;
    1285           0 :           dPA = currentCFPA-actualPA;
    1286           0 :           inData.assign(*cfc.getStorage());
    1287             :           try
    1288             :             {
    1289           0 :               SynthesisUtils::rotateComplexArray(log_l, inData, cfc.coordSys_p,
    1290           0 :                                                  *cfc.getStorage(),
    1291             :                                                  dPA);//,"LINEAR");
    1292             :               // currentCFPA-actualPA);//,"LINEAR");
    1293             :             }
    1294           0 :           catch (AipsError &x)
    1295             :             {
    1296           0 :               log_l << x.getMesg() << LogIO::EXCEPTION;
    1297           0 :             }
    1298           0 :           cfc.pa_p=Quantity(actualPA, "rad");
    1299           0 :         }
    1300           0 :     };
    1301             : 
    1302             : 
    1303             :     //
    1304             :     // Parser for parsing the NAME field of the SPECTRAL_WINDOW sub-table.
    1305             :     // Returns a vector of string containing tokens separated by "#"
    1306             :     // in the supplied band name string.
    1307             :     //
    1308           0 :     casacore::Vector<casacore::String> SynthesisUtils::parseBandName(const casacore::String& bandName)
    1309             :     {
    1310           0 :       casacore::Vector<casacore::String> tokens;
    1311             : 
    1312             :       // Allow a blank band name for older MSes where this is sometimes left blank.
    1313           0 :       if (bandName == "")
    1314             :         {
    1315           0 :           tokens.resize(1);tokens="";
    1316           0 :           return tokens;
    1317             :         }
    1318             : 
    1319             :       char *tok, *name;
    1320           0 :       int i=0;
    1321             : 
    1322           0 :       name = (char *)bandName.c_str();
    1323           0 :       if ((tok = std::strtok(name,"#"))!=NULL)
    1324             :         {
    1325           0 :           tokens.resize(i+1,true); tokens(i)="";
    1326           0 :           tokens(i++).assign(tok);
    1327             :         }
    1328             : 
    1329           0 :       while ((tok = std::strtok(NULL,"#"))!=NULL)
    1330             :         {
    1331           0 :           tokens.resize(i+1,true); tokens(i)="";
    1332           0 :           tokens(i++).assign(tok);
    1333             :         }
    1334           0 :       if (tokens(0)=="")
    1335             :         {
    1336           0 :           LogIO log_l(LogOrigin("SynthesisUtils", "parseBandName"));
    1337           0 :           log_l << "Error while parsing band name \"" << bandName << "\"" << LogIO::EXCEPTION;
    1338           0 :         }
    1339             : 
    1340             :       // for (i=0;i<3;i++)
    1341             :       //        if (tokens(i)=="") log_l << "Error while parsing band name \"" << bandName << LogIO::EXCEPTION;
    1342           0 :       return tokens;
    1343           0 :     }
    1344             : 
    1345             : 
    1346             : //
    1347             : //-----------------------------------------------------------------------------------------
    1348             : //
    1349           0 :     casacore::CoordinateSystem SynthesisUtils::makeModelGridFromImage(const std::string& modelImageName,
    1350             :                                                                       casacore::TempImage<casacore::DComplex>& modelImageGrid)
    1351             :     {
    1352             :       // This code is basically loading a floating point image from
    1353             :       // the disk, and loading it into a complex<double> image.  This
    1354             :       // should be possible on-the-fly.
    1355             :       //
    1356             :       // However currently it is not possible to this OTF.  So one has
    1357             :       // to load the image from the disk in a float image (copy-1 of
    1358             :       // the image in the memory).  Then, since
    1359             :       // StokesImageUtil::From() does not work with complex<double>
    1360             :       // images, convert it first to a complex<float> image (equal to
    1361             :       // 2 more float buffers in the memory).  And then covert the
    1362             :       // complex<float> image to a complex<Double> image (equal to 4
    1363             :       // more float buffers in the memory).
    1364             :       //
    1365             :       // In the end, just because of limitations of OTF type
    1366             :       // conversions, we end up with 7x memory footprint!
    1367             : 
    1368           0 :       casacore::LatticeBase* lattPtr = casacore::ImageOpener::openImage (modelImageName);
    1369             :       casacore::ImageInterface<float> *fImage;
    1370           0 :       fImage = dynamic_cast<casacore::ImageInterface<float>*>(lattPtr);
    1371             : 
    1372           0 :       TempImage<casacore::Complex> tmp(fImage->shape(), fImage->coordinates());
    1373           0 :       StokesImageUtil::From(tmp, *fImage);
    1374             : 
    1375           0 :       modelImageGrid  = casacore::TempImage<casacore::DComplex> (fImage->shape(), fImage->coordinates());
    1376             : 
    1377             :       Bool d0,d1;
    1378           0 :       casacore::Array<casacore::DComplex> dcArray=modelImageGrid.get();
    1379           0 :       casacore::Array<casacore::Complex> fcArray=tmp.get();
    1380             : 
    1381           0 :       casacore::DComplex* dcArrayPtr= dcArray.getStorage(d0);
    1382           0 :       casacore::Complex* fcArrayPtr = fcArray.getStorage(d1);
    1383           0 :       IPosition ndx(4,0,0,0,0),shape=fImage->shape();
    1384             : 
    1385           0 :       for (ndx(0)=0; ndx(0)<shape(0);ndx(0)++)
    1386           0 :         for (ndx(1)=0; ndx(1)<shape(1);ndx(1)++)
    1387           0 :           for (ndx(2)=0; ndx(2)<shape(2);ndx(2)++)
    1388           0 :             for (ndx(3)=0; ndx(3)<shape(3);ndx(3)++)
    1389           0 :               dcArray(ndx) = DComplex(fcArray(ndx).real(), fcArray(ndx).imag());
    1390             : 
    1391           0 :       modelImageGrid.put(dcArray);
    1392           0 :       return fImage->coordinates();
    1393           0 :     }
    1394             :     //
    1395             :     //-------------------------------------------------------------------------------------
    1396             :     //
    1397           0 :     void SynthesisUtils::makeAWLists(const casacore::Vector<double>& wVals,
    1398             :                                      const casacore::Vector<double>& fVals,
    1399             :                                      const bool& wbAWP, const uint& nw,
    1400             :                                      const double& imRefFreq, const double& spwRefFreq,
    1401             :                                      casacore::Vector<int>& wNdxList,
    1402             :                                      casacore::Vector<int>& spwNdxList,
    1403             :                                      const int vbSPW)
    1404             :     {
    1405             :       //
    1406             :       // The following can be generalized to pick a subset of CFs along
    1407             :       // W and SPW axis in the CFB.  Perhaps also useful in the longer
    1408             :       // run, e.g. when using a super-set CFC not all of which may be
    1409             :       // used for a given imaging.
    1410             :       //
    1411             :       // W-pixels in the CFC should be >= w-planes user setting
    1412           0 :       assert(wVals.nelements() >= nw);
    1413             :       
    1414             :       // Make list of W-CF indexes
    1415           0 :       int nWCFs=(nw<=1)?nw:wVals.nelements();
    1416           0 :       wNdxList.resize(nWCFs);
    1417           0 :       for(int i=0;i<nWCFs;i++) wNdxList[i] = i;
    1418             :       
    1419             :       // Make list of SPW-CF indexes
    1420           0 :       int nSPWCFs=fVals.nelements();
    1421           0 :       if (wbAWP==true)
    1422             :         {
    1423             :           // If a valid SPW ID is given, translate it to the spwNdx for the nearest SPW
    1424           0 :           if ((vbSPW>=0))// && (vbSPW <nSPWCFs))
    1425             :             {
    1426             :               int refSPW;
    1427           0 :               std::vector<double> stdList(nSPWCFs);
    1428           0 :               for (int i=0; i<nSPWCFs; i++) stdList[i] = fVals[i];
    1429             :               //Double refCFFreq =
    1430           0 :               SynthesisUtils::stdNearestValue(stdList, spwRefFreq, refSPW);
    1431             :               
    1432           0 :               spwNdxList.resize(1);
    1433           0 :               spwNdxList[0]=refSPW;
    1434           0 :             }
    1435             :           else
    1436             :             {
    1437           0 :               spwNdxList.resize(nSPWCFs);
    1438           0 :               for(int i=0;i<nSPWCFs;i++) spwNdxList[i] = i;
    1439             :             }
    1440             :         }
    1441             :       else
    1442             :         {
    1443             :           // For wbAWP=F, pick up the CF closest to the image reference frequency
    1444             :           int refSPW;
    1445           0 :           std::vector<double> stdList(nSPWCFs);
    1446           0 :           for (int i=0; i<nSPWCFs; i++) stdList[i] = fVals[i];
    1447             :           //Double refCFFreq =
    1448           0 :           SynthesisUtils::stdNearestValue(stdList, imRefFreq, refSPW);
    1449             :           
    1450           0 :           spwNdxList.resize(1);
    1451           0 :           spwNdxList[0]=refSPW;
    1452           0 :         }
    1453             :       
    1454           0 :       return;
    1455             :     }
    1456             : 
    1457             : 
    1458             :   template
    1459             :   std::vector<Double>::iterator SynthesisUtils::Unique(std::vector<Double>::iterator first, std::vector<Double>::iterator last);
    1460             :   template
    1461             :   std::vector<Float>::iterator SynthesisUtils::Unique(std::vector<Float>::iterator first, std::vector<Float>::iterator last);
    1462             :   template
    1463             :   std::vector<Int>::iterator SynthesisUtils::Unique(std::vector<Int>::iterator first, std::vector<Int>::iterator last);
    1464             : 
    1465             :   template 
    1466             :   Double SynthesisUtils::stdNearestValue(const vector<Double>& list, const Double& val, Int& index);
    1467             :   template 
    1468             :   Float SynthesisUtils::stdNearestValue(const vector<Float>& list, const Float& val, Int& index);
    1469             :   template 
    1470             :   Int SynthesisUtils::stdNearestValue(const vector<Int>& list, const Int& val, Int& index);
    1471             : 
    1472             : /////===========
    1473           0 :    MathUtils::MathUtils(){
    1474             :      //Timer tim;
    1475             :      //tim.mark();
    1476           0 :     initSincCache();
    1477             :     //tim.show("Calculating 16000 sines");
    1478           0 :   }
    1479           0 :   Array<Complex> MathUtils::resample(const Array<Complex>& inarray, const Double factorX, const Double factorY) {
    1480             : 
    1481           0 :     if(factorX == 1.0 && factorY==1.0)
    1482           0 :       return inarray;
    1483           0 :     Double nx=Double(inarray.shape()(0));
    1484           0 :     Double ny=Double(inarray.shape()(1));
    1485           0 :     IPosition shp=inarray.shape();
    1486             :     //cerr <<  "shp " <<  shp <<  endl;
    1487           0 :     shp(0)=Int(nx*factorX/8.0)*8;
    1488           0 :     shp(1)=Int(ny*factorY/8.0)*8;
    1489           0 :     Int newNx=shp(0);
    1490           0 :     Int newNy=shp(1);
    1491             :     // cerr << "SHP " << shp << endl;
    1492           0 :     Array<Complex> out(shp, Complex(0.0));
    1493             :    
    1494             :    /*IPosition incursor=IPosition(inarray.shape().nelements(),1);
    1495             :     incursor[0]=nx;
    1496             :     incursor[1]=ny;
    1497             :     IPosition outcursor=IPosition(inarray.shape().nelements(),1);
    1498             :     outcursor[0]=shp[0];
    1499             :     outcursor[1]=shp[1];
    1500             :     */
    1501           0 :     ArrayIterator<Complex> inIt(inarray, IPosition(2,0,1), True);
    1502           0 :     ArrayIterator<Complex> outIt(out, IPosition(2,0,1),True);
    1503           0 :     inIt.origin();
    1504           0 :     outIt.origin();
    1505             :     //for (zzz=0; zzz< shp.(4); ++zzz){
    1506             :     //  for(yyy=0; yyy< shp.(3); ++yyy){
    1507             :     // for(xxx=0; xxx< shp.(2); ++xxx){
    1508           0 :     while(!inIt.pastEnd()) {
    1509             :        // cerr << "Iter shape " << inIt.array().shape() << endl;
    1510           0 :         Matrix<Complex> inmat;
    1511           0 :         inmat=inIt.array();    
    1512             :         //Matrix<Float> leReal=real(Matrix<Complex>(inIt.array()));
    1513             :         //Matrix<Float> leImag=imag(Matrix<Complex>(inIt.array()));
    1514           0 :         Matrix<Float> leReal=real(inmat);
    1515           0 :         Matrix<Float> leImag=imag(inmat);
    1516             :         Bool leRealCopy, leImagCopy;
    1517           0 :         Float *realptr=leReal.getStorage(leRealCopy);
    1518           0 :         Float *imagptr=leImag.getStorage(leImagCopy);
    1519             :         Bool isCopy;
    1520           0 :         Matrix<Complex> outMat(outIt.array());
    1521           0 :         Complex *intPtr=outMat.getStorage(isCopy);
    1522             :         Float realval, imagval;
    1523             : #ifdef _OPENMP
    1524           0 :         omp_set_nested(0);
    1525             : #endif
    1526           0 :         #pragma omp parallel for default(none) private(realval, imagval) firstprivate(intPtr, realptr, imagptr, nx, ny, newNx, newNy) shared(leReal, leImag)
    1527             : 
    1528             :         for (Int k =0; k < newNy; ++k) {
    1529             :             Double y =Double(k)/Double(newNy)*Double(ny);
    1530             : 
    1531             :             for (Int j=0; j < newNx; ++j) {
    1532             :                 //      Interpolate2D interp(Interpolate2D::LANCZOS);
    1533             :                 Double x=Double(j)/Double(newNx)*Double(nx);
    1534             :                 //interp.interp(realval, where, leReal);
    1535             :                 realval=interpLanczos(x , y, nx, ny,
    1536             :                                       realptr, 3);
    1537             :                 imagval=interpLanczos(x , y, nx, ny,
    1538             :                                       imagptr, 3);
    1539             :                 //interp.interp(imagval, where, leImag);
    1540             :                 intPtr[k*Int(newNx)+j]=Complex(realval, imagval);
    1541             :             }
    1542             : 
    1543             :         }
    1544           0 :         outMat.putStorage(intPtr, isCopy);
    1545           0 :         leReal.putStorage(realptr, leRealCopy);
    1546           0 :         leImag.putStorage(imagptr, leImagCopy);
    1547           0 :         inIt.next();
    1548           0 :         outIt.next();
    1549           0 :     }
    1550           0 :     return out;
    1551           0 : }
    1552           0 :     void MathUtils::initSincCache(){
    1553           0 :      for (Float u=-4000; u<4000; ++u){ 
    1554           0 :       Float ux=u/1000.0;
    1555           0 :       if (ux == 0) {
    1556           0 :         sincCache_p[u+4000]=1.0;
    1557             :       }
    1558             :       else{
    1559           0 :         sincCache_p[u+4000]= sin(C::pi * ux) / (C::pi * ux);
    1560             :       }
    1561             :     }
    1562           0 :     sincCachePtr_p=sincCache_p.data(); 
    1563             :       
    1564           0 :     }
    1565           0 :     Float MathUtils::sinc(const Float x)  {
    1566           0 :         Int index=x*1000+4000;
    1567             :  
    1568             :     
    1569           0 :         return sincCachePtr_p[index];
    1570             : 
    1571             :     }
    1572           0 :     casacore::Float MathUtils::interpLanczos( const casacore::Double& x , const casacore::Double& y, const casacore::Double& nx, const casacore::Double& ny,   const casacore::Float* data, const casacore::Float a){
    1573           0 :           Double floorx = floor(x);
    1574           0 :           Double floory = floor(y);
    1575           0 :           Float result=0.0;
    1576           0 :           if (floorx < a || floorx >= nx - a || floory < a || floory >= ny - a) {
    1577           0 :             result = 0;
    1578           0 :             return result;
    1579             :           }
    1580           0 :     for (Float i = floorx - a + 1; i <= floorx + a; ++i) {
    1581           0 :       for (Float j = floory - a + 1; j <= floory + a; ++j) {
    1582           0 :         result += Float(Double(data[Int(j*nx+i)]) * sinc(x - i)*sinc((x-i)/ a) * sinc(y - j)*sinc((y-j)/ a));
    1583             :       }
    1584             :     }
    1585           0 :     return result;
    1586             :     
    1587             :     
    1588             :     }
    1589           0 :     Array<Complex> MathUtils::getMiddle(const Array<Complex>& inArr, const int nx, const int ny){
    1590           0 :      IPosition outshape=inArr.shape();
    1591           0 :      outshape[0]=nx;
    1592           0 :      outshape[1]=ny;
    1593           0 :      IPosition blc(2, (inArr.shape()[0]-nx)/2, (inArr.shape()[1]-ny)/2);
    1594           0 :      IPosition trc(2, (inArr.shape()[0]+nx)/2-1, (inArr.shape()[1]+ny)/2-1);
    1595           0 :      Array<Complex> outArr(outshape);
    1596           0 :      ArrayIterator<Complex> inIt(inArr, IPosition(2,0,1));
    1597           0 :      ArrayIterator<Complex> outIt(outArr, IPosition(2,0,1));
    1598           0 :      inIt.origin();
    1599           0 :      outIt.origin();
    1600           0 :      while(!inIt.pastEnd()){
    1601             :        //cerr << "Shapes in getM " << outIt.array().shape() << " in " << inIt.array()(blc, trc).shape() << endl;
    1602           0 :        outIt.array().assign(inIt.array()(blc,  trc));
    1603           0 :        inIt.next();
    1604           0 :        outIt.next();
    1605             :        
    1606             :        
    1607             :      }
    1608             :       
    1609           0 :       return outArr;
    1610           0 :     }
    1611             :      
    1612           0 :     void MathUtils::putMiddle(Array<Complex>& outArr, const Array<Complex>& inArr) {
    1613           0 :      Int nx = inArr.shape()[0];
    1614           0 :      Int ny = inArr.shape()[1];
    1615           0 :      if(nx < outArr.shape()[0] && ny < outArr.shape()[1]){
    1616           0 :        IPosition blc(2,  (outArr.shape()[0]-nx)/2,  (outArr.shape()[1]-ny)/2);
    1617           0 :        IPosition trc(2,  (outArr.shape()[0]+nx)/2-1,  (outArr.shape()[1]+ny)/2-1);
    1618           0 :        ArrayIterator<Complex> inIt(inArr, IPosition(2,0,1));
    1619           0 :        ArrayIterator<Complex> outIt(outArr, IPosition(2,0,1));
    1620           0 :        inIt.origin();
    1621           0 :        outIt.origin();
    1622           0 :        while(!inIt.pastEnd() && !inIt.pastEnd()){
    1623             :       
    1624           0 :         (outIt.array())(blc, trc).assign(inIt.array());
    1625             :        
    1626           0 :         inIt.next();
    1627           0 :         outIt.next();
    1628             :        }
    1629           0 :      }
    1630           0 :      else if(outArr.shape()[0] < nx && outArr.shape()[1] < ny){// take the inner of inArray
    1631           0 :         IPosition blc(2,  (nx-outArr.shape()[0])/2,  (ny-outArr.shape()[1])/2);
    1632           0 :         IPosition trc(2,  (outArr.shape()[0]+nx)/2-1,  (outArr.shape()[1]+ny)/2-1);
    1633           0 :         ArrayIterator<Complex> inIt(inArr, IPosition(2,0,1));
    1634           0 :         ArrayIterator<Complex> outIt(outArr, IPosition(2,0,1));
    1635           0 :         inIt.origin();
    1636           0 :         outIt.origin();
    1637           0 :         while(!inIt.pastEnd() && !inIt.pastEnd()){
    1638             :           //cerr << "Shapes in putM " << outIt.array().shape() << " in " << inIt.array()(blc, trc).shape() << endl;
    1639           0 :           outIt.array()=inIt.array()(blc, trc);
    1640           0 :           inIt.next();
    1641           0 :           outIt.next();
    1642             :         }
    1643             : 
    1644             : 
    1645           0 :      }
    1646             :      else{
    1647           0 :        throw(AipsError("Programmer's error  cannot use PutMiddle"));
    1648             : 
    1649             :      }
    1650             :        
    1651             :        
    1652           0 :     }
    1653             :       
    1654           0 :     Array<Complex> MathUtils::resampleViaFFT(const Array<Complex>& inarray, const Double factorX, const Double factorY) {
    1655             : 
    1656           0 :       if(factorX==1.0 && factorY==1.0)
    1657           0 :         return inarray;
    1658           0 :     Double nx=Double(inarray.shape()(0));
    1659           0 :     Double ny=Double(inarray.shape()(1));
    1660           0 :     IPosition shp=inarray.shape();
    1661             :     //cerr <<  "shp " <<  shp <<  endl;
    1662           0 :     shp(0)=Int(std::ceil(nx*factorX/8.0))*8;
    1663           0 :     shp(1)=Int(std::ceil(ny*factorY/8.0))*8;
    1664           0 :     Int newNx=shp(0);
    1665           0 :     Int newNy=shp(1);
    1666             :     /* cerr << "SHP " << shp << endl;
    1667             :     Array<Complex> out(shp, Complex(0.0));  
    1668             :     ArrayIterator<Complex> inIt(inarray, IPosition(2,0,1), True);
    1669             :     ArrayIterator<Complex> outIt(out, IPosition(2,0,1),True);
    1670             :     inIt.origin();
    1671             :     outIt.origin();
    1672             :     FFT2D ftsmall;
    1673             :     FFT2D ftlarge;
    1674             :     
    1675             :     while(!inIt.pastEnd()) {
    1676             :        // cerr << "Iter shape " << inIt.array().shape() << endl;
    1677             :         Matrix<Complex> inmat;
    1678             :         inmat=inIt.array();    
    1679             :         Bool isCopy;
    1680             :         Complex * inmatptr=inmat.getStorage(isCopy);
    1681             :         ftsmall.c2cFFT(inmatptr, nx, ny, True);
    1682             :         inmat.putStorage(inmatptr,isCopy);
    1683             :         Matrix<Complex> outMat(outIt.array());
    1684             :         putMiddle(outMat, inmat);
    1685             :         Complex *intPtr=outMat.getStorage(isCopy);
    1686             :         ftlarge.c2cFFT(intPtr, newNx, newNy, False);
    1687             :         outMat.putStorage(intPtr, isCopy);
    1688             :         Float fac=Float(newNx)*Float(newNy)/Float(nx*ny);
    1689             :         outMat *= fac; 
    1690             :         inIt.next();
    1691             :         outIt.next();
    1692             :         
    1693             :     }*/
    1694             :   
    1695           0 :     return resampleViaFFT(inarray,  newNx,  newNy);
    1696           0 :     }
    1697           0 :     Array<Complex> MathUtils::resampleViaFFT(const Array<Complex>& inarray, const Int newNx, const Int newNy) {
    1698             : 
    1699             :      
    1700           0 :     Double nx=Double(inarray.shape()(0));
    1701           0 :     Double ny=Double(inarray.shape()(1));
    1702           0 :     if (newNx == nx && newNy == ny)
    1703           0 :        return inarray;
    1704           0 :     IPosition shp=inarray.shape();
    1705           0 :     cerr <<  "shp " <<  shp <<  endl;
    1706             :     
    1707           0 :     shp(0) = newNx;
    1708           0 :     shp(1) = newNy;
    1709           0 :      cerr << "SHP " << shp << endl;
    1710           0 :     Array<Complex> out(shp, Complex(0.0));  
    1711           0 :     ArrayIterator<Complex> inIt(inarray, IPosition(2,0,1), True);
    1712           0 :     ArrayIterator<Complex> outIt(out, IPosition(2,0,1),True);
    1713           0 :     inIt.origin();
    1714           0 :     outIt.origin();
    1715           0 :     FFT2D ftsmall;
    1716           0 :     FFT2D ftlarge;
    1717             :     
    1718           0 :     while(!inIt.pastEnd()) {
    1719             :        // cerr << "Iter shape " << inIt.array().shape() << endl;
    1720           0 :         Matrix<Complex> inmat;
    1721           0 :         inmat=inIt.array();    
    1722             :         Bool isCopy;
    1723           0 :         Complex * inmatptr=inmat.getStorage(isCopy);
    1724           0 :         ftsmall.c2cFFT(inmatptr, nx, ny, True);
    1725           0 :         inmat.putStorage(inmatptr,isCopy);
    1726           0 :         Matrix<Complex> outMat(outIt.array());
    1727           0 :         putMiddle(outMat, inmat);
    1728           0 :         Complex *intPtr=outMat.getStorage(isCopy);
    1729           0 :         ftlarge.c2cFFT(intPtr, newNx, newNy, False);
    1730           0 :         outMat.putStorage(intPtr, isCopy);
    1731           0 :         Float fac=Float(newNx)*Float(newNy)/Float(nx*ny);
    1732           0 :         outMat *= fac; 
    1733           0 :         inIt.next();
    1734           0 :         outIt.next();
    1735             :         
    1736           0 :     }
    1737             :   
    1738           0 :     return out;
    1739           0 :     }
    1740             :   }  
    1741             :    
    1742             :     //using namespace casacore;
    1743             :   } // namespace casa

Generated by: LCOV version 1.16