LCOV - code coverage report
Current view: top level - synthesis/TransformMachines - Utils.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 13 579 2.2 %
Date: 2023-11-06 10:06:49 Functions: 1 52 1.9 %

          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: aips2-request@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 <msvis/MSVis/VisBuffer.h>
      29             : #include <casacore/casa/Logging/LogIO.h>
      30             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      31             : #include <casacore/measures/Measures/MEpoch.h>
      32             : #include <casacore/measures/Measures/MeasTable.h>
      33             : #include <synthesis/TransformMachines/Utils.h>
      34             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      35             : #include <casacore/casa/Utilities/Assert.h>
      36             : #include <casacore/casa/Arrays/Vector.h>
      37             : #include <casacore/casa/Arrays/ArrayMath.h>
      38             : #include <casacore/lattices/LEL/LatticeExpr.h>
      39             : #include <casacore/images/Images/PagedImage.h>
      40             : #include <casacore/images/Images/ImageRegrid.h>
      41             : #include <casacore/casa/Containers/Record.h>
      42             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      43             : #include <casacore/lattices/Lattices/TiledLineStepper.h> 
      44             : #include <casacore/lattices/Lattices/LatticeStepper.h> 
      45             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      46             : #include <casacore/casa/System/Aipsrc.h>
      47             : 
      48             : using namespace casacore;
      49             : namespace casa{
      50             :   //
      51             :   //--------------------------------------------------------------------------------------------
      52             :   //  
      53           0 :   void storeImg(String fileName,ImageInterface<Complex>& theImg, Bool writeReIm)
      54             :   {
      55           0 :     PagedImage<Complex> ctmp(theImg.shape(), theImg.coordinates(), fileName);
      56           0 :     LatticeExpr<Complex> le(theImg);
      57           0 :     ctmp.copyData(le);
      58           0 :     if (writeReIm)
      59             :       {
      60           0 :         ostringstream reName,imName;
      61           0 :         reName << "re" << fileName;
      62           0 :         imName << "im" << fileName;
      63             :         {
      64           0 :           PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), reName);
      65           0 :           LatticeExpr<Float> le(abs(theImg));
      66           0 :           tmp.copyData(le);
      67             :         }
      68             :         {
      69           0 :           PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), imName);
      70           0 :           LatticeExpr<Float> le(arg(theImg));
      71           0 :           tmp.copyData(le);
      72             :         }
      73             :       }
      74           0 :   }
      75             :   
      76           0 :   void storeImg(String fileName,ImageInterface<Float>& theImg)
      77             :   {
      78           0 :     PagedImage<Float> tmp(theImg.shape(), theImg.coordinates(), fileName);
      79           0 :     LatticeExpr<Float> le(theImg);
      80           0 :     tmp.copyData(le);
      81           0 :   }
      82             : 
      83           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
      84             :                          const Array<Complex>& theImg)
      85             :   {
      86           0 :     PagedImage<Complex> ctmp(theImg.shape(), coord, fileName);
      87           0 :     ctmp.put(theImg);
      88           0 :   }
      89           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
      90             :                          const Array<DComplex>& theImg)
      91             :   {
      92           0 :     PagedImage<DComplex> ctmp(theImg.shape(), coord, fileName);
      93           0 :     ctmp.put(theImg);
      94           0 :   }
      95           0 :   void storeArrayAsImage(String fileName, const CoordinateSystem& coord,
      96             :                          const Array<Float>& theImg)
      97             :   {
      98           0 :     PagedImage<Float> ctmp(theImg.shape(), coord, fileName);
      99           0 :     ctmp.put(theImg);
     100           0 :   }
     101             :   //
     102             :   //---------------------------------------------------------------------
     103             :   //
     104             :   // Get the time stamp for the for the current visibility integration.
     105             :   // Since VisTimeAverager() does not accumulate auto-correlations (it
     106             :   // should though!), and the VisBuffer can potentially have
     107             :   // auto-correlation placeholders, vb.time()(0) may not be correct (it
     108             :   // will be in fact zero when AC rows are present).  So look for the
     109             :   // first timestamp of a row corresponding to an unflagged
     110             :   // cross-correlation.
     111             :   //
     112           0 :   Double getCurrentTimeStamp(const VisBuffer& vb)
     113             :   {
     114           0 :     LogIO os(LogOrigin("Utils", "getCurrentTimeStamp", WHERE));
     115             : 
     116           0 :     Int N=vb.nRow();
     117           0 :     for(Int i=0;i<N;i++)
     118             :       {
     119           0 :         if ((!vb.flagRow()(i)) && (vb.antenna1()(i) != vb.antenna2()(i)))
     120           0 :           return vb.time()(i);
     121             :       }
     122             :     //os << "No unflagged row found!  This is a major problem/bug" << LogIO::WARN;
     123           0 :     return 0.0;
     124             :   }
     125             :   //
     126             :   //---------------------------------------------------------------------
     127             :   // Compute the Parallactic Angle for the give VisBuffer
     128             :   //
     129           0 :   void getHADec(MeasurementSet& ms, const VisBuffer& vb, 
     130             :                 Double& HA, Double& RA, Double& Dec)
     131             :   {
     132           0 :     MEpoch last;
     133           0 :     Double time = getCurrentTimeStamp(vb);
     134             :     
     135           0 :     Unit Second("s"), Day("d");
     136           0 :     MEpoch epoch(Quantity(time,Second),MEpoch::TAI);
     137           0 :     MPosition pos;
     138           0 :     MSObservationColumns msoc(ms.observation());
     139           0 :     String ObsName=msoc.telescopeName()(vb.arrayId());
     140             :     
     141           0 :     if (!MeasTable::Observatory(pos,ObsName))
     142           0 :       throw(AipsError("Observatory position for "+ ObsName + " not found"));
     143             :     
     144           0 :     MeasFrame frame(epoch,pos);
     145           0 :     MEpoch::Convert toLAST = MEpoch::Convert(MEpoch::Ref(MEpoch::TAI,frame),
     146           0 :                                              MEpoch::Ref(MEpoch::LAST,frame));
     147           0 :     RA=vb.direction1()(0).getAngle().getValue()(0);    
     148           0 :     if (RA < 0.0) RA += M_PI*2.0;
     149           0 :     Dec=vb.direction1()(0).getAngle().getValue()(1);    
     150             : 
     151           0 :     last = toLAST(epoch);
     152           0 :     Double LST   = last.get(Day).getValue();
     153           0 :     LST -= floor(LST); // Extract the fractional day
     154           0 :     LST *= 2*C::pi;// Convert to Raidan
     155             : 
     156           0 :     cout << "LST = " << LST << " " << LST/(2*C::pi) << endl;
     157             :     
     158           0 :     HA = LST - RA;
     159           0 :   }
     160             :   //
     161             :   //---------------------------------------------------------------------
     162             :   // Compute the Parallactic Angle for the give VisBuffer
     163             :   //
     164           0 :   Double getPA(const VisBuffer& vb)
     165             :   {
     166           0 :     return (Double)(vb.feed_pa(getCurrentTimeStamp(vb))(0));
     167             :     // Double pa=0;
     168             :     // Int n=0;
     169             :     // Vector<Float> antPA = vb.feed_pa(getCurrentTimeStamp(vb));
     170             :     // for (uInt i=0;i<antPA.nelements();i++)
     171             :     //   {
     172             :     //  if (!vb.msColumns().antenna().flagRow()(i))
     173             :     //    {pa += antPA(i); n++;break;}
     174             :     //   }
     175             :     // //    pa = sum(antPA)/(antPA.nelements()-1);
     176             :     // if (n==0) 
     177             :     //   throw(AipsError("No unflagged antenna found in getPA()."));
     178             :     // return pa/n;
     179             :   }
     180             :   //
     181             :   //---------------------------------------------------------------------
     182             :   //
     183             :   // Make stokes axis, given the polarization types.
     184             :   //
     185           0 :   void makeStokesAxis(Int npol_p, Vector<String>& polType, Vector<Int>& whichStokes)
     186             :   {
     187             :     //    Vector<String> polType=msc.feed().polarizationType()(0);
     188             :     StokesImageUtil::PolRep polRep_p;
     189           0 :     LogIO os(LogOrigin("Utils", "makeStokesAxis", WHERE));
     190             : 
     191           0 :     if (polType(0)!="X" && polType(0)!="Y" &&
     192           0 :         polType(0)!="R" && polType(0)!="L") 
     193             :       {
     194             :         os << "Warning: Unknown stokes types in feed table: ["
     195           0 :            << polType(0) << ", " << polType(1) << "]" << endl
     196           0 :            << "Results open to question!" << LogIO::POST;
     197             :       }
     198             :   
     199           0 :     if (polType(0)=="X" || polType(0)=="Y") 
     200             :       {
     201           0 :         polRep_p=StokesImageUtil::LINEAR;
     202           0 :         os << "Preferred polarization representation is linear" << LogIO::POST;
     203             :       }
     204             :     else 
     205             :       {
     206           0 :         polRep_p=StokesImageUtil::CIRCULAR;
     207           0 :         os << "Preferred polarization representation is circular" << LogIO::POST;
     208             :       }
     209             : 
     210             :     //    Vector<Int> whichStokes(npol_p);
     211           0 :     switch(npol_p) 
     212             :       {
     213           0 :       case 1:
     214           0 :         whichStokes.resize(1);
     215           0 :         whichStokes(0)=Stokes::I;
     216           0 :         os <<  "Image polarization = Stokes I" << LogIO::POST;
     217           0 :         break;
     218           0 :       case 2:
     219           0 :         whichStokes.resize(2);
     220           0 :         whichStokes(0)=Stokes::I;
     221           0 :         if (polRep_p==StokesImageUtil::LINEAR) 
     222             :           {
     223           0 :             whichStokes(1)=Stokes::Q;
     224           0 :             os <<  "Image polarization = Stokes I,Q" << LogIO::POST;
     225             :           }
     226             :       else 
     227             :         {
     228           0 :           whichStokes(1)=Stokes::V;
     229           0 :           os <<  "Image polarization = Stokes I,V" << LogIO::POST;
     230             :         }
     231           0 :         break;
     232           0 :       case 3:
     233           0 :         whichStokes.resize(3);
     234           0 :         whichStokes(0)=Stokes::I;
     235           0 :         whichStokes(1)=Stokes::Q;
     236           0 :         whichStokes(1)=Stokes::U;
     237           0 :         os <<  "Image polarization = Stokes I,Q,U" << LogIO::POST;
     238           0 :         break;
     239           0 :       case 4:
     240           0 :         whichStokes.resize(4);
     241           0 :         whichStokes(0)=Stokes::I;
     242           0 :         whichStokes(1)=Stokes::Q;
     243           0 :         whichStokes(2)=Stokes::U;
     244           0 :         whichStokes(3)=Stokes::V;
     245           0 :         os <<  "Image polarization = Stokes I,Q,U,V" << LogIO::POST;
     246           0 :         break;
     247           0 :       default:
     248             :         os << LogIO::SEVERE << "Illegal number of Stokes parameters: " << npol_p
     249           0 :            << LogIO::POST;
     250             :       };
     251           0 :   }
     252             :   //
     253             :   //--------------------------------------------------------------------------------------------
     254             :   //  
     255           0 :   Bool isVBNaN(const VisBuffer &vb,String& mesg)
     256             :   {
     257           0 :     IPosition ndx(3,0);
     258           0 :     Int N = vb.nRow();
     259           0 :     for(ndx(2)=0;ndx(2)<N;ndx(2)++)
     260           0 :       if (std::isnan(vb.modelVisCube()(ndx).real()) ||
     261           0 :           std::isnan(vb.modelVisCube()(ndx).imag())
     262             :           )
     263             :         {
     264           0 :           ostringstream os;
     265           0 :           os << ndx(2) << " " << vb.antenna1()(ndx(2)) << "-" << vb.antenna2()(ndx(2)) << " "
     266           0 :              << vb.flagCube()(ndx) << " " << vb.flag()(0,ndx(2)) << " " << vb.weight()(ndx(2));
     267           0 :           mesg = os.str().c_str();
     268           0 :           return true;
     269             :         }
     270           0 :     return false;
     271             :   }
     272             :   //
     273             :   //--------------------------------------------------------------------------------------------
     274             :   //  
     275             :   /////////////////////////////////////////////////////////////////////////////
     276             :   //
     277             :   // IChangeDetector  - an interface class to detect changes in the VisBuffer
     278             :   //     Exact meaning of the "change" is defined in the derived classes
     279             :   //     (e.g. a change in the parallactic angle)
     280             :   
     281             :   // return true if a change occurs somewhere in the buffer
     282           0 :   Bool IChangeDetector::changed(const VisBuffer &vb) const
     283             :   {
     284           0 :      for (Int i=0;i<vb.nRow();++i)
     285           0 :           if (changed(vb,i)) return true;
     286           0 :      return false;
     287             :   }
     288             : 
     289             :   // return true if a change occurs somewhere in the buffer starting from row1
     290             :   // up to row2 (row2=-1 means up to the end of the buffer). The row number,
     291             :   // where the change occurs is returned in the row2 parameter
     292           0 :   Bool IChangeDetector::changedBuffer(const VisBuffer &vb, Int row1, 
     293             :                    Int &row2) const
     294             :   {
     295           0 :     if (row1<0) row1=0;
     296           0 :     Int jrow = row2;
     297           0 :     if (jrow < 0) jrow = vb.nRow()-1;
     298           0 :     DebugAssert(jrow<vb.nRow(),AipsError);
     299             :     
     300             :     // It is not important now to have a separate function for a "block"
     301             :     // operation. Because an appropriate caching is implemented inside
     302             :     // VisBuffer, changed(vb,row) can be called in the
     303             :     // loop without a perfomance penalty. This method returns the 
     304             :     // first row where the change occured rather than the last unchanged 
     305             :     // row as it was for BeamSkyJones::changedBuffer
     306             :       
     307           0 :     for (Int ii=row1;ii<=jrow;++ii)
     308           0 :          if (changed(vb,ii)) {
     309           0 :              row2 = ii;
     310           0 :              return true;
     311             :          }
     312           0 :     return false;
     313             :   }
     314             :   
     315             :   // a virtual destructor to make the compiler happy
     316           0 :   IChangeDetector::~IChangeDetector() {}
     317             :   
     318             :   //
     319             :   /////////////////////////////////////////////////////////////////////////////
     320             : 
     321             :   /////////////////////////////////////////////////////////////////////////////
     322             :   //
     323             :   // ParAngleChangeDetector - a class to detect a change in the parallatic 
     324             :   //                          angle
     325             :   //
     326             :   
     327             :   // set up the tolerance, which determines how much the position angle should
     328             :   // change to report the change by this class
     329           0 :   ParAngleChangeDetector::ParAngleChangeDetector(const Quantity &pa_tolerance) 
     330           0 :                : pa_tolerance_p(pa_tolerance.getValue("rad")),
     331           0 :                     last_pa_p(1000.) {}  // 1000 is >> 2pi, so it is changed
     332             :                                          // after construction
     333             :   
     334             :   // Set the value of the PA tolerance
     335           0 :   void ParAngleChangeDetector::setTolerance(const Quantity &pa_tolerance)
     336             :   {
     337           0 :     pa_tolerance_p = (pa_tolerance.getValue("rad"));
     338           0 :   }
     339             :   // reset to the state which exist just after construction
     340           0 :   void ParAngleChangeDetector::reset()
     341             :   {
     342           0 :       last_pa_p=1000.; // it is >> 2pi, which would force a changed state
     343           0 :   }
     344             :      
     345             :   // return parallactic angle tolerance
     346           0 :   Quantity ParAngleChangeDetector::getParAngleTolerance() const
     347             :   {
     348           0 :       return Quantity(pa_tolerance_p,"rad");
     349             :   }
     350             :   
     351             :   // return true if a change occurs in the given row since the last call 
     352             :   // of update
     353           0 :   Bool ParAngleChangeDetector::changed(const VisBuffer &vb, Int row) const
     354             :   {
     355           0 :      if (row<0) row=0;
     356             :      //     const Double feed1_pa=vb.feed1_pa()[row];
     357           0 :      Double feed1_pa=getPA(vb);
     358           0 :      if (abs(feed1_pa-last_pa_p) > pa_tolerance_p) 
     359             :        {
     360             : //       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;
     361           0 :          return true;
     362             :        }
     363             :      //     const Double feed2_pa=vb.feed2_pa()[row];
     364           0 :      Double feed2_pa = getPA(vb);
     365           0 :      if (abs(feed2_pa-last_pa_p) > pa_tolerance_p) 
     366             :        {
     367             : //       cout << "Utils: " << feed2_pa*57.295 << " " 
     368             : //            << last_pa_p*57.295 << " " 
     369             : //            << abs(feed2_pa-last_pa_p)*57.295 << " " << ttt*57.295 << vb.time()(0)-4.51738e+09 <<endl;
     370           0 :          return true;
     371             :        }
     372           0 :      return false;
     373             :   }
     374             :   
     375             :   // start looking for a change from the given row of the VisBuffer
     376           0 :   void ParAngleChangeDetector::update(const VisBuffer &vb, Int row) 
     377             :   {
     378           0 :      if (row<0) row=0;
     379           0 :      const Double feed1_pa=vb.feed1_pa()[row];
     380           0 :      const Double feed2_pa=vb.feed2_pa()[row];
     381           0 :      if (abs(feed1_pa-feed2_pa)>pa_tolerance_p) {
     382           0 :          LogIO os;
     383           0 :          os<<LogIO::WARN << LogOrigin("ParAngleChangeDetector","update") 
     384             :            <<"The parallactic angle is different at different stations"
     385           0 :            <<LogIO::POST<<LogIO::WARN <<LogOrigin("ParAngleChangeDetector","update")
     386           0 :            <<"The result may be incorrect. Continuing anyway."<<LogIO::POST;
     387             :      }
     388           0 :      last_pa_p=(feed1_pa+feed2_pa)/2.;
     389           0 :   }
     390             : 
     391           0 :   Int getPhaseCenter(MeasurementSet& ms, MDirection& dir0, Int whichField)
     392             :   {
     393           0 :     MSFieldColumns msfc(ms.field());
     394           0 :     if (whichField < 0)
     395             :       {
     396           0 :         MSRange msr(ms);
     397             :         //
     398             :         // An array of shape [2,1,1]!
     399             :         //
     400           0 :         Vector<Int> fieldId;
     401           0 :         fieldId = msr.range(MSS::FIELD_ID).asArrayInt(RecordFieldId(0));
     402             :         
     403           0 :         Array<Double> phaseDir = msfc.phaseDir().getColumn();
     404             :         
     405           0 :         if (fieldId.nelements() <= 0)
     406           0 :           throw(AipsError("getPhaseCenter: No fields found in the selected MS."));
     407             :         
     408           0 :         IPosition ndx0(3,0,0,0),ndx1(3,1,0,0);
     409             :         
     410             :         Double maxRA, maxDec, RA,Dec,RA0,Dec0, dist0;
     411           0 :         maxRA = maxDec=0;
     412           0 :         for(uInt i=0;i<fieldId.nelements();i++)
     413             :           {
     414           0 :             RA   = phaseDir(IPosition(3,0,0,fieldId(i)));
     415           0 :             Dec  = phaseDir(IPosition(3,1,0,fieldId(i)));
     416           0 :             maxRA += RA; maxDec += Dec;
     417             :           }
     418           0 :         RA0=maxRA/fieldId.nelements(); Dec0=maxDec/fieldId.nelements();
     419             :         
     420           0 :         dist0=10000;
     421           0 :         Int field0=0;
     422           0 :         for(uInt i=0;i<fieldId.nelements();i++)
     423             :           {
     424           0 :             RA   = RA0-phaseDir(IPosition(3,0,0,fieldId(i)));
     425           0 :             Dec  = Dec0-phaseDir(IPosition(3,1,0,fieldId(i)));
     426           0 :             Double dist=sqrt(RA*RA + Dec*Dec);
     427           0 :             if (dist < dist0) {field0=fieldId(i);dist0=dist;};
     428             :           }
     429           0 :         dir0=msfc.phaseDirMeasCol()(field0)(IPosition(1,0));
     430             :         //dir0=msfc.phaseDirMeasCol()(6)(IPosition(1,0));
     431           0 :         return field0;
     432             :       }
     433             :     else
     434             :       {
     435           0 :         dir0=msfc.phaseDirMeasCol()(whichField)(IPosition(1,0));
     436           0 :         return whichField;
     437             :       }
     438             :   }
     439             :   //
     440             :   //------------------------------------------------------------------
     441             :   //
     442           0 :   Bool findMaxAbsLattice(const ImageInterface<Float>& lattice,
     443             :                          Float& maxAbs,IPosition& posMaxAbs) 
     444             :   {
     445           0 :     posMaxAbs = IPosition(lattice.shape().nelements(), 0);
     446           0 :     maxAbs=0.0;
     447             : 
     448           0 :     const IPosition tileShape = lattice.niceCursorShape();
     449           0 :     TiledLineStepper ls(lattice.shape(), tileShape, 0);
     450             :     {
     451           0 :       RO_LatticeIterator<Float> li(lattice, ls);
     452           0 :       for(li.reset();!li.atEnd();li++)
     453             :         {
     454           0 :           IPosition posMax=li.position();
     455           0 :           IPosition posMin=li.position();
     456           0 :           Float maxVal=0.0;
     457           0 :           Float minVal=0.0;
     458             :           
     459           0 :           minMax(minVal, maxVal, posMin, posMax, li.cursor());
     460           0 :           if((maxVal)>(maxAbs)) 
     461             :             {
     462           0 :               maxAbs=maxVal;
     463           0 :               posMaxAbs=li.position();
     464           0 :               posMaxAbs(0)=posMax(0);
     465             :             }
     466             :         }
     467             :     }
     468             : 
     469           0 :     return true;
     470             :   };
     471             :   //
     472             :   //------------------------------------------------------------------
     473             :   //
     474           0 :   Bool findMaxAbsLattice(const ImageInterface<Float>& masklat,
     475             :                          const Lattice<Float>& lattice,
     476             :                          Float& maxAbs,IPosition& posMaxAbs, 
     477             :                          Bool flip)
     478             :   {
     479             :     
     480           0 :     AlwaysAssert(masklat.shape()==lattice.shape(), AipsError);
     481             : 
     482           0 :     Array<Float> msk;
     483             :   
     484           0 :     posMaxAbs = IPosition(lattice.shape().nelements(), 0);
     485           0 :     maxAbs=0.0;
     486             :     //maxAbs=-1.0e+10;
     487           0 :     const IPosition tileShape = lattice.niceCursorShape();
     488           0 :     TiledLineStepper ls(lattice.shape(), tileShape, 0);
     489           0 :     TiledLineStepper lsm(masklat.shape(), tileShape, 0);
     490             :     {
     491           0 :       RO_LatticeIterator<Float> li(lattice, ls);
     492           0 :       RO_LatticeIterator<Float> lim(masklat, lsm);
     493           0 :       for(li.reset(),lim.reset();!li.atEnd();li++,lim++) 
     494             :         {
     495           0 :           IPosition posMax=li.position();
     496           0 :           IPosition posMin=li.position();
     497           0 :           Float maxVal=0.0;
     498           0 :           Float minVal=0.0;
     499             :           
     500           0 :           msk = lim.cursor();
     501           0 :           if(flip) msk = (Float)1.0 - msk;
     502             :           
     503             :           //minMaxMasked(minVal, maxVal, posMin, posMax, li.cursor(),lim.cursor());
     504           0 :           minMaxMasked(minVal, maxVal, posMin, posMax, li.cursor(),msk);
     505             :           
     506             :           
     507           0 :           if((maxVal)>(maxAbs)) 
     508             :             {
     509           0 :               maxAbs=maxVal;
     510           0 :               posMaxAbs=li.position();
     511           0 :               posMaxAbs(0)=posMax(0);
     512             :             }
     513             :         }
     514             :     }
     515             : 
     516           0 :     return true;
     517             :   }
     518             :   //
     519             :   //---------------------------------------------------------------
     520             :   //Rotate a complex array using a the given coordinate system and the
     521             :   //angle in radians.  Default interpolation method is "CUBIC".
     522             :   //Axeses corresponding to Linear coordinates in the given
     523             :   //CoordinateSystem object are rotated.  Rotation is done using
     524             :   //ImageRegrid object, about the pixel given by (N+1)/2 where N is
     525             :   //the number of pixels along the axis.
     526             :   //
     527           0 :   void SynthesisUtils::rotateComplexArray(LogIO& logio, Array<Complex>& inArray, 
     528             :                                           CoordinateSystem& inCS,
     529             :                                           Array<Complex>& outArray,
     530             :                                           Double dAngleRad,
     531             :                                           String interpMethod,
     532             :                                           Bool modifyInCS)
     533             :   {
     534             : //     logio << LogOrigin("SynthesisUtils", "rotateComplexArray")
     535             : //        << "Rotating CF using " << interpMethod << " interpolation." 
     536             : //        << LogIO::POST;
     537             :     (void)logio;
     538             :     //
     539             :     // If no rotation required, just copy the inArray to outArray.
     540             :     //
     541             :     //    if (abs(dAngleRad) < 0.1)
     542             :     
     543             :     // IPosition tt;
     544             :     // inCS.list(logio,MDoppler::RADIO,tt,tt);
     545             : 
     546           0 :     if (abs(dAngleRad) == 0.0)
     547             :       {
     548           0 :         outArray.reference(inArray);
     549             :         //      outArray.assign(inArray);
     550           0 :         return;
     551             :       }
     552             :     //
     553             :     // Re-grid inImage onto outImage
     554             :     //
     555           0 :     Vector<Int> pixelAxes;
     556           0 :     Int coordInd = -1;
     557             :     // Extract LINRAR coords from inCS.
     558             :     // Extract axes2
     559             : 
     560           0 :     if(modifyInCS){
     561           0 :       Vector<Double> refPix = inCS.referencePixel();
     562           0 :       refPix(0) = (Int)((inArray.shape()(0))/2.0);
     563           0 :       refPix(1) = (Int)((inArray.shape()(1))/2.0);
     564           0 :       inCS.setReferencePixel(refPix);
     565             :     }
     566             : 
     567           0 :     coordInd = inCS.findCoordinate(Coordinate::LINEAR);
     568           0 :     Bool haveLinear = true;
     569             : 
     570           0 :     if(coordInd == -1){ // no linear coordinate found, look for DIRECTION instead
     571           0 :       coordInd = inCS.findCoordinate(Coordinate::DIRECTION);
     572           0 :       haveLinear = false;
     573             :     }
     574             : 
     575           0 :     pixelAxes=inCS.pixelAxes(coordInd);
     576           0 :     IPosition axes2(pixelAxes);
     577             :     // Set linear transformation matrix in inCS.
     578             : //     CoordinateSystem outCS =
     579             : //       ImageRegrid<Complex>::makeCoordinateSystem (logio, outCS, inCS, axes2);
     580             : 
     581           0 :     CoordinateSystem outCS(inCS);
     582             : 
     583           0 :     Matrix<Double> xf = outCS.coordinate(coordInd).linearTransform();
     584           0 :     Matrix<Double> rotm(2,2);
     585           0 :     rotm(0,0) = cos(dAngleRad); rotm(0,1) = sin(dAngleRad);
     586           0 :     rotm(1,0) = -rotm(0,1);     rotm(1,1) = rotm(0,0);
     587             : 
     588             :     // Double s = sin(dAngleRad);
     589             :     // Double c = cos(dAngleRad);
     590             :     // rotm(0,0) =  c; rotm(0,1) = s;
     591             :     // rotm(1,0) = -s; rotm(1,1) = c;
     592             : 
     593             :     // Create new linear transform matrix
     594           0 :     Matrix<Double> xform(2,2);
     595           0 :     xform(0,0) = rotm(0,0)*xf(0,0)+rotm(0,1)*xf(1,0);
     596           0 :     xform(0,1) = rotm(0,0)*xf(0,1)+rotm(0,1)*xf(1,1);
     597           0 :     xform(1,0) = rotm(1,0)*xf(0,0)+rotm(1,1)*xf(1,0);
     598           0 :     xform(1,1) = rotm(1,0)*xf(0,1)+rotm(1,1)*xf(1,1);
     599             : 
     600           0 :     if(haveLinear){
     601           0 :       LinearCoordinate linCoords = outCS.linearCoordinate(coordInd);
     602           0 :       linCoords.setLinearTransform(xform);
     603           0 :       outCS.replaceCoordinate(linCoords, coordInd);
     604             :     }
     605             :     else{
     606           0 :       DirectionCoordinate dirCoords = outCS.directionCoordinate(coordInd);
     607           0 :       dirCoords.setLinearTransform(xform);
     608           0 :       outCS.replaceCoordinate(dirCoords, coordInd);
     609             :     }      
     610             :     
     611           0 :     outArray.resize(inArray.shape());
     612           0 :     outArray.set(0);
     613             :     //
     614             :     // Make an image out of inArray and inCS --> inImage
     615             :     //
     616             :     //    TempImage<Complex> inImage(inArray.shape(), inCS);
     617             :     {
     618           0 :       TempImage<Float> inImage(inArray.shape(),inCS);
     619           0 :       TempImage<Float> outImage(outArray.shape(), outCS);
     620           0 :       ImageRegrid<Float> ir;
     621           0 :       Interpolate2D::Method interpolationMethod = Interpolate2D::stringToMethod(interpMethod);
     622             :       //------------------------------------------------------------------------
     623             :       // Rotated the real part
     624             :       //
     625           0 :       inImage.copyData(LatticeExpr<Float>(real(ArrayLattice<Complex>(inArray))));
     626           0 :       outImage.set(0.0);
     627             : 
     628           0 :       ir.regrid(outImage, interpolationMethod, axes2, inImage);
     629           0 :       setReal(outArray,outImage.get());
     630             :       //------------------------------------------------------------------------
     631             :       // Rotated the imaginary part
     632             :       //
     633           0 :       inImage.copyData(LatticeExpr<Float>(imag(ArrayLattice<Complex>(inArray))));
     634           0 :       outImage.set(0.0);
     635             : 
     636           0 :       ir.regrid(outImage, interpolationMethod, axes2, inImage);
     637           0 :       setImag(outArray,outImage.get());
     638             :     }
     639             :   }
     640             :   //
     641             :   //---------------------------------------------------------------
     642             :   //
     643           0 :   void SynthesisUtils::findLatticeMax(const ImageInterface<Complex>& lattice,
     644             :                                       Vector<Float>& maxAbs,
     645             :                                       Vector<IPosition>& posMaxAbs) 
     646             :   {
     647           0 :     IPosition lshape(lattice.shape());
     648           0 :     IPosition ndx(lshape);
     649           0 :     Int nPol=lshape(2);
     650           0 :     posMaxAbs.resize(nPol);
     651           0 :     for(Int i=0;i<nPol;i++)
     652           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     653           0 :     maxAbs.resize(nPol);
     654           0 :     ndx=0;
     655             :     
     656           0 :     for(Int s2=0;s2<lshape(2);s2++)
     657           0 :       for(Int s3=0;s3<lshape(3);s3++)
     658             :         {
     659           0 :           ndx(2) = s2; ndx(3)=s3;
     660             :           {
     661             :             //
     662             :             // Locate the pixel with the peak value.  That's the
     663             :             // origin in pixel co-ordinates.
     664             :             //
     665           0 :             maxAbs(s2)=0;
     666           0 :             posMaxAbs(s2) = 0;
     667           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     668           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     669           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     670           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     671             :           }
     672             :         }
     673           0 :   }
     674             :   //
     675             :   //---------------------------------------------------------------
     676             :   //
     677           0 :   void SynthesisUtils::findLatticeMax(const Array<Complex>& lattice,
     678             :                                       Vector<Float>& maxAbs,
     679             :                                       Vector<IPosition>& posMaxAbs) 
     680             :   {
     681           0 :     IPosition lshape(lattice.shape());
     682           0 :     IPosition ndx(lshape);
     683           0 :     Int nPol=lshape(2);
     684           0 :     posMaxAbs.resize(nPol);
     685           0 :     for(Int i=0;i<nPol;i++)
     686           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     687           0 :     maxAbs.resize(nPol);
     688           0 :     ndx=0;
     689             :     
     690           0 :     for(Int s2=0;s2<lshape(2);s2++)
     691           0 :       for(Int s3=0;s3<lshape(3);s3++)
     692             :         {
     693           0 :           ndx(2) = s2; ndx(3)=s3;
     694             :           {
     695             :             //
     696             :             // Locate the pixel with the peak value.  That's the
     697             :             // origin in pixel co-ordinates.
     698             :             //
     699           0 :             maxAbs(s2)=0;
     700           0 :             posMaxAbs(s2) = 0;
     701           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     702           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     703           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     704           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     705             :           }
     706             :         }
     707           0 :   }
     708             :   //
     709             :   //---------------------------------------------------------------
     710             :   //
     711           0 :   void SynthesisUtils::findLatticeMax(const ImageInterface<Float>& lattice,
     712             :                                       Vector<Float>& maxAbs,
     713             :                                       Vector<IPosition>& posMaxAbs) 
     714             :   {
     715           0 :     IPosition lshape(lattice.shape());
     716           0 :     IPosition ndx(lshape);
     717           0 :     Int nPol=lshape(2);
     718           0 :     posMaxAbs.resize(nPol);
     719           0 :     for(Int i=0;i<nPol;i++)
     720           0 :       posMaxAbs(i)=IPosition(lattice.shape().nelements(), 0);
     721           0 :     maxAbs.resize(nPol);
     722           0 :     ndx=0;
     723             :     
     724           0 :     for(Int s2=0;s2<lshape(2);s2++)
     725           0 :       for(Int s3=0;s3<lshape(3);s3++)
     726             :         {
     727           0 :           ndx(2) = s2; ndx(3)=s3;
     728             :           {
     729             :             //
     730             :             // Locate the pixel with the peak value.  That's the
     731             :             // origin in pixel co-ordinates.
     732             :             //
     733           0 :             maxAbs(s2)=0;
     734           0 :             posMaxAbs(s2) = 0;
     735           0 :             for(ndx(1)=0;ndx(1)<lshape(1);ndx(1)++)
     736           0 :               for(ndx(0)=0;ndx(0)<lshape(0);ndx(0)++)
     737           0 :                 if (abs(lattice(ndx)) > maxAbs(s2)) 
     738           0 :                   {posMaxAbs(s2) = ndx;maxAbs(s2)=abs(lattice(ndx));}
     739             :           }
     740             :         }
     741           0 :   }
     742             :   //
     743             :   //---------------------------------------------------------------
     744             :   // Get the value of the named variable from ~/.aipsrc (or ~/.casarc)
     745             :   // or from a env. variable (in this precidence order).
     746             :   //
     747             :   template <class T>
     748           0 :   T SynthesisUtils::getenv(const char *name,const T defaultVal)
     749             :     {
     750           0 :       T val=defaultVal;
     751           0 :       stringstream defaultStr;
     752           0 :       defaultStr << defaultVal;
     753             :       {
     754           0 :         char *valStr=NULL;
     755           0 :         std::string tt(name);
     756             :         unsigned long pos;
     757           0 :         while((pos=tt.find(".")) != tt.npos)
     758           0 :           tt.replace(pos, 1, "_");
     759             : 
     760           0 :         if ((valStr = std::getenv(tt.c_str())) != NULL)
     761             :           {
     762           0 :             stringstream toT2(valStr);
     763           0 :             toT2 >> val;
     764             :           }
     765             :       }
     766             :       // If environment variable was not found (val remained set to the
     767             :       // defaulVal), look in ~/.aipsrc.
     768           0 :       if (val==defaultVal)
     769             :         {
     770           0 :           uint handle = Aipsrc::registerRC(name, defaultStr.str().c_str());    
     771           0 :           String strVal = Aipsrc::get(handle);
     772           0 :           stringstream toT(strVal);
     773           0 :           toT >> val;
     774             :         }
     775           0 :       return val;
     776             :     }
     777             :   template 
     778             :   Int SynthesisUtils::getenv(const char *name, const Int defaultVal);
     779             :   template 
     780             :   Bool SynthesisUtils::getenv(const char *name, const Bool defaultVal);
     781             :   template 
     782             :   Double SynthesisUtils::getenv(const char *name, const Double defaultVal);
     783           0 :   Float SynthesisUtils::libreSpheroidal(Float nu) 
     784             :   {
     785             :     Double top, bot, nuend, delnusq;
     786             :     uInt part;
     787           0 :     if (nu <= 0) return 1.0;
     788             :     else 
     789           0 :       if (nu >= 1.0) 
     790           0 :         return 0.0;
     791             :       else 
     792             :         {
     793           0 :           uInt np = 5;
     794           0 :           uInt nq = 3;
     795           0 :           Matrix<Double> p(np, 2);
     796           0 :           Matrix<Double> q(nq, 2);
     797           0 :           p(0,0) = 8.203343e-2;
     798           0 :           p(1,0) = -3.644705e-1;
     799           0 :           p(2,0) =  6.278660e-1;
     800           0 :           p(3,0) = -5.335581e-1; 
     801           0 :           p(4,0) =  2.312756e-1;
     802           0 :           p(0,1) =  4.028559e-3;
     803           0 :           p(1,1) = -3.697768e-2; 
     804           0 :           p(2,1) = 1.021332e-1;
     805           0 :           p(3,1) = -1.201436e-1;
     806           0 :           p(4,1) = 6.412774e-2;
     807           0 :           q(0,0) = 1.0000000e0;
     808           0 :           q(1,0) = 8.212018e-1;
     809           0 :           q(2,0) = 2.078043e-1;
     810           0 :           q(0,1) = 1.0000000e0;
     811           0 :           q(1,1) = 9.599102e-1;
     812           0 :           q(2,1) = 2.918724e-1;
     813             : 
     814           0 :           part = 0;
     815           0 :           nuend = 0.0;
     816           0 :           if ((nu >= 0.0) && (nu < 0.75)) 
     817             :             {
     818           0 :               part = 0;
     819           0 :               nuend = 0.75;
     820             :             } 
     821           0 :           else if ((nu >= 0.75) && (nu <= 1.00)) 
     822             :             {
     823           0 :               part = 1;
     824           0 :               nuend = 1.0;
     825             :             }
     826             :           
     827           0 :           top = p(0,part);
     828           0 :           delnusq = pow(nu,2.0) - pow(nuend,2.0);
     829           0 :           for (uInt k=1; k<np; k++) 
     830           0 :             top += p(k, part) * pow(delnusq, (Double)k);
     831             : 
     832           0 :           bot = q(0, part);
     833           0 :           for (uInt k=1; k<nq; k++) 
     834           0 :             bot += q(k,part) * pow(delnusq, (Double)k);
     835             :           
     836           0 :           if (bot != 0.0) return (top/bot);
     837           0 :           else            return 0.0;
     838             :         }
     839             :   }
     840             : 
     841           0 :   Double SynthesisUtils::getRefFreq(const VisBuffer& vb)
     842           0 :   {return max(vb.msColumns().spectralWindow().chanFreq().getColumn());}
     843             :   
     844           0 :   void SynthesisUtils::makeFTCoordSys(const CoordinateSystem& coords,
     845             :                                       const Int& convSize,
     846             :                                       const Vector<Double>& ftRef,
     847             :                                       CoordinateSystem& ftCoords)
     848             :   {
     849             :     Int directionIndex;
     850             : 
     851           0 :     ftCoords = coords;
     852           0 :     directionIndex=ftCoords.findCoordinate(Coordinate::DIRECTION);
     853             :     //  The following line follows the (lame) logic that if a
     854             :     //  DIRECTION axis was not found, the coordinate system must be of
     855             :     //  the FT domain already
     856           0 :     if (directionIndex == -1) return;
     857             : 
     858           0 :     DirectionCoordinate dc;//=coords.directionCoordinate(directionIndex);
     859             :     //  AlwaysAssert(directionIndex>=0, AipsError);
     860           0 :     dc=coords.directionCoordinate(directionIndex);
     861           0 :     Vector<Bool> axes(2); axes(0)=axes(1)=true;//axes(2)=true;
     862           0 :     Vector<Int> shape(2,convSize);
     863             : 
     864           0 :     Vector<Double>ref(4);
     865           0 :     ref(0)=ref(1)=ref(2)=ref(3)=0;
     866           0 :     dc.setReferencePixel(ref);
     867           0 :     Coordinate* ftdc=dc.makeFourierCoordinate(axes,shape);
     868           0 :     Vector<Double> refVal;
     869           0 :     refVal=ftdc->referenceValue();
     870             :     //    refVal(0)=refVal(1)=0;
     871             :     //    ftdc->setReferenceValue(refVal);
     872           0 :     ref(0)=ftRef(0);
     873           0 :     ref(1)=ftRef(1);
     874           0 :     ftdc->setReferencePixel(ref);
     875             : 
     876           0 :     ftCoords.replaceCoordinate(*ftdc, directionIndex);
     877             :     // LogIO logio;
     878             :     // IPosition tt;
     879             :     // coords.list(logio,MDoppler::RADIO,tt,tt);
     880             :     // ftCoords.list(logio,MDoppler::RADIO,tt,tt);
     881             : 
     882           0 :     delete ftdc; ftdc=0;
     883             :   }
     884             : 
     885             :   //
     886             :   // Given a list of Spw,MinFreq,MaxFreq,FreqStep (the output product
     887             :   // of MSSelection), expand the list to a list of channel freqs. and
     888             :   // conjugate freqs. per SPW.
     889             :   //
     890         244 :   void SynthesisUtils::expandFreqSelection(const Matrix<Double>& freqSelection, 
     891             :                                            Matrix<Double>& expandedFreqList,
     892             :                                            Matrix<Double>& expandedConjFreqList)
     893             :   {
     894         244 :     Int nSpw = freqSelection.shape()(0), maxSlots=0;
     895             :     Double freq;
     896             : 
     897         522 :     for (Int s=0;s<nSpw;s++)
     898         278 :         maxSlots=max(maxSlots,SynthesisUtils::nint((freqSelection(s,2)-freqSelection(s,1))/freqSelection(s,3))+1);
     899             : 
     900         244 :     expandedFreqList.resize(nSpw,maxSlots);
     901         244 :     expandedConjFreqList.resize(nSpw,maxSlots);
     902             : 
     903         522 :     for (Int s=0,cs=(nSpw-1);s<nSpw;s++,cs--)
     904       83242 :       for (Int i=0,ci=(maxSlots-1);i<maxSlots;i++,ci--)
     905             :         {
     906       82964 :           freq = freqSelection(s,1)+i*freqSelection(s,3);
     907       82964 :           expandedFreqList(s,i) = (freq <= freqSelection(s,2)) ? freq : 0;
     908       82964 :           freq = freqSelection(cs,2) - ci*freqSelection(cs,3);
     909       82964 :           expandedConjFreqList(s,ci) = (freq >= freqSelection(cs,1)) ? freq : 0;
     910             :         }
     911         244 :   }
     912             : 
     913             :   //
     914             :   // The result will be in-place in c1
     915             :   //
     916             :   template
     917             :   void SynthesisUtils::libreConvolver(Array<Complex>& c1, const Array<Complex>& c2);
     918             :   
     919             : 
     920             :   template <class T>
     921           0 :   void SynthesisUtils::libreConvolver(Array<T>& c1, const Array<T>& c2)
     922             :   {
     923           0 :     Array<T> c2tmp;
     924           0 :     c2tmp.assign(c2);
     925             : 
     926           0 :     if (c1.shape().product() > c2tmp.shape().product())
     927           0 :       c2tmp.resize(c1.shape(),true);
     928             :     else
     929           0 :       c1.resize(c2tmp.shape(),true);
     930             : 
     931             : 
     932           0 :     ArrayLattice<T> c2tmp_lat(c2tmp), c1_lat(c1);
     933             : 
     934           0 :     LatticeFFT::cfft2d(c1_lat,false);
     935           0 :     LatticeFFT::cfft2d(c2tmp_lat,false);
     936             :     //cerr << "########## " << c1.shape() << " " << c2tmp.shape() << endl;
     937           0 :     c1 = sqrt(c1);
     938           0 :     c2tmp=sqrt(c2tmp);
     939           0 :     c1 *= conj(c2tmp);
     940           0 :     LatticeFFT::cfft2d(c1_lat);
     941           0 :   }
     942             : 
     943             : 
     944           0 :   Double SynthesisUtils::nearestValue(const Vector<Double>& list, const Double& val, Int& index)
     945             :   {
     946           0 :     Vector<Double> diff = fabs(list - val);
     947           0 :     Double minVal=1e20; 
     948           0 :     Int i=0;
     949             : 
     950           0 :     for (index=0;index<(Int)diff.nelements();index++)
     951           0 :       if (diff[index] < minVal) {minVal=diff[index];i=index;}
     952           0 :     index=i;
     953           0 :     return list(index);
     954             : 
     955             :     // The algorithm below has a N*log(N) cost.
     956             :     //
     957             :     // Bool dummy;
     958             :     // Sort sorter(diff.getStorage(dummy), sizeof(Double));
     959             :     // sorter.sortKey((uInt)0,TpDouble);
     960             :     // Int nch=list.nelements();
     961             :     // Vector<uInt> sortIndx;
     962             :     // sorter.sort(sortIndx, nch);
     963             :     
     964             :     // index=sortIndx(0);
     965             :     // return list(index);
     966             : 
     967             : 
     968             :     // Works only for regularly samplied list
     969             :     //
     970             :     // Int ndx=min(freqValues_p.nelements()-1,max(0,SynthesisUtils::nint((freqVal-freqValues_p[0])/freqValIncr_p)));
     971             :     // return ndx;
     972             :   }
     973             : 
     974             :   template <class T>
     975           0 :   T SynthesisUtils::stdNearestValue(const vector<T>& list, const T& val, Int& index)
     976             :   {
     977           0 :     vector<T> diff=list;
     978           0 :     for (uInt i=0;i<list.size();i++)
     979           0 :       diff[i] = fabs(list[i] - val);
     980             :     
     981           0 :     T minVal=std::numeric_limits<T>::max();//1e20; 
     982           0 :     Int i=0;
     983             : 
     984           0 :     for (index=0;index<(Int)diff.size();index++)
     985           0 :       if (diff[index] < minVal) {minVal=diff[index];i=index;}
     986           0 :     index=i;
     987           0 :     return list[index];
     988             :   }
     989             : 
     990           0 :   CoordinateSystem SynthesisUtils::makeUVCoords(CoordinateSystem& imageCoordSys,
     991             :                                                 IPosition& shape)
     992             :   {
     993           0 :     CoordinateSystem FTCoords = imageCoordSys;
     994             :     
     995           0 :     Int dirIndex=FTCoords.findCoordinate(Coordinate::DIRECTION);
     996           0 :     DirectionCoordinate dc=imageCoordSys.directionCoordinate(dirIndex);
     997           0 :     Vector<Bool> axes(2); axes=true;
     998           0 :     Vector<Int> dirShape(2); dirShape(0)=shape(0);dirShape(1)=shape(1);
     999           0 :     Coordinate* FTdc=dc.makeFourierCoordinate(axes,dirShape);
    1000           0 :     FTCoords.replaceCoordinate(*FTdc,dirIndex);
    1001           0 :     delete FTdc;
    1002             :     
    1003           0 :     return FTCoords;
    1004             :   }
    1005             : 
    1006           0 :   Vector<Int> SynthesisUtils::mapSpwIDToDDID(const VisBuffer& vb, const Int& spwID)
    1007             :   {
    1008           0 :     Vector<Int> ddidList;
    1009           0 :     Int nDDRows = vb.msColumns().dataDescription().nrow();
    1010           0 :     for (Int i=0; i<nDDRows; i++)
    1011             :       {
    1012           0 :         if(vb.msColumns().dataDescription().spectralWindowId().get(i) == spwID)
    1013             :           {
    1014           0 :             Int n=ddidList.nelements();
    1015           0 :             ddidList.resize(n+1,true);
    1016           0 :             ddidList(n) = i;
    1017             :           }
    1018             :       }
    1019           0 :     return ddidList;
    1020             :   }
    1021             : 
    1022           0 :   Vector<Int> SynthesisUtils::mapSpwIDToPolID(const VisBuffer& vb, const Int& spwID)
    1023             :   {
    1024           0 :     Vector<Int> polIDList, ddIDList;
    1025           0 :     ddIDList = SynthesisUtils::mapSpwIDToDDID(vb, spwID);
    1026           0 :     Int n=ddIDList.nelements();
    1027           0 :     polIDList.resize(n);
    1028           0 :     for (Int i=0; i<n; i++)
    1029           0 :       polIDList(i) = vb.msColumns().dataDescription().polarizationId().get(ddIDList(i));
    1030             :       
    1031           0 :     return polIDList;
    1032             :   }
    1033             : 
    1034             : 
    1035             :   // 
    1036             :   // Calcualte the BLC, TRC of the intersection of two rectangles (courtesy U.Rau)
    1037             :   //
    1038           0 :   void SynthesisUtils::calcIntersection(const Int blc1[2], const Int trc1[2], 
    1039             :                                         const Float blc2[2], const Float trc2[2],
    1040             :                                         Float blc[2], Float trc[2])
    1041             :   {
    1042             :     //    cerr << blc1[0] << " " << blc1[1] << " " << trc1[0] << " " << trc1[1] << " " << blc2[0] << " " << blc2[1] << " " << trc2[0] << " " << trc2[1] << endl;
    1043             :     Float dblc, dtrc;
    1044           0 :     for (Int i=0;i<2;i++)
    1045             :       {
    1046           0 :         dblc = blc2[i] - blc1[i];
    1047           0 :         dtrc = trc2[i] - trc1[i];
    1048             : 
    1049           0 :         if ((dblc >= 0) and (dtrc >= 0))
    1050             :           {
    1051           0 :             blc[i] = blc1[i] + dblc;
    1052           0 :             trc[i] = trc2[i] - dtrc;
    1053             :           }
    1054           0 :         else if ((dblc >= 0) and (dtrc < 0))
    1055             :           {
    1056           0 :             blc[i] = blc1[i] + dblc;
    1057           0 :             trc[i] = trc1[i] + dtrc;
    1058             :           }
    1059           0 :         else if ((dblc < 0) and (dtrc >= 0))
    1060             :           {
    1061           0 :             blc[i] = blc2[i] - dblc;
    1062           0 :             trc[i] = trc2[i] - dtrc;
    1063             :           }
    1064             :         else
    1065             :           {
    1066           0 :             blc[i] = blc2[i] - dblc;
    1067           0 :             trc[i] = trc1[i] + dtrc;
    1068             :           }
    1069             :       }
    1070           0 :   }
    1071             :   //
    1072             :   // Check if the two rectangles interset (courtesy U.Rau).
    1073             :   //
    1074           0 :   Bool SynthesisUtils::checkIntersection(const Int blc1[2], const Int trc1[2], const Float blc2[2], const Float trc2[2])
    1075             :   {
    1076             :     // blc1[2] = {xmin1, ymin1}; 
    1077             :     // blc2[2] = {xmin2, ymin2};
    1078             :     // trc1[2] = {xmax1, ymax1};
    1079             :     // trc2[2] = {xmax2, ymax2};
    1080             : 
    1081           0 :     if ((blc1[0] > trc2[0]) || (trc1[0] < blc2[0]) || (blc1[1] > trc2[1]) || (trc1[1] < blc2[1])) 
    1082           0 :       return false;
    1083             :     else
    1084           0 :       return true;
    1085             : // def checkintersect(  xmin1, ymin1, xmax1, ymax1,   xmin2, ymin2, xmax2, ymax2 ):
    1086             : //     if  xmin1 > xmax2  or xmax1 < xmin2 or ymin1 > ymax2 or ymax1 < ymin2 :
    1087             : //         return false
    1088             : //     else : 
    1089             : //         return true
    1090             :   }
    1091             : 
    1092             :   // template<class Iterator>
    1093             :   // Iterator SynthesisUtils::Unique(Iterator first, Iterator last)
    1094             :   // {
    1095             :   //   while (first != last)
    1096             :   //     {
    1097             :   //       Iterator next(first);
    1098             :   //       last = std::remove(++next, last, *first);
    1099             :   //       first = next;
    1100             :   //     }
    1101             :     
    1102             :   //   return last;
    1103             :   // }
    1104             : 
    1105           0 :   String SynthesisUtils::mjdToString(Time& time)
    1106             :   {
    1107           0 :     String tStr;
    1108           0 :     tStr = String::toString(time.year()) + "/" +
    1109           0 :       String::toString(time.month()) + "/" +
    1110           0 :       String::toString(time.dayOfMonth()) + "/" +
    1111           0 :       String::toString(time.hours()) + ":" +
    1112           0 :       String::toString(time.minutes()) + ":";
    1113           0 :     ostringstream fsec;
    1114           0 :     fsec << setprecision(2) << time.dseconds();
    1115           0 :     tStr = tStr + String(fsec.str());
    1116             :     //      String::toString(time.dseconds());
    1117           0 :     return tStr;
    1118             :   }
    1119             : 
    1120             :   template <class Iterator>
    1121           0 :   Iterator SynthesisUtils::Unique(Iterator first, Iterator last)
    1122             :   {
    1123           0 :     while (first != last)
    1124             :       {
    1125           0 :         Iterator next(first);
    1126           0 :         last = std::remove(++next, last, *first);
    1127           0 :         first = next;
    1128             :       }
    1129             :     
    1130           0 :     return last;
    1131             :   }
    1132             : 
    1133           0 :   void SynthesisUtils::showCS(const CoordinateSystem& cs, ostream &os, const String& msg)
    1134             :   {
    1135           0 :     LogIO log_l(LogOrigin("SynthesisUtils","showCS"));
    1136           0 :     IPosition dummy;
    1137           0 :     Vector<String> csList;
    1138           0 :     if (msg!="")
    1139           0 :       os << "CoordSys: ";
    1140           0 :     csList = cs.list(log_l,MDoppler::RADIO,dummy,dummy);
    1141           0 :     os << csList << endl;
    1142           0 :   }
    1143             : 
    1144           0 :   const casacore::Array<Complex> SynthesisUtils::getCFPixels(const casacore::String& Dir,
    1145             :                                                              const casacore::String& fileName)
    1146             :   {
    1147             :     try
    1148             :       {
    1149           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1150           0 :         return thisCF.get();
    1151             :       }
    1152           0 :     catch (AipsError &x)
    1153             :       {
    1154           0 :         LogIO log_l(LogOrigin("SynthesisUtils","getCFPixels"));
    1155           0 :         log_l << x.getMesg() << LogIO::EXCEPTION;
    1156             :       }
    1157           0 :     return casacore::Array<Complex>(); // Just to keep the complier happy.  Program control should never get here.
    1158             :   }
    1159             :   
    1160           0 :   casacore::TableRecord SynthesisUtils::getCFParams(const casacore::String& Dir,
    1161             :                                                     const casacore::String& fileName,
    1162             :                                                     casacore::Array<Complex>& pixelBuffer,
    1163             :                                                     casacore::CoordinateSystem& coordSys, 
    1164             :                                                     casacore::Double& sampling,
    1165             :                                                     casacore::Double& paVal,
    1166             :                                                     casacore::Int& xSupport, casacore::Int& ySupport,
    1167             :                                                     casacore::Double& fVal, casacore::Double& wVal, casacore::Int& mVal,
    1168             :                                                     casacore::Double& conjFreq, casacore::Int& conjPoln,
    1169             :                                                     casacore::Bool loadPixels,
    1170             :                                                     casacore::Bool loadMiscInfo)
    1171             :   {
    1172             :     try
    1173             :       {
    1174           0 :         casacore::PagedImage<casacore::Complex> thisCF(Dir+'/'+fileName);
    1175           0 :         if (loadPixels) pixelBuffer.assign(thisCF.get());
    1176           0 :         casacore::TableRecord miscinfo;
    1177           0 :         if (loadMiscInfo)
    1178             :           {
    1179           0 :             miscinfo= thisCF.miscInfo();
    1180             : 
    1181           0 :             miscinfo.get("ParallacticAngle", paVal);
    1182           0 :             miscinfo.get("MuellerElement", mVal);
    1183           0 :             miscinfo.get("WValue", wVal);
    1184           0 :             miscinfo.get("Xsupport", xSupport);
    1185           0 :             miscinfo.get("Ysupport", ySupport);
    1186           0 :             miscinfo.get("Sampling", sampling);
    1187           0 :             miscinfo.get("ConjFreq", conjFreq);
    1188           0 :             miscinfo.get("ConjPoln", conjPoln);
    1189           0 :             casacore::Int index= thisCF.coordinates().findCoordinate(casacore::Coordinate::SPECTRAL);
    1190           0 :             coordSys = thisCF.coordinates();
    1191           0 :             casacore::SpectralCoordinate spCS = coordSys.spectralCoordinate(index);
    1192           0 :             fVal=static_cast<Float>(spCS.referenceValue()(0));
    1193             :           }
    1194           0 :         return miscinfo;
    1195             :       }
    1196           0 :     catch(AipsError& x)
    1197             :       {
    1198           0 :         throw(AipsError(String("Error in SynthesisUtils::getCFParams(): ")
    1199           0 :                                       +x.getMesg()));
    1200             :       }
    1201             :   };
    1202             : 
    1203             : 
    1204           0 :   void SynthesisUtils::rotate2(const double& actualPA, CFCell& baseCFC, CFCell& cfc, const double& rotAngleIncr)
    1205             :     {
    1206           0 :       LogIO log_l(LogOrigin("SynthesisUtils", "rotate2"));
    1207             : 
    1208             :       // // If the A-Term is a No-Op, the resulting CF is rotationally
    1209             :       // // symmetric.
    1210             :       // if (isNoOp()) return;
    1211             : 
    1212             :       (void)baseCFC;
    1213             : 
    1214             :       //double actualPA = getPA(vb);
    1215           0 :       double currentCFPA = cfc.pa_p.getValue("rad");
    1216             :       //Double baseCFCPA=baseCFC.pa_p.getValue("rad");
    1217             : 
    1218           0 :       double dPA = currentCFPA-actualPA;
    1219             : 
    1220           0 :       if (fabs(dPA) > fabs(rotAngleIncr))
    1221             :         {
    1222           0 :           casacore::Array<TT> inData;
    1223             :           //inData.assign(*baseCFC.getStorage());
    1224             :           //dPA = baseCFCPA-actualPA;
    1225           0 :           dPA = currentCFPA-actualPA;
    1226           0 :           inData.assign(*cfc.getStorage());
    1227             :           try
    1228             :             {
    1229           0 :               SynthesisUtils::rotateComplexArray(log_l, inData, cfc.coordSys_p,
    1230           0 :                                                  *cfc.getStorage(),
    1231             :                                                  dPA);//,"LINEAR");
    1232             :               // currentCFPA-actualPA);//,"LINEAR");
    1233             :             }
    1234           0 :           catch (AipsError &x)
    1235             :             {
    1236           0 :               log_l << x.getMesg() << LogIO::EXCEPTION;
    1237             :             }
    1238           0 :           cfc.pa_p=Quantity(actualPA, "rad");
    1239             :         }
    1240           0 :     };
    1241             : 
    1242             : 
    1243             :   template
    1244             :   std::vector<Double>::iterator SynthesisUtils::Unique(std::vector<Double>::iterator first, std::vector<Double>::iterator last);
    1245             :   template
    1246             :   std::vector<Float>::iterator SynthesisUtils::Unique(std::vector<Float>::iterator first, std::vector<Float>::iterator last);
    1247             :   template
    1248             :   std::vector<Int>::iterator SynthesisUtils::Unique(std::vector<Int>::iterator first, std::vector<Int>::iterator last);
    1249             : 
    1250             :   template 
    1251             :   Double SynthesisUtils::stdNearestValue(const vector<Double>& list, const Double& val, Int& index);
    1252             :   template 
    1253             :   Float SynthesisUtils::stdNearestValue(const vector<Float>& list, const Float& val, Int& index);
    1254             :   template 
    1255             :   Int SynthesisUtils::stdNearestValue(const vector<Int>& list, const Int& val, Int& index);
    1256             : 
    1257             : 
    1258             : using namespace casacore;
    1259             : } // namespace casa

Generated by: LCOV version 1.16