LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - EJones.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 354 0.0 %
Date: 2024-10-04 16:51:10 Functions: 0 30 0.0 %

          Line data    Source code
       1             : //# StandardVisCal.cc: Implementation of Standard VisCal types
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : 
      27             : #include <synthesis/MeasurementComponents/EJones.h>
      28             : 
      29             : #include <synthesis/MeasurementComponents/MSMetaInfoForCal.h>
      30             : 
      31             : #include <msvis/MSVis/VisBuffer.h>
      32             : #include <msvis/MSVis/VisBuffAccumulator.h>
      33             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      34             : #include <synthesis/MeasurementEquations/VisEquation.h>
      35             : 
      36             : #include <casacore/tables/Tables/Table.h>
      37             : #include <casacore/tables/Tables/TableIter.h>
      38             : #include <casacore/tables/Tables/TableUtil.h>
      39             : #include <casacore/tables/TaQL/ExprNode.h>
      40             : 
      41             : #include <casacore/casa/Arrays/ArrayMath.h>
      42             : #include <casacore/casa/BasicSL/String.h>
      43             : #include <casacore/casa/Utilities/Assert.h>
      44             : #include <casacore/casa/Exceptions/Error.h>
      45             : #include <casacore/casa/OS/Memory.h>
      46             : #include <casacore/casa/System/Aipsrc.h>
      47             : #include <casacore/scimath/Functionals/ScalarSampledFunctional.h>
      48             : #include <casacore/scimath/Functionals/Interpolate1D.h>
      49             : #include <casacore/scimath/Mathematics/Combinatorics.h>
      50             : 
      51             : #include <sstream>
      52             : 
      53             : #include <casacore/casa/Logging/LogMessage.h>
      54             : #include <casacore/casa/Logging/LogSink.h>
      55             : 
      56             : using namespace casacore;
      57             : namespace casa { //# NAMESPACE CASA - BEGIN
      58             : 
      59             : 
      60             : // **********************************************************
      61             : //  EGainCurve
      62             : //
      63             : 
      64           0 : EGainCurve::EGainCurve(VisSet& vs) :
      65             :   VisCal(vs), 
      66             :   VisMueller(vs),
      67             :   SolvableVisJones(vs),
      68           0 :   za_(),
      69           0 :   eff_(nSpw(),1.0)
      70             : {
      71           0 :   if (prtlev()>2) cout << "EGainCurve::EGainCurve(vs)" << endl;
      72           0 : }
      73             : 
      74           0 : EGainCurve::EGainCurve(String msname,Int MSnAnt,Int MSnSpw) :
      75             :   VisCal(msname,MSnAnt,MSnSpw), 
      76             :   VisMueller(msname,MSnAnt,MSnSpw),
      77             :   SolvableVisJones(msname,MSnAnt,MSnSpw),
      78           0 :   za_(),
      79           0 :   eff_(nSpw(),1.0)
      80             : {
      81           0 :   if (prtlev()>2) cout << "EGainCurve::EGainCurve(msname,MSnAnt,MSnSpw)" << endl;
      82           0 : }
      83             : 
      84           0 : EGainCurve::EGainCurve(const MSMetaInfoForCal& msmc) :
      85             :   VisCal(msmc), 
      86             :   VisMueller(msmc),
      87             :   SolvableVisJones(msmc),
      88           0 :   za_(),
      89           0 :   eff_(nSpw(),1.0)
      90             : {
      91           0 :   if (prtlev()>2) cout << "EGainCurve::EGainCurve(msmc)" << endl;
      92           0 : }
      93             : 
      94             : 
      95             : 
      96           0 : EGainCurve::~EGainCurve() {
      97           0 :   if (prtlev()>2) cout << "EGainCurve::~EGainCurve()" << endl;
      98           0 : }
      99             : 
     100           0 : void EGainCurve::setApply(const Record& applypar) {
     101             : 
     102           0 :   LogMessage message;
     103             : 
     104             :   // Extract user's table name
     105           0 :   String usertab("");
     106           0 :   if (applypar.isDefined("table")) {
     107           0 :     usertab=applypar.asString("table");
     108             :   }
     109             : 
     110           0 :   if (usertab=="") {
     111             : 
     112           0 :     { ostringstream o;
     113           0 :       o<< "Invoking gaincurve application without a caltable (e.g., " << endl
     114           0 :        << " via gaincurve=T in calibration tasks) will soon be disabled." << endl
     115           0 :        << " Please begin using gencal to generate a gaincurve caltable, " << endl
     116           0 :        << " and then supply that table in the standard manner." << endl;
     117           0 :       message.message(o);
     118           0 :       message.priority(LogMessage::WARN);
     119           0 :       logSink().post(message);
     120           0 :     }
     121             : 
     122           0 :     String tempname="temporary.gaincurve";
     123             : 
     124             :     // Generate automatically via specify mechanism
     125           0 :     Record specpar;
     126           0 :     specpar.define("caltable",tempname);
     127           0 :     specpar.define("caltype","gc");
     128           0 :     setSpecify(specpar);
     129           0 :     specify(specpar);
     130           0 :     storeNCT();
     131           0 :     delete ct_; ct_=NULL;  // so we can form it in the standard way...
     132             : 
     133             :     // Load the caltable for standard apply
     134           0 :     Record newapplypar=applypar;
     135           0 :     newapplypar.define("table",tempname);
     136           0 :     SolvableVisCal::setApply(newapplypar);
     137             : 
     138             :     // Delete the temporary gaincurve disk table (in-mem copy still ok)
     139           0 :     if (calTableName()==tempname &&
     140           0 :         TableUtil::canDeleteTable(calTableName()) ) {
     141           0 :       TableUtil::deleteTable(calTableName());
     142             :     }
     143             : 
     144             :     // Revise name that will appear in log messages, etc.
     145           0 :     calTableName()="<"+tempname+">";
     146             : 
     147           0 :   }
     148             :   else
     149             :     // Standard apply via table
     150           0 :     SolvableVisCal::setApply(applypar);
     151             : 
     152             :   // Resize za()
     153           0 :   za().resize(nAnt());
     154             : 
     155           0 : }
     156             : 
     157           0 : void EGainCurve::setCallib(const Record& applypar,const MeasurementSet& selms) {
     158             : 
     159           0 :   LogMessage message;
     160             : 
     161             :   // Standard setCallib
     162           0 :   SolvableVisCal::setCallib(applypar,selms);
     163             : 
     164             :   // Resize za()
     165           0 :   za().resize(nAnt());
     166             : 
     167           0 : }
     168             : 
     169           0 : void EGainCurve::setSpecify(const Record& specify) {
     170             : 
     171             :   // Get some information from the MS to help us find
     172             :   //  the right gain curves
     173             : 
     174           0 :   MeasurementSet ms(msName());
     175           0 :   MSColumns mscol(ms);
     176             : 
     177             :   // The antenna names
     178           0 :   const MSAntennaColumns& antcol(mscol.antenna());
     179           0 :   antnames_ = antcol.name().getColumn();
     180             : 
     181             :   // Observation info
     182           0 :   const MSObservationColumns& obscol(mscol.observation());
     183             : 
     184           0 :   String telescope(obscol.telescopeName()(0));
     185             : 
     186             :   // Parse infile
     187           0 :   if (specify.isDefined("infile"))
     188           0 :     gainCurveSrc_=specify.asString("infile");
     189             : 
     190             :   // Use external file, if specified
     191           0 :   if (gainCurveSrc_!="") {
     192           0 :     if ( !Table::isReadable(gainCurveSrc_) )
     193           0 :       throw(AipsError("Specified gain curve table: "+gainCurveSrc_+" is unreadable or absent."));
     194             : 
     195             :     // Specified table exists, so we'll try to use it
     196             :     logSink() << "Using user-specified gaincurve table: " 
     197           0 :               << gainCurveSrc_ 
     198           0 :               << LogIO::POST;
     199             : 
     200             :   } 
     201             :   // If VLA, use standard file
     202           0 :   else if (telescope.contains("VLA")) {
     203           0 :     gainCurveSrc_=Aipsrc::aipsRoot() + "/data/nrao/VLA/GainCurves";
     204           0 :     if ( !Table::isReadable(gainCurveSrc_) )
     205           0 :       throw(AipsError("Standard VLA gain curve table "+gainCurveSrc_+" is unreadable or absent."));
     206             : 
     207             :     // VLA gaincurve exists, so we'll try to use it
     208             :     logSink() << "Using standard VLA gaincurve table from the data repository: " 
     209           0 :               << gainCurveSrc_ 
     210           0 :               << LogIO::POST;
     211             : 
     212             :     // Strip any ea/va baloney from the MS antenna names so 
     213             :     //  they match the integers (as strings) in the GainCurves table
     214           0 :     for (uInt iant=0;iant<antnames_.nelements();++iant) {
     215           0 :       antnames_(iant)=antnames_(iant).from(RXint);
     216           0 :       if (antnames_(iant).find('0')==0)
     217           0 :         antnames_(iant)=antnames_(iant).after('0');
     218             :     }
     219             :   }
     220             :   // Unspecified and not VLA: gain curve unsupported...
     221             :   else {
     222           0 :     throw(AipsError("Automatic gain curve not supported for "+telescope));
     223             :   }
     224             : 
     225           0 :   Vector<Double> timerange(obscol.timeRange()(0));
     226           0 :   obstime_ = timerange(0);
     227             : 
     228           0 :   const MSSpWindowColumns& spwcol(mscol.spectralWindow());
     229           0 :   spwfreqs_.resize(nSpw());
     230           0 :   spwfreqs_.set(0.0);
     231           0 :   spwbands_.resize(nSpw());
     232           0 :   spwbands_.set(String("?"));
     233           0 :   for (Int ispw=0;ispw<nSpw();++ispw) {
     234           0 :     Vector<Double> chanfreqs=spwcol.chanFreq()(ispw);
     235           0 :     spwfreqs_(ispw)=chanfreqs(chanfreqs.nelements()/2);
     236           0 :     String bname=spwcol.name()(ispw);
     237           0 :     if (bname.contains("EVLA"))
     238           0 :       spwbands_(ispw)=String(bname.before("#")).after("EVLA_");
     239           0 :   }
     240             :   //  cout << "spwfreqs_ = " << spwfreqs_ << endl;
     241             :   //  cout << "spwbands_ = " << spwbands_ << endl;
     242             : 
     243             :   // Neither applying nor solving in specify context
     244           0 :   setSolved(false);
     245           0 :   setApplied(false);
     246             : 
     247             :   // Collect Cal table parameters
     248           0 :   if (specify.isDefined("caltable")) {
     249           0 :     calTableName()=specify.asString("caltable");
     250             : 
     251           0 :     if (Table::isReadable(calTableName()))
     252             :       logSink() << "FYI: We are going to overwrite an existing CalTable: "
     253           0 :                 << calTableName()
     254           0 :                 << LogIO::POST;
     255             :   }
     256             : 
     257             :   // Create a new caltable to fill
     258           0 :   createMemCalTable();
     259             : 
     260             :   // Setup shape of solveAllRPar
     261           0 :   initSolvePar();
     262             : 
     263             :   /* From AIPS TYAPL (2012Sep14):
     264             : 
     265             :       DATA TF / 1.0,  1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,
     266             :      *    1.9,  2.0,  2.0,  2.3,  2.7,  3.0,  3.5,  3.7,  4.0,  4.0,
     267             :      *    5.0,  6.0,  7.0,  8.0,  8.0, 12.0, 12.0, 13.0, 14.0, 15.0,
     268             :      *   16.0, 17.0, 18.0, 19.0, 24.0, 26.0, 26.5, 28.0, 33.0, 38.0,
     269             :      *   40.0, 43.0, 48.0/
     270             : C                                       Rick Perley efficiencies
     271             :       DATA TE /0.45, 0.48, 0.48, 0.45, 0.46, 0.45, 0.43, 0.44, 0.44,
     272             :      *   0.49, 0.48, 0.52, 0.52, 0.51, 0.53, 0.55, 0.53, 0.54, 0.55,
     273             :      *   0.54, 0.56, 0.62, 0.64, 0.60, 0.60, 0.65, 0.65, 0.62, 0.58,
     274             :      *   0.59, 0.60, 0.60, 0.57, 0.52, 0.48, 0.50, 0.49, 0.42, 0.35,
     275             :      *   0.29, 0.28, 0.26/
     276             :   */
     277             : 
     278             : 
     279           0 :   Double Efffrq[] = {1.0,  1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,
     280             :                      1.9,  2.0,  2.0+1e-9,  2.3,  2.7,  3.0,  3.5,  3.7,  4.0,  4.0+1e-9,
     281             :                      5.0,  6.0,  7.0,  8.0,  8.0+1e-9, 12.0, 12.0+1e-9, 13.0, 14.0, 15.0,
     282             :                      16.0, 17.0, 18.0, 19.0, 24.0, 26.0, 26.5, 28.0, 33.0, 38.0,
     283             :                      40.0, 43.0, 48.0};
     284           0 :   Double Eff[] = {0.45, 0.48, 0.48, 0.45, 0.46, 0.45, 0.43, 0.44, 0.44,
     285             :                   0.49, 0.48, 0.52, 0.52, 0.51, 0.53, 0.55, 0.53, 0.54, 0.55,
     286             :                   0.54, 0.56, 0.62, 0.64, 0.60, 0.60, 0.65, 0.65, 0.62, 0.58,
     287             :                   0.59, 0.60, 0.60, 0.57, 0.52, 0.48, 0.50, 0.49, 0.42, 0.35,
     288             :                   0.29, 0.28, 0.26};
     289             : 
     290           0 :   Vector<Double> f,ef;
     291             : 
     292           0 :   f.takeStorage(IPosition(1,42),Efffrq);
     293           0 :   ef.takeStorage(IPosition(1,42),Eff);
     294             : 
     295             :   // Fractional -> K/Jy (for 25m)
     296           0 :   ef/=Double(5.622);
     297             : 
     298             :   // convert to voltagey units
     299           0 :   ef=sqrt(ef);
     300             : 
     301           0 :   ScalarSampledFunctional<Double> fx(f);
     302           0 :   ScalarSampledFunctional<Double> fy(ef);
     303           0 :   Interpolate1D<Double,Double> eff(fx,fy);
     304           0 :   eff.setMethod(Interpolate1D<Double,Double>::linear);
     305           0 :   for (Int ispw=0;ispw<nSpw();++ispw) {
     306           0 :     Double fghz=spwfreqs_(ispw)/1.e9;
     307           0 :     eff_(ispw)=eff(fghz);
     308             :   }
     309             : 
     310             :   //  cout << "spwfreqs_ = " << spwfreqs_ << endl;
     311             :   //  cout << "eff_      = " << eff_ << endl;
     312             : 
     313             : 
     314           0 : }
     315             : 
     316           0 : void EGainCurve::specify(const Record& specify) {
     317             : 
     318           0 :   LogMessage message;
     319             : 
     320           0 :   Bool doeff(false);
     321           0 :   Bool dogc(false);
     322           0 :   if (specify.isDefined("caltype")) {
     323           0 :     String caltype=specify.asString("caltype");
     324             :     //cout << "caltype=" << caltype  << endl;
     325           0 :     doeff = (caltype.contains("eff"));
     326           0 :     dogc = (caltype.contains("gc"));
     327           0 :   }
     328             : 
     329             :   // Open raw gain curve source table
     330           0 :   Table rawgaintab(gainCurveSrc_);
     331             : 
     332           0 :   logSink() << "Using " << Path(gainCurveSrc_).absoluteName()
     333           0 :             << " nrow=" << rawgaintab.nrow() << LogIO::POST;
     334             : 
     335             :   // Select on Time
     336           0 :   Table timegaintab = rawgaintab(rawgaintab.col("BTIME") <= obstime_
     337           0 :                                  && rawgaintab.col("ETIME") > obstime_);
     338             : 
     339             :   // ...for each spw:
     340           0 :   Vector<Bool> spwFound_(nSpw(),false);  
     341           0 :   spwFound_.set(false);  // will set true when we find them
     342             : 
     343           0 :   for (Int ispw=0; ispw<nSpw(); ispw++) {
     344             : 
     345           0 :     currSpw()=ispw;
     346             : 
     347             : 
     348           0 :     if (dogc) {
     349             : 
     350             :       // Select on freq:
     351           0 :       Table freqgaintab=timegaintab(timegaintab.col("BANDNAME")==spwbands_(ispw));
     352             : 
     353             :       // If we fail to select anything by bandname, try to select by freq
     354             :       //   (this can get wrong answer near band edges if center freq "out-of-band")
     355           0 :       if (freqgaintab.nrow()==0)
     356           0 :         freqgaintab = timegaintab(timegaintab.col("BFREQ") <= spwfreqs_(ispw)
     357           0 :                                   && timegaintab.col("EFREQ") > spwfreqs_(ispw));
     358             : 
     359           0 :       if (freqgaintab.nrow() > 0) {
     360             : 
     361             :         /*      
     362             :         { logSink() // << "EGainCurve::specify:"
     363             :                     << "  Found the following gain curve coefficient data" << endl
     364             :                     << "  for spectral window = "  << ispw << " (band=" << spwbands_(ispw) << ", center freq="
     365             :                     << spwfreqs_(ispw) << "):" << LogIO::POST;
     366             :         }
     367             :         */
     368             :         // Find nominal gain curve
     369             :         //  Nominal antenna is named "0" (this is a VLA convention)
     370           0 :         Matrix<Float> nomgain(4,2,0.0);
     371             :         {
     372           0 :           Table nomgaintab = freqgaintab(freqgaintab.col("ANTENNA")=="0");
     373           0 :           if (nomgaintab.nrow() > 0) {
     374           0 :             ArrayColumn<Float> gain(nomgaintab,"GAIN");
     375           0 :             nomgain=gain(0);
     376           0 :           } else {
     377             :             // nominal gain is unity
     378           0 :             nomgain(0,0)=1.0;
     379           0 :             nomgain(0,1)=1.0;
     380             :           }
     381           0 :         }
     382             : 
     383           0 :         solveAllParOK()=true;
     384             :         
     385           0 :         ArrayIterator<Float> piter(solveAllRPar(),1);
     386             :         
     387           0 :         for (Int iant=0; iant<nAnt(); iant++,piter.next()) {
     388             :           
     389             :           // Select antenna by name
     390           0 :           Table antgaintab = freqgaintab(freqgaintab.col("ANTENNA")==antnames_(iant));
     391           0 :           if (antgaintab.nrow() > 0) {
     392           0 :             ArrayColumn<Float> gain(antgaintab,"GAIN");
     393           0 :             piter.array().nonDegenerate().reform(gain(0).shape())=gain(0);
     394           0 :           } else {
     395           0 :             piter.array().nonDegenerate().reform(nomgain.shape())=nomgain;
     396             :           }
     397             : 
     398             :           /*
     399             :           { 
     400             :             logSink() << "   Antenna=" << antnames_(iant) << ": "
     401             :                       << piter.array().nonDegenerate() << LogIO::POST;
     402             :           }
     403             :           */
     404           0 :         }
     405             :         
     406           0 :         spwFound_(currSpw())=true;
     407             :         
     408           0 :       }
     409             :       else {
     410             :         logSink() << "Could not find gain curve data for Spw="
     411           0 :                   << ispw << " (reffreq=" << spwfreqs_(ispw)/1.0e9 << " GHz) "
     412           0 :                   << "Using flat unit gaincurve." << LogIO::POST;
     413             :         // We used to punt here
     414             :         //throw(AipsError(o.str()));
     415             :         
     416             :         // Use unity
     417           0 :         solveAllParOK()=true;
     418           0 :         solveAllRPar().set(0.0);
     419           0 :         solveAllRPar()(Slice(0,1,1),Slice(),Slice()).set(1.0);
     420           0 :         solveAllRPar()(Slice(4,1,1),Slice(),Slice()).set(1.0);
     421             :         
     422             :       }
     423           0 :     }
     424             :     else {
     425             :       // Use unity, flat
     426           0 :       solveAllParOK()=true;
     427           0 :       solveAllRPar().set(0.0);
     428           0 :       solveAllRPar()(Slice(0,1,1),Slice(),Slice()).set(1.0);
     429           0 :       solveAllRPar()(Slice(4,1,1),Slice(),Slice()).set(1.0);
     430           0 :       spwFound_(currSpw())=true;
     431             :     }
     432             : 
     433             :     // Scale by efficiency factor, if requested
     434           0 :     if (doeff) {
     435           0 :       solveAllRPar()*=Float(eff_(ispw));
     436             :     }
     437             : 
     438             :     // Record in the memory caltable
     439           0 :     keepNCT();
     440             : 
     441             :   } // ispw
     442             : 
     443           0 :   if (allEQ(spwFound_,false))
     444           0 :     throw(AipsError("Found no gaincurve data for any spw."));
     445             : 
     446             : 
     447             :   // Reset currSpw()
     448           0 :   currSpw()=0;
     449             : 
     450             :   // Resize za()
     451           0 :   za().resize(nAnt());
     452             : 
     453           0 : }
     454             : 
     455             : 
     456           0 : void EGainCurve::guessPar(VisBuffer&) {
     457             : 
     458           0 :   throw(AipsError("Spurious attempt to guess EGainCurve for solving!"));
     459             : 
     460             : }
     461             : 
     462             : // EGainCurve needs to zenith angle (old VB version)
     463           0 : void EGainCurve::syncMeta(const VisBuffer& vb) {
     464             : 
     465             :   // Call parent (sets currTime())
     466           0 :   SolvableVisJones::syncMeta(vb);
     467             : 
     468             :   // Current time's zenith angle...  (in _degrees_)
     469           0 :   za().resize(nAnt());
     470           0 :   Vector<MDirection> antazel(vb.azel(currTime()));
     471           0 :   Double* a=za().data();
     472           0 :   for (Int iant=0;iant<nAnt();++iant,++a) 
     473           0 :     (*a)=90.0 - antazel(iant).getAngle().getValue()(1)*180.0/C::pi;
     474             : 
     475           0 : }
     476             : 
     477             : // EGainCurve needs to zenith angle  (VB2 version) 
     478           0 : void EGainCurve::syncMeta2(const vi::VisBuffer2& vb) {
     479             : 
     480             :   // Call parent (sets currTime())
     481           0 :   SolvableVisJones::syncMeta2(vb);
     482             : 
     483             :   // Current time's zenith angle...(in _degrees_)
     484           0 :   za().resize(nAnt());
     485           0 :   Vector<MDirection> antazel(vb.azel(currTime()));
     486           0 :   Double* a=za().data();
     487           0 :   for (Int iant=0;iant<nAnt();++iant,++a) 
     488           0 :     (*a)=90.0 - antazel(iant).getAngle().getValue()(1)*180.0/C::pi;
     489             : 
     490           0 : }
     491             : 
     492             : 
     493             : 
     494           0 : void EGainCurve::calcPar() {
     495             : 
     496           0 :   if (prtlev()>6) cout << "      EGainCurve::calcPar()" << endl;
     497             : 
     498             :   // Could do the following in setApply, so it only happens once?
     499           0 :   if (ci_ || cpp_)
     500           0 :     SolvableVisCal::calcPar();
     501             :   else
     502           0 :     throw(AipsError("Problem in EGainCurve::calcPar()"));
     503             : 
     504             :   // Pars now valid, matrices not yet
     505           0 :   validateP();
     506           0 :   invalidateJ();
     507             : 
     508           0 : }
     509             : 
     510           0 : void EGainCurve::calcAllJones() {
     511             : 
     512           0 :   if (prtlev()>6) cout << "       EGainCurve::calcAllJones()" << endl;
     513             : 
     514             :   // Nominally no gain curve effect
     515           0 :   currJElem()=Complex(1.0);
     516           0 :   currJElemOK()=false;
     517             : 
     518             :   /*
     519             :   cout << "currSpw() = " << currSpw() << endl;
     520             :   cout << "   spwMap() = " << spwMap() << endl;
     521             :   cout << "   currRPar().shape() = " << currRPar().shape() << endl;
     522             :   cout << "   currRPar() = " << currRPar() << endl;
     523             :   */
     524             : 
     525           0 :   Complex* J=currJElem().data();
     526           0 :   Bool*    JOk=currJElemOK().data();
     527           0 :   Float*  c=currRPar().data();
     528           0 :   Double* a=za().data();
     529             : 
     530             :   Double loss, ang;
     531           0 :   for (Int iant=0; iant<nAnt(); ++iant,++a)
     532           0 :     for (Int ipol=0;ipol<2;++ipol,++J,++JOk) {
     533           0 :       loss=Double(*c);
     534           0 :       ++c;
     535           0 :       ang=1.0;
     536           0 :       for (Int ipar=1;ipar<4;++ipar,++c) {
     537           0 :         ang*=(*a);
     538           0 :         loss+=((*c)*ang);
     539             :       }
     540           0 :       (*J) = Complex(loss);
     541           0 :       (*JOk) = true;
     542             :     }
     543             :   
     544           0 : }
     545             : 
     546             : 
     547           0 : EPowerCurve::EPowerCurve(VisSet& vs) :
     548             :   VisCal(vs), 
     549             :   VisMueller(vs),
     550             :   EGainCurve(vs),
     551           0 :   gainCurveTabName_("")
     552             : {
     553           0 :   if (prtlev()>2) cout << "EPowerCurve::EPowerCurve(vs)" << endl;
     554           0 : }
     555             : 
     556           0 : EPowerCurve::EPowerCurve(String msname,Int MSnAnt,Int MSnSpw) :
     557             :   VisCal(msname,MSnAnt,MSnSpw), 
     558             :   VisMueller(msname,MSnAnt,MSnSpw),
     559             :   EGainCurve(msname,MSnAnt,MSnSpw),
     560           0 :   gainCurveTabName_("")
     561             : {
     562           0 :   if (prtlev()>2) cout << "EPowerCurve::EPowerCurve(msname,MSnAnt,MSnSpw)" << endl;
     563             : 
     564             :   // Temporary MS to get some info
     565           0 :   MeasurementSet ms(msname);
     566             : 
     567             :   // The relevant subtable names (there must be a better way...)
     568           0 :   gainCurveTabName_ = ms.rwKeywordSet().asTable("GAIN_CURVE").tableName();
     569           0 : }
     570             : 
     571           0 : EPowerCurve::EPowerCurve(const MSMetaInfoForCal& msmc) :
     572             :   VisCal(msmc), 
     573             :   VisMueller(msmc),
     574             :   EGainCurve(msmc),
     575           0 :   gainCurveTabName_("")
     576             : {
     577           0 :   if (prtlev()>2) cout << "EPowerCurve::EPowerCurve(msmc)" << endl;
     578             : 
     579             :   // Temporary MS to get some info
     580           0 :   MeasurementSet ms(this->msmc().msname());
     581             : 
     582             :   // The relevant subtable names (there must be a better way...)
     583           0 :   gainCurveTabName_ = ms.rwKeywordSet().asTable("GAIN_CURVE").tableName();
     584           0 : }
     585             : 
     586           0 : EPowerCurve::~EPowerCurve() {
     587           0 :   if (prtlev()>2) cout << "EPowerCurve::~EPowerCurve()" << endl;
     588           0 : }
     589             : 
     590           0 : void EPowerCurve::setSpecify(const Record& specify) {
     591             : 
     592             :   // Neither applying nor solving in specify context
     593           0 :   setSolved(false);
     594           0 :   setApplied(false);
     595             : 
     596             :   // Collect Cal table parameters
     597           0 :   if (specify.isDefined("caltable")) {
     598           0 :     calTableName()=specify.asString("caltable");
     599             : 
     600           0 :     if (Table::isReadable(calTableName()))
     601             :       logSink() << "FYI: We are going to overwrite an existing CalTable: "
     602           0 :                 << calTableName()
     603           0 :                 << LogIO::POST;
     604             :   }
     605             : 
     606             :   // Create a new caltable to fill
     607           0 :   createMemCalTable();
     608             : 
     609             :   // Setup shape of solveAllRPar
     610           0 :   initSolvePar();
     611           0 : }
     612             : 
     613           0 : void EPowerCurve::specify(const Record& specify) {
     614             : 
     615             :   // Escape if GAIN_CURVE table absent
     616           0 :   if (!Table::isReadable(gainCurveTabName()))
     617           0 :     throw(AipsError("The GAIN_CURVE subtable is not present in the specified MS. Gain curves unavailable."));
     618             : 
     619             :   // Construct matrix for EL to ZA conversion of polynomials.
     620           0 :   Matrix<Float> m_el(nPar(), nPar(), 0.0);
     621           0 :   for (Int i = 0; i < nPar()/2; i++) {
     622           0 :     for (Int j = 0; j < nPar()/2; j++) {
     623           0 :       if (i > j)
     624           0 :         continue;
     625           0 :       m_el(i, j) = Combinatorics::choose(j, i) *
     626           0 :         pow(-1.0, j) * pow(-90.0, (j - i));
     627           0 :       m_el(nPar()/2 + i, nPar()/2 + j) = m_el(i, j);
     628             :     }
     629             :   }
     630             : 
     631           0 :   Table gainCurveTab(gainCurveTabName(),Table::Old);
     632             : 
     633           0 :   for (Int ispw=0; ispw<nSpw(); ispw++) {
     634           0 :     Table itab = gainCurveTab(gainCurveTab.col("SPECTRAL_WINDOW_ID")==ispw);
     635             : 
     636           0 :     ScalarColumn<Double> timeCol(itab, "TIME");
     637           0 :     ScalarColumn<Double> intervalCol(itab, "INTERVAL");
     638           0 :     ScalarColumn<Int> antCol(itab,"ANTENNA_ID");
     639           0 :     ScalarColumn<Int> spwCol(itab,"SPECTRAL_WINDOW_ID");
     640           0 :     ScalarColumn<String> typeCol(itab,"TYPE");
     641           0 :     ScalarColumn<Int> numPolyCol(itab, "NUM_POLY");
     642           0 :     ArrayColumn<Float> gainCol(itab, "GAIN");
     643           0 :     ArrayColumn<Float> sensCol(itab, "SENSITIVITY");
     644             : 
     645           0 :     for (Int irow=0; irow<itab.nrow(); irow++) {
     646           0 :       Int iant=antCol(irow);
     647           0 :       currSpw()=ispw;
     648             : 
     649           0 :       Matrix<Float> m;
     650           0 :       if (typeCol(irow) == "POWER(ZA)" || typeCol(irow) == "VOLTAGE(ZA)")
     651           0 :         m = Matrix<Float>::identity(nPar());
     652           0 :       else if (typeCol(irow) == "POWER(EL)" || typeCol(irow) == "VOLTAGE(EL)")
     653           0 :         m = m_el;
     654             :       else
     655           0 :         throw(AipsError("The " + typeCol(irow) + "gain curve type is not supported. Gain curves unavailable."));
     656             : 
     657             :       // Initialize solveAllParOK, etc.
     658           0 :       solveAllParOK()=true;  // Assume all ok
     659           0 :       solveAllParErr()=0.0;  // what should we use here?
     660           0 :       solveAllParSNR()=1.0;
     661             : 
     662           0 :       Double begin = timeCol(irow) - intervalCol(irow) / 2;
     663           0 :       Double end = timeCol(irow) + intervalCol(irow) / 2;
     664             : 
     665             :       // Warn if we need to truncate the polynomial?
     666           0 :       Int npoly = min(numPolyCol(irow), nPar()/2);
     667             : 
     668           0 :       Vector<Float> gain(nPar(), 0.0);
     669           0 :       for (Int i = 0; i < npoly; i++) {
     670           0 :         gain(i) = gainCol(irow)(IPosition(2, 0, i));
     671           0 :         gain(nPar()/2 + i) = gainCol(irow)(IPosition(2, 1, i));
     672             :       }
     673             : 
     674             :       // Convert to ZA polynomial
     675           0 :       gain = product(m, gain);
     676             : 
     677             :       // Square voltage to get power.
     678           0 :       if (typeCol(irow).startsWith("VOLTAGE")) {
     679           0 :         Vector<Float> v(nPar(), 0.0);
     680           0 :         for (Int i = 0; i < nPar()/2; i++) {
     681           0 :           for (Int j = 0; j < nPar()/2; j++) {
     682           0 :             if (i + j < nPar()/2)
     683           0 :               v(i + j) += gain(i) * gain(j);
     684             :           }
     685             :         }
     686           0 :         gain = v;
     687           0 :       }
     688             : 
     689           0 :       for (Int i = 0; i < nPar()/2; i++) {
     690           0 :         gain(i) *= sensCol(irow)(IPosition(1, 0));
     691           0 :         gain(nPar()/2 + i) *= sensCol(irow)(IPosition(1, 1));
     692             :       }
     693             : 
     694           0 :       ct_->addRow(1);
     695             : 
     696           0 :       CTMainColumns ncmc(*ct_);
     697             : 
     698             :       // We are adding to the most-recently added row
     699           0 :       Int row=ct_->nrow()-1;
     700             : 
     701             :       // Meta-info
     702           0 :       ncmc.time().put(row, (begin + end) / 2);
     703           0 :       ncmc.fieldId().put(row, currField());
     704           0 :       ncmc.spwId().put(row, currSpw());
     705           0 :       ncmc.scanNo().put(row, currScan());
     706           0 :       ncmc.obsId().put(row, currObs());
     707           0 :       ncmc.interval().put(row, (end - begin) / 2);
     708           0 :       ncmc.antenna1().put(row, iant);
     709           0 :       ncmc.antenna2().put(row, -1);
     710             : 
     711             :       // Params
     712           0 :       ncmc.fparam().put(row,gain);
     713             : 
     714             :       // Stats
     715           0 :       ncmc.paramerr().put(row,solveAllParErr().xyPlane(iant));
     716           0 :       ncmc.snr().put(row,solveAllParErr().xyPlane(iant));
     717           0 :       ncmc.flag().put(row,!solveAllParOK().xyPlane(iant));
     718           0 :     }
     719             : 
     720             :     // This spw now has some solutions in it
     721           0 :     spwOK_(currSpw())=True;
     722           0 :   }
     723           0 : }
     724             : 
     725           0 : void EPowerCurve::calcAllJones() {
     726             : 
     727           0 :   if (prtlev()>6) cout << "       EPowerCurve::calcAllJones()" << endl;
     728             : 
     729             :   // Nominally no gain curve effect
     730           0 :   currJElem()=Complex(1.0);
     731           0 :   currJElemOK()=false;
     732             : 
     733             :   /*
     734             :   cout << "currSpw() = " << currSpw() << endl;
     735             :   cout << "   spwMap() = " << spwMap() << endl;
     736             :   cout << "   currRPar().shape() = " << currRPar().shape() << endl;
     737             :   cout << "   currRPar() = " << currRPar() << endl;
     738             :   */
     739             : 
     740           0 :   Complex* J=currJElem().data();
     741           0 :   Bool*    JOk=currJElemOK().data();
     742           0 :   Float*  c=currRPar().data();
     743           0 :   Double* a=za().data();
     744             : 
     745             :   Double loss, ang;
     746           0 :   for (Int iant=0; iant<nAnt(); ++iant,++a)
     747           0 :     for (Int ipol=0;ipol<2;++ipol,++J,++JOk) {
     748           0 :       loss=Double(*c);
     749           0 :       ++c;
     750           0 :       ang=1.0;
     751           0 :       for (Int ipar=1;ipar<nPar()/2;++ipar,++c) {
     752           0 :         ang*=(*a);
     753           0 :         loss+=((*c)*ang);
     754             :       }
     755           0 :       if (loss >= 0) {
     756           0 :         (*J) = Complex(sqrt(loss));
     757           0 :         (*JOk) = true;
     758             :       } else {
     759           0 :         (*J) = 0.0;
     760           0 :         (*JOk) = false;
     761             :       }
     762             :     }
     763           0 : }
     764             : 
     765             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16