LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - GSpline.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 337 586 57.5 %
Date: 2024-11-06 17:42:47 Functions: 10 18 55.6 %

          Line data    Source code
       1             : //# GJonesPoly.cc: Implementation of GJonesPoly.h
       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             : //# $Id: GJonesPoly.cc,v 19.15 2006/02/03 00:29:52 gmoellen Exp $
      27             : 
      28             : #include <synthesis/MeasurementComponents/GSpline.h>
      29             : #include <synthesis/MeasurementEquations/VisEquation.h>
      30             : 
      31             : #include <casacore/casa/Logging/LogIO.h>
      32             : #include <casacore/casa/Utilities/Assert.h>
      33             : #include <casacore/casa/Exceptions/Error.h>
      34             : #include <casacore/casa/Arrays/ArrayMath.h>
      35             : #include <casacore/scimath/Mathematics/MatrixMathLA.h>
      36             : #include <casacore/casa/Quanta/MVTime.h>
      37             : //#include <casa/Containers/SimOrdMap.h>
      38             : #include <casacore/casa/Containers/Block.h>
      39             : #include <cmath>
      40             : #include <casacore/casa/fstream.h>
      41             : 
      42             : #include <casacore/casa/System/PGPlotter.h>
      43             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      44             : #include <msvis/MSVis/VisBuffAccumulator.h>
      45             : #include <synthesis/CalTables/GJonesMBuf.h>
      46             : #include <synthesis/CalTables/GJonesTable.h>
      47             : #include <synthesis/CalTables/CalIter.h>
      48             : #include <casacore/tables/Tables/TableUtil.h>
      49             : 
      50             : using namespace casacore;
      51             : namespace casa { //# NAMESPACE CASA - BEGIN
      52             : 
      53             : using casacore::operator*;
      54             : 
      55             : // Define external CLIC solvers
      56             : #define NEED_UNDERSCORES
      57             : #if defined(NEED_UNDERSCORES)
      58             : #define polyant polyant_
      59             : #define splinant splinant_
      60             : #define getbspl getbspl_
      61             : #define phaseant phaseant_
      62             : #define ampliant ampliant_
      63             : #define cheb cheb_
      64             : #endif
      65             : 
      66             : extern "C" { 
      67             :   void polyant(Int*, Int*, Int*, Int*, Int*, Int*, Int*, Int*,
      68             :                Double*, Double*, Double*, Double*, Double*, Double*,
      69             :                Double*, Double* );
      70             :   void splinant(Int*, Int*, Int*, Int*, Int*, Int*, Int*, Int*,
      71             :                Double*, Double*, Double*, Double*, Double*, Double*,
      72             :                Double*, Double*, Double* );
      73             : 
      74             :   void getbspl(Int*, Double*, Double*, Double*, Double*, Int*);
      75             : 
      76             :   void phaseant(Int*, Int*, Int*, Int*, Double*, Double*, Double*, Double*, 
      77             :                 Int*, Double*, Double*);
      78             : 
      79             :   void ampliant(Int*, Int*, Int*, Int*, Double*, Double*, Double*, Double*, 
      80             :                 Int*, Double*, Double*);
      81             : 
      82             :   void cheb(Int*, Double*, Double*, Int*);
      83             : }
      84             : 
      85             : //----------------------------------------------------------------------------
      86             : 
      87           1 : GJonesSpline::GJonesSpline (VisSet& vs) :
      88             :   VisCal(vs),
      89             :   VisMueller(vs),
      90             :   GJones(vs),
      91           1 :   vs_p(&vs),
      92           1 :   solveAmp_p(false),
      93           1 :   solvePhase_p(true),
      94           1 :   splinetime_p(7200.0),
      95             :   //cacheTimeValid_p(0),
      96           1 :   calBuffer_p(NULL),
      97             :   //rawPhaseRemoval_p(false),
      98           1 :   solTimeStamp_p(0.0)
      99             : {
     100             : // Construct from a visibility set
     101             : // Input:
     102             : //    vs                VisSet&            Visibility set
     103             : // Output to private data:
     104             : //    solveAmp_p        Bool               true if mode_p includes amp. soln.
     105             : //    solvePhase_p      Bool               true if mode_p includes phase soln.
     106             : //    cacheTimeValid_p  Double             Time for which the current
     107             : //                                         calibration cache is valid
     108             : //    calBuffer_p       GJonesSplineMBuf*  Ptr to the applied cal. buffer
     109             : //
     110             : 
     111           1 :   if (prtlev()>2) cout << "GSpline::GSpline(vs)" << endl;
     112             : 
     113             :   // Mark the Jones matrix as neither solved for nor applied,
     114             :   // pending initialization by setSolver() or setInterpolation()
     115           1 :   setSolved(false);
     116           1 :   setApplied(false);
     117             : 
     118           1 : };
     119             : 
     120           0 : GJonesSpline::GJonesSpline (const MSMetaInfoForCal& msmc) :
     121             :   VisCal(msmc),
     122             :   VisMueller(msmc),
     123             :   GJones(msmc),
     124           0 :   vs_p(NULL),
     125           0 :   solveAmp_p(false),
     126           0 :   solvePhase_p(true),
     127           0 :   splinetime_p(7200.0),
     128             :   // cacheTimeValid_p(0),
     129           0 :   calBuffer_p(NULL),
     130             :   // rawPhaseRemoval_p(false),
     131           0 :   solTimeStamp_p(0.0)
     132             : {
     133             : // Construct from a MSMetaInfoForCal
     134             : // Input:
     135             : //    msmc              MSMetaInfoForCal&  MS Meta info server
     136             : // Output to private data:
     137             : //    solveAmp_p        Bool               true if mode_p includes amp. soln.
     138             : //    solvePhase_p      Bool               true if mode_p includes phase soln.
     139             : //    cacheTimeValid_p  Double             Time for which the current
     140             : //                                         calibration cache is valid
     141             : //    calBuffer_p       GJonesSplineMBuf*  Ptr to the applied cal. buffer
     142             : //
     143             : 
     144           0 :   if (prtlev()>2) cout << "GSpline::GSpline(msmc)" << endl;
     145             : 
     146             :   // Mark the Jones matrix as neither solved for nor applied,
     147             :   // pending initialization by setSolver() or setInterpolation()
     148           0 :   setSolved(false);
     149           0 :   setApplied(false);
     150             : 
     151           0 : };
     152             : 
     153             : //----------------------------------------------------------------------------
     154             : 
     155           2 : GJonesSpline::~GJonesSpline () 
     156             : {
     157             : // Virtual destructor
     158             : // Output to private data:
     159             : //    calBuffer_p       GJonesSplineMBuf*  Ptr to the applied cal. buffer
     160             : //
     161             : 
     162           1 :   if (prtlev()>2) cout << "GSpline::~GSpline(vs)" << endl;
     163             : 
     164             :   // Delete the calibration buffer
     165           1 :   if (calBuffer_p) delete(calBuffer_p);
     166           2 : };
     167             : 
     168             : //----------------------------------------------------------------------------
     169             : 
     170           1 : void GJonesSpline::setSolve(const Record& solvepar)
     171             : {
     172             : // Set the solver parameters
     173             : // Input:
     174             : //    solvepar            const Record&      Solver parameters
     175             : // Output to private data:
     176             : //    splinetime_p      Double             Spline knot timescale
     177             : 
     178           1 :   if (prtlev()>2) cout << "GSpline::setSolve()" << endl;
     179             : 
     180             :   // Call parent for generic pars
     181           1 :   SolvableVisCal::setSolve(solvepar);
     182             : 
     183             :   // Total solution interval is always all selecte data (for now)
     184           1 :   interval()=DBL_MAX;
     185             : 
     186             :   // Override nominal preavg handling
     187             :   //  (avoids interpretting -1 as pre-avg up to full interval)
     188           1 :   if (solvepar.isDefined("preavg")) 
     189           1 :     preavg() = solvepar.asDouble("preavg");
     190             : 
     191             :   // Spline-specific pars:
     192           1 :   if (solvepar.isDefined("splinetime")) 
     193           1 :     splinetime_p = solvepar.asDouble("splinetime");
     194           1 :   if (solvepar.isDefined("numpoint"))   
     195           1 :     numpoint_p   = solvepar.asInt("numpoint");
     196           1 :   if (solvepar.isDefined("phasewrap"))    // deg->rad
     197           1 :     phaseWrap_p  = solvepar.asDouble("phasewrap")*C::pi/180.0;
     198             : 
     199             :   // Interpret mode for SPLINE case
     200             :   //  (apmode now set in SVC::setsolve)
     201           1 :   solveAmp_p = (apmode().contains("A"));
     202           1 :   solvePhase_p = (apmode().contains("P"));
     203             : 
     204             :   //  cout << "solveAmp_p = " << solveAmp_p << endl;
     205             :   //  cout << "solvePhase_p = " << solvePhase_p << endl;
     206             :   //  cout << "calTableName() = " << calTableName() << endl;
     207             : 
     208             :   // Mark the Jones matrix as being solved for
     209           1 :   setSolved(true);
     210             : 
     211           1 :   return;
     212             : };
     213             : 
     214             : //----------------------------------------------------------------------------
     215             : 
     216           0 : void GJonesSpline::setApply(const Record& applypar)
     217             : {
     218             : // Set the apply parameters
     219             : // Input:
     220             : //    applypar     const Record&      Interpolation parameters
     221             : // Output to private data:
     222             : //    applyTable_p      String             Cal. table name containing
     223             : //                                         solutions to be applied
     224             : //    applySelect_p     String             Selection for the applied
     225             : //                                         calibration table
     226             : //    applyInterval_p   Double             Interpolation interval
     227             : //
     228             : 
     229           0 :   if (prtlev()>2) cout << "GSpline::setApply()" << endl;
     230             : 
     231             :   // Extract the parameters
     232           0 :   if (applypar.isDefined("table"))
     233           0 :     calTableName() = applypar.asString("table");
     234           0 :   if (applypar.isDefined("select"))
     235           0 :     calTableSelect() = applypar.asString("select");
     236           0 :   if (applypar.isDefined("t"))
     237           0 :     interval() = applypar.asDouble("t");
     238             : 
     239             :   // Attach a calibration buffer and iterator to the calibration 
     240             :   // table containing corrections to be applied
     241           0 :   GJonesSplineTable calTable(calTableName(), Table::Update);
     242           0 :   CalIter calIter(calTable);
     243             :   // Create the buffer and synchronize with the iterator
     244           0 :   if (calBuffer_p) delete calBuffer_p;
     245           0 :   calBuffer_p = new GJonesSplineMBuf(calIter);
     246           0 :   calBuffer_p->synchronize();
     247           0 :   calBuffer_p->fillCache();
     248             : 
     249             :   // Mark the Jones matrix as being applied
     250           0 :   setApplied(true);
     251             :   
     252           0 :   return;
     253           0 : };
     254             : 
     255             : //----------------------------------------------------------------------------
     256             : 
     257           1 : void GJonesSpline::selfGatherAndSolve (VisSet& vs, VisEquation& ve)
     258             : {
     259             : // Solver for the electronic gain in spline form
     260             : // Input:
     261             : //    me           VisEquation&         Measurement Equation (ME) in
     262             : //                                      which this Jones matrix resides
     263             : // Output:
     264             : //    solve        Bool                 true is solution succeeded
     265             : //                                      else false
     266             : //
     267             : 
     268           1 :   if (prtlev()>2) cout << "GSpline::selfGatherAndSolve(vs,ve)" << endl;
     269             : 
     270             : 
     271             :   //  cout << "Entering GSpline::solve." << endl;
     272             : 
     273             : 
     274           2 :   LogIO os (LogOrigin("GJonesSpline", "solve()", WHERE));
     275             : 
     276             : 
     277             :   os << LogIO::NORMAL
     278             :      << "Fitting time-dependent cubic splines."
     279           1 :      << LogIO::POST;
     280           1 :   if (solvePhase_p) {
     281             :     os << LogIO::NORMAL
     282             :        << "Solving for phase splines with splinetime= " << splinetime_p
     283           1 :        << LogIO::POST;
     284             :   }
     285           1 :   if (solveAmp_p) {
     286             :     os << LogIO::NORMAL
     287             :        << "Solving for amplitude splines with splinetime= " << splinetime_p
     288           1 :        << LogIO::POST;
     289             :   }
     290             : 
     291             :   // Arrange for iteration over data
     292           1 :   Block<Int> columns;
     293             :   // avoid scan iteration
     294           1 :   columns.resize(4);
     295           1 :   columns[0]=MS::ARRAY_ID;
     296           1 :   columns[1]=MS::FIELD_ID;      
     297           1 :   columns[2]=MS::DATA_DESC_ID;
     298           1 :   columns[3]=MS::TIME;
     299           1 :   vs.resetVisIter(columns,interval());
     300           1 :   VisIter& vi(vs.iter());
     301           1 :   VisBuffer vb(vi);
     302             : 
     303             :   // Count polarizations
     304           1 :   Int nPH(0);
     305           5 :   for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
     306           4 :     vi.origin();
     307           4 :     Int ncorr(vb.corrType().nelements());
     308           4 :     nPH= max(nPH,min(ncorr,2));
     309             :   }
     310             : 
     311             :   // nPH has the number of correlations (1 or 2) to process
     312             : 
     313             :   // Initialize time-series accumulation buffers for the
     314             :   // corrected and corrupted visibility data and associated
     315             :   // weights. 
     316           1 :   std::map<String,Int> timeValueMap;
     317           1 :   Vector<Double> timeValues;
     318           1 :   PtrBlock<Matrix<Complex>* > visTimeSeries;
     319           1 :   PtrBlock<Matrix<Double>* > weightTimeSeries;
     320           1 :   Int nTimeSeries = 0;
     321             : 
     322             :   // Initialize antenna indices
     323           1 :   Vector<Int> ant1(nBln(), -1);
     324           1 :   Vector<Int> ant2(nBln(), -1);
     325             : 
     326           1 :   Int k=0;
     327          11 :   for (Int a1=0; a1 < nAnt(); a1++) {
     328          65 :     for (Int a2=a1; a2 < nAnt(); a2++,k++) {
     329          55 :       ant1(k) = a1 + 1;
     330          55 :       ant2(k) = a2 + 1;
     331             :       //      cout << a1 << " " << a2 << " " << k << " " << blnidx(a1,a2) << endl;
     332             :     };
     333             :   };
     334             : 
     335             :   // Iterate, accumulating the averaged visibility time-series
     336             :   Int chunk;
     337             :   // Mean reference frequency
     338           1 :   Double meanFreq = 0;
     339           1 :   Int nMeanFreq = 0;
     340             : 
     341             :   // With current VisIter sort order, this chunking does
     342             :   //   all times for each spw and field
     343             :   // Double t0;
     344           5 :   for (chunk=0, vi.originChunks(); vi.moreChunks(); vi.nextChunk(), chunk++) {
     345             : 
     346             :     // Extract the current visibility buffer spectral window id.
     347             :     // and number for frequency channels
     348           4 :     Int spwid = vi.spectralWindow();
     349           4 :     Int nChan = vs.numberChan()(spwid);
     350           4 :     String fieldName = vi.fieldName();
     351             : 
     352             :     os << LogIO::NORMAL 
     353             :        << "Accumulating data for:  field= " << fieldName 
     354             :        << ", spw= " << spwid
     355             :        << ", nchan= " << nChan 
     356           4 :        << LogIO::POST;
     357             : 
     358             :     // Compute the corrected and corrupted data at the position of
     359             :     // this Jones matrix in the Measurement Equation. The corrupted
     360             :     // data are the model visibilities propagated along the ME from
     361             :     // the sky to the immediate right of the current Jones matrix.
     362             :     // The corrected data are the observed data corrected for all
     363             :     // Jones matrices up to the immediate left of the current Jones
     364             :     // matrix.
     365             : 
     366             :     // Arrange to accumulate
     367           4 :     VisBuffAccumulator vba(nAnt(),preavg(),false);
     368             : 
     369           4 :     vi.origin();
     370             :     //    t0=86400.0*floor(vb.time()(0)/86400.0);
     371             :     
     372             :     // Collapse each timestamp in this chunk according to VisEq
     373             :     //  with calibration and averaging
     374        3832 :     for (vi.origin(); vi.more(); vi++) {
     375             : 
     376             :       // TBD: initialize weights from sigma here?
     377             :       
     378        3828 :       ve.collapse(vb);
     379             :       
     380             :       // If permitted/required by solvable component, normalize
     381        3828 :       if (normalizable())
     382        3828 :         vb.normalize();
     383             :       
     384             :       // If this solve not freqdep, and channels not averaged yet, do so
     385        3828 :       if (!freqDepMat() && vb.nChannel()>1)
     386        3828 :         vb.freqAveCubes();
     387             : 
     388             :       // Accumulate collapsed vb in a time average
     389        3828 :       vba.accumulate(vb);
     390             :     }
     391           4 :     vba.finalizeAverage();
     392             : 
     393             :     // The VisBuffer to work with in solve
     394           4 :     VisBuffer& svb(vba.aveVisBuff());
     395             : 
     396             :     //    cout << " (Chunk accumulated) nrow = " << svb.nRow() << endl;
     397             :     //    cout << " nChan = " << svb.nChannel() << endl;
     398             : 
     399             :     // NB: The svb VisBuffer has many timestamps in it....
     400             : 
     401             :     // index to parallel hands (assumes canonical order)
     402           4 :     Int nCorr = svb.corrType().nelements();
     403           4 :     Vector<Int> polidx(2,0);
     404           4 :     polidx(1)=nCorr-1;
     405             :     
     406             :     // Accumulate mean frequency of the averaged data
     407           4 :     meanFreq += mean(svb.frequency());
     408           4 :     nMeanFreq++;
     409             : 
     410             :     // Iterate over the current accumulated visibility buffer, obtaining
     411             :     // a common time series in the visibility data
     412      210544 :     for (Int row=0; row < svb.nRow(); row++) {
     413             :       // Antenna numbers
     414      210540 :       Int ant1num = svb.antenna1()(row);
     415      210540 :       Int ant2num = svb.antenna2()(row);
     416             : 
     417             :       // Reject auto-correlation data
     418      210540 :       if (ant1num != ant2num) {
     419             :         // Compute baseline index
     420      172260 :         Int baselineIndex = blnidx(ant1num,ant2num);
     421             : 
     422             :         // Weight
     423      172260 :         Vector<Float> rowWeight(svb.weightMat().column(row));
     424      172260 :         if (sum(rowWeight) > 0) {
     425             :           // Map the current time stamp to a time series index
     426             :           // using 0.1 second precision, i.e. time values within
     427             :           // a tenth of a second of each other will be accumulated
     428             :           // within the same bin.
     429      172260 :           MVTime mvt(svb.time()(row) / C::day);
     430      172260 :           String timeKey = mvt.string(MVTime::TIME, 7);
     431      172260 :           Int timeIndex = 0;
     432             :           // Check the time stamp index to this precision
     433      172260 :       if (timeValueMap.find(timeKey) != timeValueMap.end( )) {
     434      171303 :             timeIndex = timeValueMap[timeKey];
     435             :           } else {
     436             :             // Create a new time series entry
     437         957 :             timeIndex = nTimeSeries++;
     438         957 :             timeValueMap.insert(std::pair<casacore::String, casacore::Int>(timeKey, timeIndex));
     439         957 :             timeValues.resize(nTimeSeries, true);
     440         957 :             timeValues(timeIndex) = svb.time()(row);
     441         957 :             Complex czero(0,0);
     442         957 :             visTimeSeries.resize(nTimeSeries, true);
     443         957 :             visTimeSeries[timeIndex] = new Matrix<Complex>(nBln(),nPH, czero);
     444         957 :             weightTimeSeries.resize(nTimeSeries, true);
     445         957 :             weightTimeSeries[timeIndex] = new Matrix<Double>(nBln(),nPH, 0);
     446             :           };
     447             : 
     448             :           // Accumulate the current visbility row in the common time series
     449      516780 :           for (Int ip=0;ip<nPH;++ip) {
     450      344520 :             Double dwt=Double(rowWeight(polidx(ip)));
     451      344520 :             (*visTimeSeries[timeIndex])(baselineIndex,ip) +=
     452      689040 :               svb.visCube()(polidx(ip),0,row) * dwt;
     453      344520 :             (*weightTimeSeries[timeIndex])(baselineIndex,ip) += dwt;
     454             :           }
     455      172260 :         };
     456      172260 :       };
     457             :     };
     458           4 :   }; // for (chunk...) iteration
     459             : 
     460             :   // Create amplitude, phase and weight arrays per time-slot
     461             :   // and interferometer index in the form required by the
     462             :   // GILDAS solver, splinant.
     463           1 :   Int nTimes = timeValueMap.size( );
     464             : 
     465             :   os << LogIO::NORMAL 
     466             :      << "Number of timestamps in data = " << nTimes
     467           1 :      << LogIO::POST;
     468             : 
     469           1 :   Vector<Double> time(nTimes, 0);
     470           1 :   Cube<Double> amp(nTimes, nBln(), nPH, 0);
     471           1 :   Cube<Double> phase(nTimes, nBln(), nPH, 0);
     472           1 :   Cube<Double> weight(nTimes, nBln(),nPH, 0);
     473             :   //
     474             :   // First create a simple index in order of ascending time ordinate
     475           1 :   Vector<Int> index(nTimes);
     476           1 :   indgen(index);
     477         958 :   for (Int j=0; j < nTimes; j++) {
     478      458403 :     for (Int k=j+1; k < nTimes; k++) {
     479      457446 :       if (timeValues(index(j)) > timeValues(index(k))) {
     480           0 :         Int swap = index(j);
     481           0 :         index(j) = index(k);
     482           0 :         index(k) = swap;
     483             :       };
     484             :     };
     485             :   };
     486             : 
     487             :   // Fill the amplitude, phase and weight arrays with normalized 
     488             :   // and scaled vaues from the accumulated time series.
     489         958 :   for (Int t=0; t < nTimes; t++) {
     490       53592 :     for (Int baselineIndex=0; baselineIndex < nBln(); ++baselineIndex) {
     491             :       // Iterate in ascending time order
     492       52635 :       Int indx = index(t);
     493             :       // Time
     494       52635 :       time(t) = timeValues(indx);
     495             : 
     496      157905 :       for (Int ip=0;ip<nPH;++ip) {
     497             : 
     498      105270 :         Double wgt = (*weightTimeSeries[indx])(baselineIndex,ip);
     499      105270 :         if (wgt > 0) {
     500       86130 :           Complex vis = (*visTimeSeries[indx])(baselineIndex,ip);
     501             :           
     502             :           // Amplitude
     503       86130 :           if (abs(vis) > 0) {
     504       86130 :             amp(t,baselineIndex,ip) = log(abs(vis)/wgt);
     505             :           };
     506             : 
     507             :           // Phase
     508       86130 :           if(solvePhase_p){
     509       86130 :             Double visPhase = arg(vis);
     510       86130 :             visPhase = remainder(visPhase, 2*C::pi);
     511       86130 :             if (visPhase > C::pi) {
     512           0 :               visPhase -= 2 * C::pi;
     513       86130 :             } else if (visPhase < -C::pi) {
     514           0 :               visPhase += 2 * C::pi;
     515             :             };
     516       86130 :             phase(t,baselineIndex,ip) = visPhase;
     517             :           }
     518             :           
     519             : 
     520             :           // Weight
     521       86130 :           weight(t,baselineIndex,ip) = wgt;
     522             :           //weight(t,baselineIndex,ip) = 1.0;
     523             :         }
     524             :       };
     525             :     };
     526             :   };
     527             : 
     528             :   //  cout << "weight = " << weight << endl;
     529             :   //  cout << "weight.shape() = " << weight.shape() << endl;
     530             : 
     531             :   // Delete the accumulation buffers
     532         958 :   for (Int k=0; k < nTimes; k++) {
     533         957 :     delete(visTimeSeries[k]);
     534         957 :     delete(weightTimeSeries[k]);
     535             :   };
     536             : 
     537             : 
     538             :   //  Double t0=86400.0*floor(min(time)/86400.0);
     539             : 
     540             :   // Compute the number of spline knots
     541           1 :   Vector<Double> knots, ampKnots(1,0.0), phaKnots(1,0.0);
     542           1 :   Int nKnots = getKnots(time, knots);
     543             :   
     544             :   os << LogIO::NORMAL 
     545             :      << "Number of cubic spline control points = " << nKnots-4
     546           1 :      << LogIO::POST;
     547             : 
     548             :   os << LogIO::NORMAL 
     549             :      << "Number of cubic spline knots = " << nKnots
     550           1 :      << LogIO::POST;
     551             : 
     552             :   os << LogIO::NORMAL 
     553             :      << "Number of cubic spline segments = " << nKnots-7
     554           1 :      << LogIO::POST;
     555             : 
     556           1 :   if (nTimes < (nKnots-4) ) {
     557             :     os << LogIO::SEVERE
     558             :        << "Insufficient number of timestamps for cubic splines:" << endl 
     559           0 :        << "  Control points - nTimes > 0  (" << nKnots-4-nTimes << ")"
     560           0 :        << LogIO::POST;
     561             :     os << LogIO::SEVERE
     562             :        << "Increase splinetime or reduce preavg (if possible), or " << endl
     563             :        << "  solve for ordinary G instead."
     564           0 :        << LogIO::POST;
     565           0 :     return;
     566             :   };
     567             : 
     568           1 :   solTimeStamp_p = mean(knots);
     569             : 
     570             :   // Declare work arrays and returned value
     571             :   // arrays to be used by the solver
     572           1 :   Matrix<Double> wk1(4, nTimes);
     573           1 :   Matrix<Double> wk2(4*nAnt(), nKnots*nAnt());
     574           1 :   Vector<Double> wk3(nKnots*nAnt());
     575           1 :   Vector<Double> rmsfit(nBln(),0);
     576             : 
     577           1 :   Double dzero(0);
     578             : 
     579             :   // GSpline is nominally dual-pol
     580           1 :   Cube<Double> polyCoeffAmp(nAnt(),nKnots,2, dzero);
     581           1 :   Cube<Double> polyCoeffPhase(nAnt(),nKnots,2, dzero);
     582             : 
     583             :   // Fit using spline polynomials (GILDAS splinant)
     584             :   Bool dum;
     585             :   Int iy;
     586             :   // GILDAS solver uses one-relative antenna numbers
     587           1 :   Int rAnt = refant() + 1;
     588           1 :   Int nBL(nBln());
     589           1 :   Int nA(nAnt());
     590             : 
     591           1 :   if (solveAmp_p) {
     592             :     // Amplitude solution
     593             : 
     594             :     os << LogIO::NORMAL 
     595             :        << "Fitting amplitude spline."
     596           1 :        << LogIO::POST;
     597             : 
     598           1 :     ampKnots.resize(knots.shape());
     599           1 :     ampKnots=knots;
     600             : 
     601           1 :     iy = 1;
     602             :     
     603           3 :     for (Int ip=0;ip<nPH;++ip) {
     604             : 
     605           6 :       splinant(&iy,
     606             :                &nTimes,
     607             :                &nBL,
     608             :                ant1.getStorage(dum),
     609             :                ant2.getStorage(dum),
     610             :                &rAnt,
     611             :                &nKnots,
     612             :                &nA,
     613             :                time.getStorage(dum),
     614           4 :                amp.xyPlane(ip).getStorage(dum),
     615           4 :                weight.xyPlane(ip).getStorage(dum),
     616             :                knots.getStorage(dum),
     617             :                wk1.getStorage(dum),
     618             :                wk2.getStorage(dum),
     619             :                wk3.getStorage(dum),
     620             :                rmsfit.getStorage(dum),
     621           4 :                polyCoeffAmp.xyPlane(ip).getStorage(dum));
     622             :     
     623           2 :       ostringstream o;
     624           2 :       o << calTableName() << ".AMP.pol" << ip << ".log";
     625           2 :       String logfile=o.str();
     626           2 :       writeAsciiLog(logfile, polyCoeffAmp.xyPlane(ip), rmsfit, false);
     627             :       //    plotsolve(time, amp, weight, rmsfit, polyCoeffAmp, false);
     628             : 
     629           2 :     }
     630             : 
     631             :   }
     632             : 
     633           1 :   if (solvePhase_p){
     634             :     // Phase solution
     635             : 
     636             :     os << LogIO::NORMAL 
     637             :        << "Searching for and correcting phase-wraps on each baseline."
     638           1 :        << LogIO::POST;
     639             : 
     640           3 :     for (Int ip=0;ip<nPH;++ip) {
     641             :       
     642         112 :       for(Int bsInd=0; bsInd < nBln() ; ++bsInd){
     643             :         
     644         110 :         Int npoi=numpoint_p; 
     645         110 :         if (npoi < 2) npoi=2;
     646             :         
     647      104720 :         for (Int k1=npoi; k1 < nTimes-npoi; k1=k1+(npoi/2)){
     648      104610 :           Vector<Double> vecAheadPh(npoi), vecBheadPh(npoi);
     649      418440 :           for (Int k=0; k < npoi; ++k){
     650      313830 :             vecBheadPh[k]=phase(k1-k-1,bsInd,ip);
     651      313830 :             vecAheadPh[k]=phase(k1+k, bsInd,ip);
     652             :           }
     653      104610 :           Double medA=median(vecAheadPh);
     654      104610 :           Double medB=median(vecBheadPh);
     655      104610 :           if((medA- medB) >phaseWrap_p)
     656        2478 :             for(Int k=k1; k< nTimes; ++k)
     657        2450 :               phase(k, bsInd,ip) -= 2*C::pi;
     658      104610 :           if((medA-medB) < -phaseWrap_p)
     659        3534 :             for(Int k=k1; k< nTimes; ++k)
     660        3504 :               phase(k, bsInd,ip) += 2*C::pi;
     661             :           
     662      104610 :         }
     663             :         
     664         110 :         if(nTimes >npoi*2){
     665             :           
     666             :           //the last npoi pts
     667         110 :           Vector<Double> vecAheadPh(npoi), vecBheadPh(npoi);
     668         440 :           for (Int k=0; k <npoi; ++k){
     669         330 :             vecBheadPh[k]=phase(nTimes-2*npoi+k,bsInd,ip);
     670         330 :             vecAheadPh[k]=phase(nTimes-npoi+k, bsInd,ip);
     671             :           }
     672         110 :           Double medA=median(vecAheadPh);
     673         110 :           Double medB=median(vecBheadPh);
     674         110 :           if((medA- medB) > phaseWrap_p)
     675           0 :             for(Int k=(nTimes-npoi); k< nTimes; ++k)
     676           0 :               phase(k, bsInd,ip) -= 2*C::pi;
     677         110 :           if((medA-medB) < -phaseWrap_p)
     678           0 :             for(Int k=(nTimes-npoi); k< nTimes; ++k)
     679           0 :               phase(k, bsInd,ip) += 2*C::pi;
     680             :           
     681             :           // The first npoi points
     682             :           
     683         440 :           for (Int k=0; k <npoi; ++k){
     684         330 :             vecBheadPh[k]=phase(k,bsInd,ip);
     685         330 :             vecAheadPh[k]=phase(npoi+k, bsInd,ip);
     686             :           }
     687         110 :           medA=median(vecAheadPh);
     688         110 :           medB=median(vecBheadPh);
     689         110 :           if((medA- medB) > phaseWrap_p)
     690           0 :             for(Int k=0; k< npoi; ++k)
     691           0 :               phase(k, bsInd,ip) += 2*C::pi;
     692         110 :           if((medA-medB) < -phaseWrap_p)
     693           0 :             for(Int k=0; k< npoi; ++k)
     694           0 :               phase(k, bsInd,ip) -= 2*C::pi;
     695             :           
     696         110 :         }
     697             :       }
     698             :     }
     699             : 
     700             :     os << LogIO::NORMAL 
     701             :        << "Fitting phase spline."
     702           1 :        << LogIO::POST;
     703             : 
     704           1 :     phaKnots.resize(knots.shape());
     705           1 :     phaKnots=knots;
     706           1 :     iy = 2;
     707             : 
     708           3 :     for (Int ip=0;ip<nPH;++ip) {
     709             : 
     710           2 :       wk1=0.0; wk2=0.0; wk3=0.0;
     711             : 
     712           6 :       splinant(&iy,
     713             :                &nTimes,
     714             :                &nBL,
     715             :                ant1.getStorage(dum),
     716             :                ant2.getStorage(dum),
     717             :                &rAnt,
     718             :                &nKnots,
     719             :                &nA,
     720             :                time.getStorage(dum),
     721           4 :                phase.xyPlane(ip).getStorage(dum),
     722           4 :                weight.xyPlane(ip).getStorage(dum),
     723             :                knots.getStorage(dum),
     724             :                wk1.getStorage(dum),
     725             :                wk2.getStorage(dum),
     726             :                wk3.getStorage(dum),
     727             :                rmsfit.getStorage(dum),
     728           4 :                polyCoeffPhase.xyPlane(ip).getStorage(dum));
     729             : 
     730             : 
     731             :       //      cout << "Finished solve." << endl;
     732             : 
     733             : 
     734           2 :       ostringstream o;
     735           2 :       o << calTableName() << ".PHASE.pol" << ip << ".log";
     736           2 :       String logfile=o.str();
     737           2 :       writeAsciiLog(logfile, polyCoeffPhase.xyPlane(ip), rmsfit, true);
     738             : 
     739             :       // TBD: make multi-pol plotsolve
     740             :       //      plotsolve(time, phase, weight, rmsfit, polyCoeffPhase, true);
     741             : 
     742           2 :     }
     743             : 
     744             : 
     745             : 
     746             :   };
     747             : 
     748             :   // Update the output calibration table
     749           1 :   Vector<Int> antId(nAnt());
     750           1 :   indgen(antId);
     751           1 :   Vector<Int> fieldIdKeys = fieldIdRange();
     752           1 :   Vector<String> freqGrpName(nAnt(), "");
     753           1 :   Vector<String> polyType(nAnt(), "SPLINE");
     754           1 :   Vector<String> polyMode(nAnt(), apmode());
     755           1 :   if (apmode()=="AP")
     756           1 :     polyMode="PHASAMP";
     757           1 :   if (apmode()=="P")
     758           0 :     polyMode="PHAS";
     759           1 :   if (apmode()=="A")
     760           0 :     polyMode="AMP";
     761             : 
     762           1 :   Vector<Complex> scaleFactor(nAnt(), Complex(1,0));
     763           1 :   Vector<String> phaseUnits(nAnt(), "RADIANS");
     764           1 :   Vector<Int> refAnt(nAnt(), refant());
     765             :   
     766             :   // Use mean frequency as the reference frequency
     767           1 :   if (nMeanFreq > 0) meanFreq = meanFreq / nMeanFreq;
     768           2 :   Vector<MFrequency> refFreq(nAnt(), MFrequency(Quantity(meanFreq, "Hz")));
     769             : 
     770             :   // If not incremental calibration then create an empty
     771             :   // calibration buffer to hold the output calibration solutions
     772           1 :   if (!calBuffer_p) {
     773           1 :     newCalBuffer(fieldIdKeys, antId);
     774             :   } else {
     775             :     // Force an explicit read to cache for all calibration columns
     776             :     // (in case the input calibration table is being overwritten
     777             :     // in place)
     778           0 :     calBuffer_p->fillCache();
     779             : 
     780             :   };
     781             : 
     782             :   // Update the calibration table
     783             :   //  cout << "ampKnots.nelements() = " << ampKnots.nelements() << endl;
     784             :   //  cout << "phaKnots.nelements() = " << phaKnots.nelements() << endl;
     785             :   //  cout << "nKnots = " << nKnots << endl;
     786             : 
     787             :   //  cout << "polyCoeffPhase.shape() = " << polyCoeffPhase.shape() << endl;
     788             :   //  cout << "polyCoeffPhase.reform(IPosition(nAnt(),ampKnots.nelements()*2)).shape() = " 
     789             :   //       << polyCoeffPhase.reform(IPosition(2,nAnt(),nKnots*2)).shape() << endl;
     790             : 
     791             : 
     792           2 :   Matrix<Double> ampco(polyCoeffAmp.reform(IPosition(2,nAnt(),nKnots*2)));
     793           2 :   Matrix<Double> phaco(polyCoeffPhase.reform(IPosition(2,nAnt(),nKnots*2)));
     794             : 
     795           1 :   updateCalTable(fieldIdKeys, antId, freqGrpName, polyType, polyMode, 
     796             :                  scaleFactor, 
     797             :                  ampco,phaco,
     798             :                  //              polyCoeffAmp.xyPlane(0), polyCoeffPhase.xyPlane(0), 
     799             :                  phaseUnits, ampKnots, phaKnots, refFreq, refAnt);
     800             :         
     801           1 :   return;
     802           1 : };
     803             : 
     804             : //----------------------------------------------------------------------------
     805             : 
     806           0 : void GJonesSpline::calcPar() {
     807             : 
     808             : // Calculate new gain parameters (in this case, the G matrix elements)
     809             : 
     810           0 :   if (prtlev()>6) cout << "      GSpline::calcPar()" << endl;
     811             : 
     812           0 :   LogIO os (LogOrigin("GJonesSpline", "calcPar", WHERE));
     813             : 
     814           0 :   Double freqRatio=1.0;
     815           0 :   Double vbFreqHz = 1.0e9*mean(currFreq());
     816             : 
     817             :   //  cout << "vbFreqHz = " << vbFreqHz << endl;
     818             : 
     819           0 :   currCPar().resize(nPar(),1,nAnt());
     820           0 :   currParOK().resize(nPar(),1,nAnt());
     821           0 :   currParOK()=false;
     822             : 
     823             :   // Compute them, per antenna
     824           0 :   for (Int iant=0; iant < nAnt(); iant++) {
     825             : 
     826             :     // Match this antenna id. and the visibility buffer field id. 
     827             :     // in the calibration buffer
     828             :     Vector<Int> matchingRows = 
     829           0 :       calBuffer_p->matchAntenna1AndFieldId(iant,currField());
     830             : 
     831           0 :     if (matchingRows.nelements() > 0) {
     832             :       // Matching calibration solution found
     833           0 :       Int row = matchingRows(0);
     834           0 :       Vector<Double> ampVal(2,1.0);
     835           0 :       Vector<Double> phaseVal(2,0.0);
     836           0 :       Complex gain(calBuffer_p->scaleFactor()(row));
     837           0 :       String mode = calBuffer_p->polyMode()(row);
     838             : 
     839             :       //      cout << "gain = " << gain << endl;
     840             : 
     841             :       // Compute the ratio between the calibration solution 
     842             :       // reference frequency and the mean observed frequency
     843             :       // of the visibility data to be corrected
     844           0 :       IPosition refFreqPos = calBuffer_p->refFreqMeas().shape();
     845           0 :       refFreqPos = 0;
     846           0 :       refFreqPos.setLast(IPosition(1,row));
     847           0 :       MFrequency refFreq = calBuffer_p->refFreqMeas()(refFreqPos);
     848           0 :       Double refFreqHz = refFreq.get("Hz").getValue();
     849           0 :       freqRatio = abs(refFreqHz) > 0 ? vbFreqHz / refFreqHz : 1.0;
     850             :       //      cout << "freqRatio = " << freqRatio << endl;
     851             : 
     852             :       // Compute amplitude polynomial
     853           0 :       if (mode.contains("AMP") || mode.contains("A&P")) {
     854             :         // Extract amplitude spline polynomial knots
     855           0 :         IPosition ampKnotsPos = calBuffer_p->splineKnotsAmp().shape();
     856           0 :         ampKnotsPos = 0;
     857           0 :         Int nAmpKnotsPos = ampKnotsPos.nelements();
     858           0 :         ampKnotsPos[nAmpKnotsPos-1] = row;
     859           0 :         Int nKnots = calBuffer_p->nKnotsAmp()(row);
     860           0 :         Vector<Double> ampKnots(nKnots);
     861           0 :         for (Int k=0; k < nKnots; k++) {
     862           0 :           ampKnotsPos[nAmpKnotsPos-2] = k;
     863           0 :           ampKnots(k) = calBuffer_p->splineKnotsAmp()(ampKnotsPos);
     864             :         };
     865             :         
     866             :         // Extract amplitude spline polynomial coefficients
     867           0 :         IPosition ampCoeffPos = calBuffer_p->polyCoeffAmp().shape();
     868           0 :         ampCoeffPos = 0;
     869           0 :         Int nAmpCoeffPos = ampCoeffPos.nelements();
     870           0 :         ampCoeffPos[nAmpCoeffPos-1] = row;
     871           0 :         Int nPoly = calBuffer_p->nPolyAmp()(row);
     872           0 :         Vector<Double> ampCoeff(2*nPoly);
     873           0 :         for (Int k=0; k < 2*nPoly; k++) {
     874           0 :           ampCoeffPos[nAmpCoeffPos-2] = k;
     875           0 :           ampCoeff(k) = calBuffer_p->polyCoeffAmp()(ampCoeffPos);
     876             :         };
     877             : 
     878             :         //      cout << "ampCoeff = " << ampCoeff << endl;
     879             : 
     880             :         // Compute amplitude spline polynomial value
     881           0 :         Vector<Double> ac;
     882           0 :         for (Int i=0;i<2;++i) {
     883           0 :           ac.reference(ampCoeff(IPosition(1,i*nPoly),
     884           0 :                                 IPosition(1,(i+1)*nPoly-1)));
     885           0 :           ampVal(i) *= exp(getSplineVal(currTime(), ampKnots, ac));
     886             :         }
     887             :         //      cout << iant << " ampVal = " << ampVal << endl;
     888           0 :       };
     889             : 
     890             :       // Compute phase polynomial
     891           0 :       if (mode.contains("PHAS") || mode.contains("A&P")) {
     892             : 
     893             :           // Extract phase spline polynomial knots
     894           0 :           IPosition phaseKnotsPos = calBuffer_p->splineKnotsPhase().shape();
     895           0 :           phaseKnotsPos = 0;
     896           0 :           Int nPhaseKnotsPos = phaseKnotsPos.nelements();
     897           0 :           phaseKnotsPos[nPhaseKnotsPos-1] = row;
     898           0 :           Int nKnots = calBuffer_p->nKnotsPhase()(row);
     899           0 :           Vector<Double> phaseKnots(nKnots);
     900           0 :           for (Int k=0; k < nKnots; k++) {
     901           0 :             phaseKnotsPos[nPhaseKnotsPos-2] = k;
     902           0 :             phaseKnots(k) = calBuffer_p->splineKnotsPhase()(phaseKnotsPos);
     903             :           };
     904             :           
     905             :           // Extract phase spline polynomial coefficients
     906           0 :           IPosition phaseCoeffPos = calBuffer_p->polyCoeffPhase().shape();
     907           0 :           phaseCoeffPos = 0;
     908           0 :           Int nPhaseCoeffPos = phaseCoeffPos.nelements();
     909           0 :           phaseCoeffPos[nPhaseCoeffPos-1] = row;
     910           0 :           Int nPoly = calBuffer_p->nPolyPhase()(row);
     911           0 :           Vector<Double> phaseCoeff(2*nPoly);
     912           0 :           for (Int k=0; k < 2*nPoly; k++) {
     913           0 :             phaseCoeffPos[nPhaseCoeffPos-2] = k;
     914           0 :             phaseCoeff(k) = calBuffer_p->polyCoeffPhase()(phaseCoeffPos);
     915             :           };
     916             : 
     917             :           //      cout << "phaseCoeff = " << phaseCoeff << endl;
     918             :           
     919             :           // Compute phase spline polynomial value
     920           0 :           Vector<Double> pc;
     921           0 :           for (Int i=0;i<2;++i) {
     922           0 :             pc.reference(phaseCoeff(IPosition(1,i*nPoly),
     923           0 :                                     IPosition(1,(i+1)*nPoly-1)));
     924             : 
     925             :             //      cout << "pc = " << pc << endl;
     926             : 
     927           0 :             phaseVal(i) = getSplineVal(currTime(), phaseKnots, pc);
     928             :           
     929             :             // Handle gildas sign convention on spline phases
     930           0 :             phaseVal(i) = -phaseVal(i);
     931             :           
     932             :             // Scale by the ratio of the observing frequency of the 
     933             :             // data to be corrected and the reference frequency of the
     934             :             // calibration solution
     935           0 :             phaseVal(i) *= freqRatio;
     936             :           }
     937           0 :       };
     938             : 
     939             :       //      cout << "phaseVal = " << phaseVal << endl;
     940             :       
     941             :       // Fill the (matrix element) parameters
     942           0 :       for (Int i=0;i<2;++i) {
     943           0 :         currCPar()(i,0,iant) = gain * ampVal(i) * Complex(cos(phaseVal(i)), 
     944           0 :                                                           sin(phaseVal(i)) );
     945           0 :         currParOK()(i,0,iant) = true;
     946             :       }
     947             :       
     948           0 :     };
     949           0 :   };
     950             : 
     951             :   //cout << "currCPar() = " << currCPar() << endl;
     952             : 
     953           0 :   validateP();
     954           0 :   invalidateJ();
     955             : 
     956           0 :   return;
     957           0 : };
     958             : 
     959             : //----------------------------------------------------------------------------
     960             : 
     961           1 : void GJonesSpline::newCalBuffer (const Vector<Int>& fieldIdKeys,
     962             :                                  const Vector<Int>& antennaId)
     963             : {
     964             : // Create and fill and empty output calibration buffer
     965             : // Input:
     966             : //    fieldIdKeys      const Vec<Int>&        Field id.'s to span
     967             : //    antennaId        const Vec<Int>&        Antenna id.'s to span
     968             : // Output to private data:
     969             : //    calBuffer_p      GJonesSplineMBuf*      Calibration buffer
     970             : //
     971           2 :   LogIO os (LogOrigin("GJonesSpline", "newCalBuffer", WHERE));
     972             : 
     973             :   // Delete calibration buffer if it already exists
     974           1 :   if (calBuffer_p) delete calBuffer_p;
     975             : 
     976             :   // Initialize the GJonesSpline calibration buffer, spanning the 
     977             :   // antenna id.'s and field id.'s specified.
     978           1 :   Vector<Int> key(2);
     979           1 :   key(0) = MSC::ANTENNA1;
     980           1 :   key(1) = MSC::FIELD_ID;
     981           1 :   Block<Vector<Int> > keyvals(2);
     982           1 :   keyvals[0] = antennaId;
     983           1 :   keyvals[1] = fieldIdKeys;
     984           1 :   calBuffer_p = new GJonesSplineMBuf(key, keyvals);
     985             : 
     986           2 :   return;
     987           1 : };
     988             : 
     989             : //----------------------------------------------------------------------------
     990             : 
     991           1 : Int GJonesSpline::getKnots (const Vector<Double>& times, Vector<Double>& knots)
     992             : {
     993             : // Compute the number and location of the spline knots
     994             : // Input:
     995             : //    times        const Vector<Double>&    Vector of time values
     996             : // Output:
     997             : //    knots        Vector<Double>&          Knot positions
     998             : //    getKnots     Int                      Number of knots
     999             : //
    1000           2 :   LogIO os (LogOrigin("GJonesSpline", "getKnots()", WHERE));
    1001             : 
    1002             :   // Use algorithm in GILDAS, with user-defined timescale
    1003           1 :   Int n=times.nelements();
    1004           1 :   Int nSeg = Int(0.5 + (times(n-1)-times(0))/splinetime_p);
    1005           1 :   nSeg = max(1,nSeg);     // never fewer than 1, obviously
    1006           1 :   Int ncenterKnots = nSeg -1;
    1007           1 :   Double step = (times(n-1) - times(0)) / nSeg;
    1008             : 
    1009             :   os << LogIO::NORMAL
    1010             :      << "Gridded splinetime = " << step << " sec."
    1011           1 :      << LogIO::POST;
    1012             : 
    1013           1 :   Int numOfknots = ncenterKnots + 8; 
    1014             :   //cout << "numOfknots" << numOfknots << endl;
    1015           1 :   knots.resize(numOfknots);
    1016           1 :   knots(0)=knots(1) = knots(2) = knots(3) = times(0);
    1017           1 :   knots(numOfknots-1) = knots(numOfknots-2) = knots(numOfknots-3) =
    1018           1 :     knots(numOfknots-4)=times(n-1);
    1019           2 :   for(Int k=0; k < ncenterKnots; k++){
    1020           1 :     knots(k+4) = times(0)+ (k + 1) * step;
    1021             :   }
    1022             : 
    1023           1 :   return numOfknots;
    1024           1 : };
    1025             : 
    1026             : //----------------------------------------------------------------------------
    1027             : 
    1028           1 : void GJonesSpline::updateCalTable (const Vector<Int>& fieldIdKeys,
    1029             :                                    const Vector<Int>& antennaId,
    1030             :                                    const Vector<String>& freqGrpName,
    1031             :                                    const Vector<String>& polyType,
    1032             :                                    const Vector<String>& polyMode,
    1033             :                                    const Vector<Complex>& scaleFactor,
    1034             :                                    const Matrix<Double>& polyCoeffAmp,
    1035             :                                    const Matrix<Double>& polyCoeffPhase,
    1036             :                                    const Vector<String>& phaseUnits,
    1037             :                                    const Vector<Double>& splineKnotsAmp,
    1038             :                                    const Vector<Double>& splineKnotsPhase,
    1039             :                                    const Vector<MFrequency>& refFreq,
    1040             :                                    const Vector<Int>& refAnt)
    1041             : {
    1042             : // Update the output calibration table
    1043             : // Input:
    1044             : //    fieldIdKeys      const Vec<Int>&        Field id.'s to span
    1045             : //    antennaId        const Vec<Int>&        Antenna id. for each solution
    1046             : //    freqGrpName      const Vec<String>&     Freq. group name (per soln.)
    1047             : //    polyType         const Vec<String>&     Polynomial type (per soln.)
    1048             : //    polyMode         const Vec<String>&     Polynomial mode (per soln.)
    1049             : //    scaleFactor      const Vec<Complex>&    Polynomial scale factor 
    1050             : //                                            (per solution)
    1051             : //    polyCoeffAmp     const Matrix<Double>&  Polynomial amplitude 
    1052             : //                                            coefficients (per solution)
    1053             : //    polyCoeffPhase   const Matrix<Double>&  Polynomial phase coefficients
    1054             : //                                            (per solution)
    1055             : //    phaseUnits       const Vec<String>&     Phase units
    1056             : //    splineKnotsAmp   const Vector<Double>&  Amp. spline knot positions
    1057             : //                                            (same for all solutions)
    1058             : //    splineKnotsPhase const Vector<Double>&  Phase spline knot positions
    1059             : //                                            (same for all solutions)
    1060             : //    refFreq          const Vec<MFreq>&      Reference freq. (per soln.)
    1061             : //    refAnt           const Vec<Int>&        Reference antenna (per soln.)
    1062             : //
    1063           2 :   LogIO os (LogOrigin("GJonesSpline", "updateCalTable", WHERE));
    1064             : 
    1065             :   // Add each solution to the calibration buffer
    1066          11 :   for (uInt k=0; k < antennaId.nelements(); k++) {
    1067          30 :     for (uInt j=0; j < fieldIdKeys.nelements(); j++) {
    1068             :       // Find matching rows for this antenna and field id.
    1069             :       Vector<Int> matchingRows = 
    1070          20 :         calBuffer_p->matchAntenna1AndFieldId(antennaId(k), fieldIdKeys(j));
    1071             : 
    1072             :       // Update the matching rows in the calibration buffer
    1073          40 :       calBuffer_p->fillMatchingRows(matchingRows, freqGrpName(k), polyType(k), 
    1074          20 :                                     polyMode(k), scaleFactor(k), 
    1075          40 :                                     polyCoeffAmp.row(k).nelements()/2,
    1076          40 :                                     polyCoeffPhase.row(k).nelements()/2,
    1077          40 :                                     polyCoeffAmp.row(k), polyCoeffPhase.row(k),
    1078          20 :                                     phaseUnits(k), splineKnotsAmp.nelements(),
    1079          20 :                                     splineKnotsPhase.nelements(),
    1080             :                                     splineKnotsAmp, splineKnotsPhase,
    1081          20 :                                     refFreq(k), refAnt(k));
    1082          20 :     };
    1083             :   };
    1084             : 
    1085             :   //  calBuffer_p->fieldId().set(-1);
    1086           1 :   calBuffer_p->calDescId().set(0);
    1087             :   //  cout << "Time = " << MVTime(solTimeStamp_p/C::day).string(MVTime::YMD,7) << endl;
    1088           1 :   calBuffer_p->timeMeas().set(MEpoch(MVEpoch(solTimeStamp_p/86400.0)));
    1089             : 
    1090             :   // Delete the output calibration table if it already exists
    1091           1 :   if (calTableName()!="" && TableUtil::canDeleteTable(calTableName())) {
    1092           0 :     TableUtil::deleteTable(calTableName());
    1093             :   };
    1094             : 
    1095             :   os << LogIO::NORMAL
    1096           1 :      << "Storing solutions in table " << calTableName()
    1097           1 :      << LogIO::POST;
    1098             : 
    1099             :   // Write the calibration buffer to the output calibration table
    1100           1 :   Table::TableOption accessMode = Table::New;
    1101           1 :   if (Table::isWritable(calTableName())) accessMode = Table::Update;
    1102           1 :   GJonesSplineTable calTable(calTableName(), accessMode);
    1103           1 :   calBuffer_p->append(calTable);
    1104             : 
    1105             : 
    1106             :   // Add CAL_DESC
    1107           1 :   CalDescRecord cdr;
    1108           1 :   cdr.defineSpwId(Vector<Int>(1,-1));
    1109           1 :   cdr.defineMSName(Path(msName()).baseName());
    1110           1 :   calTable.putRowDesc(0,cdr);
    1111             : 
    1112           2 :   return;
    1113           1 : };
    1114             : 
    1115             : //----------------------------------------------------------------------------
    1116             : 
    1117           0 : Double GJonesSpline::getSplineVal (Double x, 
    1118             :                                    Vector<Double>& knots,
    1119             :                                    Vector<Double>& coeff)
    1120             : {
    1121             : // Compute a polynomial spline value using the GILDAS routine getbspl
    1122             : // Input:
    1123             : //    x             Double                   Value at which to compute spline
    1124             : //    knots         Vector<Double>&          Knot locations
    1125             : //    coeff         Vector<Double>&          Spline coefficients
    1126             : // Output:
    1127             : //    getSplineVal  Double                   Computed spline value
    1128             : //
    1129           0 :   LogIO os (LogOrigin("GJonesSpline", "getSplineVal()", WHERE));
    1130             : 
    1131             :   // Use GILDAS library routine, getbspl
    1132           0 :   Int numOfknots=knots.nelements();
    1133             :   Int failflag;
    1134             :   Bool dum;
    1135             :   Double yval;
    1136           0 :   getbspl(&numOfknots, 
    1137             :           knots.getStorage(dum),
    1138             :           coeff.getStorage(dum),
    1139             :           &x,
    1140             :           &yval,
    1141             :           &failflag);
    1142           0 :   return yval;
    1143           0 : }
    1144             : 
    1145             : //----------------------------------------------------------------------------
    1146           0 : void GJonesSpline::plotsolve(const Vector<Double>& x, 
    1147             :                            const Matrix<Double>& yall, 
    1148             :                            const Matrix<Double>& weightall, 
    1149             :                            const Vector<Double>& errall, 
    1150             :                            Matrix<Double>& coeff, Bool phasesoln){
    1151             : 
    1152             : 
    1153             : 
    1154             :   // Function to plot and compare Bandpass data and solution
    1155             :   // Input:
    1156             :   // x - vector of frequecies
    1157             :   // yall - matrix of data - shape is yall(freqindex, baselineindex)
    1158             :   // weightall - matrix of weight; same shape as yall
    1159             :   // errall - error of fits for each baseline
    1160             :   // coeff - matrix coefficients of polynomial fits -shape coeff(nant, degree)
    1161             :   // phasesoln - either phase or amplitude plot
    1162             : 
    1163             : 
    1164           0 :   LogIO os (LogOrigin("GJonesSpline", "plotsolve()", WHERE));
    1165             : 
    1166           0 :   String device;
    1167           0 :   device = calTableName();
    1168           0 :   if (phasesoln){
    1169           0 :     device = device + ".PHASE.ps/cps";
    1170             :   }
    1171             :   else{
    1172           0 :     device = device + ".AMP.ps/cps";
    1173             :   }
    1174             : 
    1175             :   os << LogIO::NORMAL 
    1176             :      << "Generating plot file: " << device
    1177           0 :      << LogIO::POST;
    1178             : 
    1179           0 :   PGPlotter pg(device);
    1180           0 :   pg.subp(4,3);
    1181           0 :   Vector<Double> knots;
    1182           0 :   getKnots(x,knots);
    1183           0 :   Int numpoints= max(x.shape().asVector());
    1184           0 :   Int numplotpoints=20*numpoints;
    1185           0 :   Int num_valid_points=0;
    1186           0 :   Vector<Float> x1(numpoints);
    1187           0 :   Vector<Float> y1(numpoints);
    1188           0 :   Vector<Float> errarray(numpoints); 
    1189           0 :   Vector<Double>  xval(numplotpoints);
    1190           0 :   Vector<Float> xfloatval(numplotpoints);
    1191           0 :   Vector<Float> soly1(numplotpoints);
    1192           0 :   Vector<Double> y, weight;
    1193             :   Double err;
    1194           0 :   Int num_ant = nAnt();
    1195           0 :   Vector<Double> ant1coeff, ant2coeff; 
    1196             : 
    1197             :   //  Float max_data, min_data, max_err;
    1198             :   //  max_err=max(errall);
    1199             :   //  max_data=max(yall)+1.5*max_err;
    1200             :   //  min_data=min(yall)-1.5*max_err;
    1201             : 
    1202           0 :   for (Int ant1=0; ant1 < num_ant; ++ant1){
    1203           0 :     for (Int ant2=ant1+1; ant2 < num_ant; ++ant2){
    1204           0 :       Int basnum=ant1*num_ant-ant1*(ant1+1)/2+ant2-1-ant1;
    1205             : 
    1206           0 :       x1.resize(numpoints);
    1207           0 :       y1.resize(numpoints);
    1208           0 :       errarray.resize(numpoints);
    1209           0 :       y.resize(); 
    1210           0 :       weight.resize();
    1211           0 :       ant1coeff=coeff.row(ant1);
    1212           0 :       ant2coeff=coeff.row(ant2);
    1213           0 :       y=yall.column(basnum);
    1214           0 :       weight=weightall.column(basnum);  
    1215           0 :       err=errall[basnum];
    1216           0 :       num_valid_points=0;
    1217             : 
    1218           0 :       for(Int k=0; k < numpoints; k++){
    1219           0 :         if (weight(k)>0){
    1220           0 :           x1(num_valid_points)=x(k)-x(0);
    1221           0 :           y1(num_valid_points)=y(k);
    1222           0 :           if(phasesoln==true){
    1223           0 :             y1(num_valid_points)=remainder(y1(num_valid_points), 2*C::pi);
    1224           0 :             y1(num_valid_points)=y1(num_valid_points)/C::pi*180.0;
    1225           0 :             errarray(num_valid_points)=Float(err)*180.0/C::pi;
    1226             :           } 
    1227             :           else{
    1228           0 :             y1(num_valid_points)=exp(y1(num_valid_points));
    1229           0 :             errarray(num_valid_points)=Float(err)*y1(num_valid_points);
    1230             :           }
    1231           0 :           num_valid_points+=1;
    1232             :         }; // weight(k) > 0
    1233             :       }; // for k=0
    1234             :       
    1235           0 :       if(num_valid_points == 0){
    1236           0 :         cout << "No valid point on baselines with antennas " 
    1237           0 :              <<  ant1 << " & " << ant2 << endl;
    1238           0 :         return;  
    1239             :       }
    1240             : 
    1241           0 :       for(Int k=0; k < numplotpoints; k++){
    1242           0 :         xval[k]= (k)*((x[numpoints-1]-x[0]))/Double(numplotpoints-1)
    1243           0 :           +(x[0]);      
    1244             :         
    1245           0 :         if(phasesoln==true){
    1246           0 :           soly1(k)=0; 
    1247             :           Double xx, yy1, yy2;
    1248           0 :           xx=xval[k];
    1249           0 :           yy1=getSplineVal(xx, knots, ant1coeff);
    1250           0 :           yy2=getSplineVal(xx, knots, ant2coeff);
    1251           0 :           soly1(k)=yy2-yy1;
    1252           0 :           while(soly1(k) > C::pi){
    1253           0 :             soly1(k) -= 2.0*(C::pi);
    1254             :           }
    1255           0 :           while(soly1(k) < (-(C::pi))){
    1256           0 :             soly1(k) += 2.0*(C::pi);
    1257             :           }
    1258           0 :           soly1(k)=soly1(k)/(C::pi)*180.0;
    1259             :                       
    1260             :         }
    1261             :         else{
    1262             : 
    1263             :           Double xx, yy1, yy2;
    1264           0 :           xx=xval[k];
    1265           0 :           yy1=getSplineVal(xx, knots, ant1coeff);
    1266           0 :           yy2=getSplineVal(xx, knots, ant2coeff);  
    1267           0 :           soly1[k]=(yy1+yy2);
    1268           0 :           soly1[k]=exp(soly1[k]);
    1269             :           
    1270             :           
    1271             :           
    1272             :         }
    1273             :         
    1274           0 :         xfloatval(k)=Float(xval(k)-xval(0));
    1275             :       }
    1276             : 
    1277             : 
    1278             :       //cout << " Mean of sol " << mean(soly1) << endl;
    1279           0 :       x1.resize(num_valid_points, true);
    1280           0 :       y1.resize(num_valid_points, true);
    1281           0 :       errarray.resize(num_valid_points, true);
    1282           0 :       pg.sci(1);
    1283             : 
    1284             :       Float max_data, min_data, max_err;
    1285           0 :       max_err=max(errarray);
    1286           0 :       max_data=max(y1);
    1287           0 :       min_data=min(y1);
    1288           0 :       max_data=max(max_data, max(soly1))+1.5*max_err;
    1289           0 :       min_data=min(min_data, min(soly1))-1.5*max_err;
    1290             : 
    1291           0 :       Float min_x= min(xfloatval);
    1292           0 :       Float max_x= max(xfloatval);
    1293             : 
    1294           0 :       Float edge=(max_x -min_x)*0.05;
    1295           0 :       min_x-=edge;
    1296           0 :       max_x+=edge;
    1297             : 
    1298           0 :       pg.sch(1.5);
    1299             :       //      pg.env(min_x, max_x, min_data, max_data, 0, 0);
    1300           0 :       pg.page();
    1301           0 :       pg.svp(0.1,0.9,0.15,0.9);
    1302           0 :       pg.swin(min_x,max_x,min_data,max_data);
    1303           0 :       pg.box("BCNST",0.0,0,"BCNST",0.0,0);
    1304             : 
    1305           0 :       ostringstream oos;
    1306           0 :       if(phasesoln){
    1307           0 :         oos << "G SPLINE phase for baseline " << ant1+1 << " & " << ant2+1 ;
    1308           0 :         pg.lab("Time in s", "Phase in deg", " ");
    1309           0 :         pg.mtxt("T",0.75,0.5,0.5,oos);
    1310             :       }
    1311             :       else{
    1312           0 :         oos << "G SPLINE amplitude for baseline " << ant1+1 << " & " << ant2+1 ;
    1313           0 :         pg.lab("Time in s", "Amplitude", " ");
    1314           0 :         pg.mtxt("T",0.75,0.5,0.5,oos);
    1315             :       }
    1316           0 :       pg.sch(0.75);
    1317           0 :       pg.sci(2);
    1318           0 :       pg.errb(6, x1, y1, errarray, 2.0);
    1319           0 :       pg.sci(3);
    1320           0 :       pg.pt(x1, y1, 17);
    1321           0 :       pg.sci(4);
    1322           0 :       pg.line(xfloatval, soly1);
    1323             : 
    1324           0 :     }
    1325             :   }
    1326             : 
    1327           0 : }
    1328             : 
    1329             : //---------------------------------------------------------------------------
    1330             : 
    1331           1 : Vector<Int> GJonesSpline::fieldIdRange()
    1332             : {
    1333             : // Return all field id.'s in the underlying MS
    1334             : // Output:
    1335             : //    fieldIdRange      Vector<Int>        All FIELD_ID's in the MS
    1336             : //
    1337             :   // Open the FIELD sub-table
    1338             : 
    1339           1 :   if (!vs_p) throw(AipsError("Error in GJonesSpline::fieldIdRange()"));
    1340             : 
    1341           1 :   const MSColumns& mscol(vs_p->iter().msColumns());
    1342           1 :   const MSFieldColumns& fldCol(mscol.field());
    1343             : 
    1344             :   // Fill vector containing all field id.'s
    1345           1 :   Vector<Int> retval(fldCol.nrow());
    1346           1 :   indgen(retval);
    1347             : 
    1348           1 :   return retval;
    1349           0 : };
    1350             : 
    1351             : //----------------------------------------------------------------------------
    1352             : 
    1353             : /*  TBD... (no raw phase processing, for now)
    1354             : 
    1355             : void GJonesSpline::setRawPhaseVisSet(VisSet& vs){
    1356             : 
    1357             :   Block<Int> columns(0);
    1358             :   
    1359             :   rawvs_p = new VisSet (vs, columns, DBL_MAX);
    1360             :   rawPhaseRemoval_p=true;
    1361             :   fillRawPhaseBuff();
    1362             : }
    1363             : 
    1364             : void GJonesSpline::fillRawPhaseBuff(){
    1365             : 
    1366             :   //Make a phase array of BaselineIndex and TimeIndex of raw phases
    1367             :   LogIO os (LogOrigin("GJonesSpline", "fillRawPhaseBuff()", WHERE));
    1368             : 
    1369             : 
    1370             :  // Use the iterator from the underlying visibility set,
    1371             :   // and attach a visibility data buffer
    1372             :   VisIter& vi(rawvs_p->iter());
    1373             :   VisBuffer vb(vi);
    1374             : 
    1375             :   // Initialize stuff
    1376             :   // SimpleOrderedMap<String,Int> timeValueMap(0);
    1377             :   Vector<Double> timeValues;
    1378             :   PtrBlock<Vector<Complex>* > rawVisTimeSeries;
    1379             :   PtrBlock<Vector<Double>* > weightTimeSeries;
    1380             :   Int nTimeSeries = 0;
    1381             : 
    1382             :   // Initialize the baseline index
    1383             :   Int nAnt = vs_p->numberAnt();
    1384             :   Int nBasl = nAnt * (nAnt - 1) / 2;
    1385             : 
    1386             : 
    1387             :   // Iterate, accumulating the averaged visibility time-series
    1388             :   Int chunk;
    1389             : 
    1390             :   for (chunk=0, vi.originChunks(); vi.moreChunks(); vi.nextChunk(), chunk++) {
    1391             :     // Extract the current visibility buffer spectral window id.
    1392             :     // and number for frequency channels
    1393             :     Int spwid = vi.spectralWindow();
    1394             :     Int nChan = rawvs_p->numberChan()(spwid);
    1395             :     String fieldName = vi.fieldName();
    1396             : 
    1397             :     os << LogIO::NORMAL << "Slot= " << (chunk+1) << ", field= "
    1398             :        << fieldName << ", spw= " << spwid+1 
    1399             :        << ", nchan= " << nChan << LogIO::POST;
    1400             : 
    1401             :     //average the buffer across frequency
    1402             :    for(vi.origin(); vi.more(); vi++){
    1403             :  
    1404             :      vb.visibility()=vb.correctedVisibility();
    1405             :      vb.freqAverage();
    1406             : 
    1407             :      //     cout << "AFTER freq aver length" << vb.correctedVisibility().shape().asVector() << endl;
    1408             : 
    1409             :     // Iterate of the current visibility buffer, accumulating
    1410             :     // a common time series in the visibility data
    1411             :     for (Int row=0; row < vb.nRow(); row++) {
    1412             :       // Antenna numbers
    1413             :       Int ant1num = vb.antenna1()(row);
    1414             :       Int ant2num = vb.antenna2()(row);
    1415             : 
    1416             :       // Reject auto-correlation data
    1417             :       if (vb.antenna1()(row) != vb.antenna2()(row)) {
    1418             :         // Compute baseline index
    1419             :         Int baselineIndex = ant1num * nAnt - ant1num * (ant1num + 1) / 2 +
    1420             :           ant2num - 1 - ant1num;
    1421             : 
    1422             :         // Weight
    1423             :         Double rowWeight = vb.weight()(row);
    1424             :         if (rowWeight > 0) {
    1425             :           // Map the current time stamp to a time series index
    1426             :           // using 0.1 second precision, i.e. time values within
    1427             :           // a tenth of a second of each other will be accumulated
    1428             :           // within the same bin.
    1429             :           MVTime mvt(vb.time()(row) / C::day);
    1430             :           String timeKey = mvt.string(MVTime::TIME, 7);
    1431             :           //      cout << "FILL Bef timekey "<< timeKey << " ntimeseries " << nTimeSeries << endl;
    1432             :           Int timeIndex = 0;
    1433             :           // Check the time stamp index to this precision
    1434             :           if (timeValueMap_p.isDefined(timeKey)) {
    1435             :             timeIndex = timeValueMap_p(timeKey);
    1436             :           } else {
    1437             :             // Create a new time series entry
    1438             :             timeIndex = nTimeSeries++;
    1439             :             //      cout << "FILL timekey "<< timeKey << " index " << timeIndex << endl;
    1440             :             timeValueMap_p.define(timeKey, timeIndex);
    1441             :             timeValues.resize(nTimeSeries, true);
    1442             :             timeValues(timeIndex) = vb.time()(row);
    1443             :             rawVisTimeSeries.resize(nTimeSeries, true);
    1444             :             Complex czero(0,0);
    1445             :             rawVisTimeSeries[timeIndex] = new Vector<Complex>(nBasl, czero);
    1446             :             weightTimeSeries.resize(nTimeSeries, true);
    1447             :             weightTimeSeries[timeIndex] = new Vector<Double>(nBasl, 0);
    1448             :           };
    1449             : 
    1450             :           //CAUTION going to use corrected
    1451             :           // Accumulate the current visbility row in the common time series
    1452             :           (*rawVisTimeSeries[timeIndex])(baselineIndex) +=
    1453             :             vb.visibility()(0,row)(0) * rowWeight;
    1454             :           (*weightTimeSeries[timeIndex])(baselineIndex) += rowWeight;
    1455             :         };
    1456             :       };
    1457             :     };
    1458             :     };
    1459             :   }; // for (chunk...) iteration
    1460             : 
    1461             :   Int nTimes = timeValueMap_p.ndefined();
    1462             :   rawPhase_p.resize(nTimes, nBasl);
    1463             :   for (Int k=0; k< nTimes; ++k){
    1464             :     for(Int j=0; j< nBasl; ++j){
    1465             :       //rawPhase_p(k, j)=arg((*(rawVisTimeSeries[k]))(j));
    1466             :       rawPhase_p(k,j)=arg(((*rawVisTimeSeries[k])(j))
    1467             :                   / ((*weightTimeSeries[k])(j)));
    1468             : 
    1469             :     }
    1470             : 
    1471             :   }
    1472             : 
    1473             : 
    1474             : 
    1475             : }
    1476             : 
    1477             : 
    1478             : Double GJonesSpline::getRawPhase(Int ant1, Int ant2, Double time){
    1479             : 
    1480             :   if (ant1 == ant2) return 0.0;
    1481             :   Int nAnt = vs_p->numberAnt();
    1482             :   Bool flip=false;
    1483             :   if(ant1 > ant2){
    1484             :     Int tmp=ant1;
    1485             :     ant1=ant2;
    1486             :     ant2=tmp;
    1487             :     flip=true;
    1488             :   }
    1489             :   Int baselineIndex = ant1 * nAnt - ant1 * (ant1 + 1) / 2 +
    1490             :                       ant2 - 1 - ant1;
    1491             : 
    1492             :   MVTime mvt(time / C::day);
    1493             :   String timeKey = mvt.string(MVTime::TIME, 7);
    1494             :   Int timeIndex=timeValueMap_p(timeKey);
    1495             :   // if (ant1==0 && ant2==1) 
    1496             :   //   cout << "phase 1 2 " << rawPhase_p(timeIndex, baselineIndex)*180.0/C::pi << " Time " << timeKey << endl;
    1497             :   //   cout << " Timekey " << timeKey << "Timeindex " << timeIndex << endl;
    1498             :   if(flip){ 
    1499             :     return -rawPhase_p(timeIndex, baselineIndex);
    1500             :   }
    1501             :   else {
    1502             :     return rawPhase_p(timeIndex, baselineIndex);
    1503             :   }
    1504             : 
    1505             : }
    1506             : 
    1507             : */
    1508             : 
    1509           4 : void GJonesSpline::writeAsciiLog(const String& filename, const Matrix<Double>& coeff, const Vector<Double>& rmsFit, Bool phasesoln){
    1510             : 
    1511           4 :   Int numAnt=coeff.shape().asVector()(0);
    1512           4 :   const char* fil=filename.chars();
    1513           4 :   ofstream outLog(fil);
    1514             : 
    1515           4 :   if(phasesoln){
    1516           2 :     outLog << "*****PHASE summary********"<< endl;
    1517             :   }
    1518             :   else{
    1519           2 :     outLog << "*****AMPLITUDE summary********"<< endl;
    1520             :   }
    1521           4 :     outLog << "Antenna based spline coefficients " << endl;
    1522          44 :   for (Int k=0; k < numAnt; k++){
    1523          40 :     outLog << "  " << k+1 << "   " << coeff.row(k) << endl;
    1524             :     
    1525             :   }
    1526             : 
    1527             : 
    1528           4 :   outLog << " RMS Fit per baseline " << endl;
    1529           4 :   outLog << "Antenna1      Antenna2      rmsfit" << endl;
    1530          44 :   for (Int ant1=0; ant1 < numAnt; ++ant1){
    1531         220 :     for (Int ant2=ant1+1; ant2 < numAnt; ++ant2){
    1532         180 :       Int basnum=ant1*numAnt-ant1*(ant1+1)/2+ant2-1-ant1;
    1533         180 :       outLog << "   " << ant1+1 << "           " << ant2+1 << "            " 
    1534         180 :              << rmsFit[basnum] << endl;  
    1535             :     }
    1536             :   }
    1537           4 : }
    1538             : 
    1539             : } //# NAMESPACE CASA - END
    1540             : 

Generated by: LCOV version 1.16