LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - StandardVisCal.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 139 1121 12.4 %
Date: 2025-12-12 07:32:35 Functions: 12 153 7.8 %

          Line data    Source code
       1             : //# StandardVisCal.cc: Implementation of Standard VisCal types
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2011
       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/StandardVisCal.h>
      28             : #include <synthesis/MeasurementComponents/CalCorruptor.h>
      29             : 
      30             : #include <msvis/MSVis/VisBuffer.h>
      31             : #include <msvis/MSVis/VisBuffAccumulator.h>
      32             : #include <synthesis/CalTables/CTIter.h>
      33             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      34             : #include <synthesis/MeasurementEquations/VisEquation.h>
      35             : #include <synthesis/MeasurementComponents/SolveDataBuffer.h>
      36             : #include <casacore/scimath/Fitting/LSQFit.h>
      37             : #include <casacore/scimath/Fitting/LinearFit.h>
      38             : #include <casacore/scimath/Functionals/CompiledFunction.h>
      39             : #include <casacore/scimath/Functionals/Polynomial.h>
      40             : #include <casacore/scimath/Mathematics/AutoDiff.h>
      41             : #include <casacore/casa/BasicMath/Math.h>
      42             : #include <casacore/tables/TaQL/ExprNode.h>
      43             : 
      44             : #include <casacore/casa/Arrays/ArrayMath.h>
      45             : #include <casacore/casa/Arrays/MatrixMath.h>
      46             : #include <casacore/casa/BasicSL/String.h>
      47             : #include <casacore/casa/Utilities/Assert.h>
      48             : #include <casacore/casa/Utilities/GenSort.h>
      49             : #include <casacore/casa/Exceptions/Error.h>
      50             : #include <casacore/casa/OS/Memory.h>
      51             : #include <casacore/casa/System/Aipsrc.h>
      52             : 
      53             : #include <sstream>
      54             : 
      55             : #include <casacore/measures/Measures/MCBaseline.h>
      56             : #include <casacore/measures/Measures/MDirection.h>
      57             : #include <casacore/measures/Measures/MEpoch.h>
      58             : #include <casacore/measures/Measures/MeasTable.h>
      59             : 
      60             : #include <casacore/casa/Logging/LogMessage.h>
      61             : #include <casacore/casa/Logging/LogSink.h>
      62             : // math.h ?
      63             : 
      64             : using namespace casacore;
      65             : namespace casa { //# NAMESPACE CASA - BEGIN
      66             : 
      67             : 
      68             : // **********************************************************
      69             : //  PJones
      70             : //
      71             : 
      72           0 : PJones::PJones(VisSet& vs) :
      73             :   VisCal(vs), 
      74             :   VisMueller(vs),
      75             :   VisJones(vs),
      76           0 :   pjonestype_(Jones::Diagonal),
      77           0 :   pa_()
      78             : {
      79           0 :   if (prtlev()>2) cout << "P::P(vs)" << endl;
      80           0 : }
      81             : 
      82           0 : PJones::PJones(String msname,Int MSnAnt,Int MSnSpw) :
      83             :   VisCal(msname,MSnAnt,MSnSpw), 
      84             :   VisMueller(msname,MSnAnt,MSnSpw),
      85             :   VisJones(msname,MSnAnt,MSnSpw),
      86           0 :   pjonestype_(Jones::Diagonal),
      87           0 :   pa_()
      88             : {
      89           0 :   if (prtlev()>2) cout << "P::P(msname,MSnAnt,MSnSpw)" << endl;
      90           0 : }
      91             : 
      92          35 : PJones::PJones(const MSMetaInfoForCal& msmc) : 
      93             :   VisCal(msmc),
      94             :   VisMueller(msmc),
      95             :   VisJones(msmc),
      96          35 :   pjonestype_(Jones::Diagonal),
      97          35 :   pa_()
      98             : {
      99          35 :   if (prtlev()>2) cout << "P::P(msmc)" << endl;
     100          35 : }
     101             : 
     102             : 
     103          70 : PJones::~PJones() {
     104          35 :   if (prtlev()>2) cout << "P::~P()" << endl;
     105          70 : }
     106             : 
     107             : // PJones needs to know pol basis and feed pa
     108           0 : void PJones::syncMeta(const VisBuffer& vb) {
     109             : 
     110             :   // Call parent (sets currTime())
     111           0 :   VisJones::syncMeta(vb);
     112             : 
     113             :   // Basis
     114           0 :   if (vb.corrType()(0)==5)         // Circulars
     115           0 :     pjonestype_=Jones::Diagonal;
     116           0 :   else if (vb.corrType()(0)==9)    // Linears
     117           0 :     pjonestype_=Jones::General;
     118             : 
     119             :   // Get parallactic angle from the vb:
     120           0 :   pa().resize(nAnt());
     121           0 :   pa() = vb.feed_pa(currTime());
     122             : 
     123           0 : }
     124             : 
     125             : // PJones needs to know pol basis and feed pa
     126       20184 : void PJones::syncMeta2(const vi::VisBuffer2& vb) {
     127             : 
     128             :   // Call parent (sets currTime())
     129       20184 :   VisJones::syncMeta2(vb);
     130             : 
     131             :   // Basis
     132       20184 :   if (vb.correlationTypes()(0)==5)         // Circulars
     133       15312 :     pjonestype_=Jones::Diagonal;
     134        4872 :   else if (vb.correlationTypes()(0)==9)    // Linears
     135        4872 :     pjonestype_=Jones::General;
     136             : 
     137             :   // Get parallactic angle from the vb:
     138       20184 :   pa().resize(nAnt());
     139       20184 :   pa() = vb.feedPa(currTime());
     140             : 
     141       20184 : }
     142             : 
     143       20184 : void PJones::calcPar() {
     144             : 
     145       20184 :   if (prtlev()>6) cout << "      VC::calcPar()" << endl;
     146             : 
     147             :   // Initialize parameter arrays
     148       20184 :   currCPar().resize(1,1,nAnt());
     149       20184 :   currParOK().resize(1,1,nAnt());
     150       20184 :   currParOK()=true;
     151             : 
     152             :   // Fill currCPar() with exp(i*pa)
     153       20184 :   Float* a=pa().data();
     154       20184 :   Complex* cp=currCPar().data();
     155       20184 :   Double ang(0.0);
     156      222024 :   for (Int iant=0;iant<nAnt();++iant,++a,++cp) {
     157      201840 :     ang=Double(*a);
     158      201840 :     (*cp) = Complex(cos(ang),sin(ang));  // as a complex number
     159             :   }
     160             :   //  cout << "ang = " << ang << endl;
     161             : 
     162             :   // Pars now valid, matrices not
     163       20184 :   validateP();
     164       20184 :   invalidateJ();
     165             : 
     166       20184 : }
     167             : 
     168             : // Calculate a single Jones matrix by some means from parameters
     169      201840 : void PJones::calcOneJones(Vector<Complex>& mat, Vector<Bool>& mOk,
     170             :                           const Vector<Complex>& par, const Vector<Bool>& pOk ) {
     171             : 
     172      201840 :   if (prtlev()>10) cout << "       P::calcOneJones()" << endl;
     173             : 
     174             : 
     175      201840 :   if (pOk(0)) {
     176             : 
     177      201840 :     switch (jonesType()) {
     178             :       // Circular version:
     179      153120 :     case Jones::Diagonal: {
     180      153120 :       mat(0)=conj(par(0));  // exp(-ia)
     181      153120 :       mat(1)=par(0);        // exp(ia)
     182      153120 :       mOk=true;
     183      153120 :       break;
     184             :     }
     185             :       // Linear version:
     186       48720 :     case Jones::General: {
     187       48720 :       Float a=arg(par(0));
     188       48720 :       mat(0)=mat(3)=cos(a);
     189       48720 :       mat(1)=sin(a);
     190       48720 :       mat(2)=-mat(1);
     191       48720 :       mOk=true;
     192       48720 :       break;
     193             :     }
     194           0 :     default:
     195           0 :       throw(AipsError("PJones doesn't know if it is Diag (Circ) or General (Lin)"));
     196             :       break;
     197             : 
     198             :     }
     199             : 
     200             :   }
     201      201840 : }
     202             : 
     203             : 
     204             : 
     205             : // **********************************************************
     206             : //  TJones Implementations
     207             : //
     208             : 
     209           0 : TJones::TJones(VisSet& vs) :
     210             :   VisCal(vs),             // virtual base
     211             :   VisMueller(vs),         // virtual base
     212             :   SolvableVisJones(vs),    // immediate parent
     213           0 :   tcorruptor_p(NULL)
     214             : {
     215           0 :   if (prtlev()>2) cout << "T::T(vs)" << endl;
     216           0 : }
     217             : 
     218           0 : TJones::TJones(String msname,Int MSnAnt,Int MSnSpw) :
     219             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
     220             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
     221             :   SolvableVisJones(msname,MSnAnt,MSnSpw),   // immediate parent
     222           0 :   tcorruptor_p(NULL)
     223             : {
     224           0 :   if (prtlev()>2) cout << "T::T(msname,MSnAnt,MSnSpw)" << endl;
     225           0 : }
     226             : 
     227           0 : TJones::TJones(const MSMetaInfoForCal& msmc) : 
     228             :   VisCal(msmc),
     229             :   VisMueller(msmc),
     230             :   SolvableVisJones(msmc),
     231           0 :   tcorruptor_p(NULL)
     232             : {
     233           0 :   if (prtlev()>2) cout << "T::T(msmc)" << endl;
     234           0 : }
     235             : 
     236             : 
     237           0 : TJones::TJones(const Int& nAnt) :
     238             :   VisCal(nAnt), 
     239             :   VisMueller(nAnt),
     240             :   SolvableVisJones(nAnt),
     241           0 :   tcorruptor_p(NULL)
     242             : {
     243           0 :   if (prtlev()>2) cout << "T::T(nAnt)" << endl;
     244           0 : }
     245             : 
     246           0 : TJones::~TJones() {
     247           0 :   if (prtlev()>2) cout << "T::~T()" << endl;
     248           0 : }
     249             : 
     250           0 : void TJones::guessPar(VisBuffer& vb) {
     251             : 
     252           0 :   if (prtlev()>4) cout << "   T::guessPar(vb)" << endl;
     253             : 
     254             :   // Assumes:  1. corrs in canonical order
     255             :   //           2. vb has 1 channel (has been freq-averaged)
     256             : 
     257             : 
     258             :   // Make an antenna-based guess at T
     259             :   //  Correlation membership-dependence
     260             :   //  nCorr = 1: use icorr=0
     261             :   //  nCorr = 2: use icorr=[0,1]
     262             :   //  nCorr = 4: use icorr=[0,3]
     263             : 
     264           0 :   Int nCorr(1);
     265           0 :   Int nDataCorr(vb.visCube().shape()(0));
     266           0 :   Vector<Int> corridx(1,0);
     267           0 :   if (nDataCorr==2) {
     268           0 :     nCorr=2;
     269           0 :     corridx.resize(nCorr);
     270           0 :     corridx(0)=0;
     271           0 :     corridx(1)=1;
     272             :   } 
     273           0 :   else if (nDataCorr==4) {
     274           0 :     nCorr=2;
     275           0 :     corridx.resize(nCorr);
     276           0 :     corridx(0)=0;
     277           0 :     corridx(1)=3;
     278             :   }
     279             : 
     280             :   // Find out which ants are available
     281             :   // TBD: count nominal guessant rows, insist not much less than nAnt
     282           0 :   Vector<Bool> antok(nAnt(),false);
     283           0 :   Vector<Bool> rowok(vb.nRow(),false);
     284           0 :   for (Int irow=0;irow<vb.nRow();++irow) {
     285             :     // Is this row ok?
     286           0 :     rowok(irow)= (!vb.flagRow()(irow) &&
     287           0 :                   (vb.antenna1()(irow)!=vb.antenna2()(irow)) &&
     288           0 :                   nfalse(vb.flag().column(irow))> 0 );
     289           0 :     if (rowok(irow)) {
     290           0 :       antok(vb.antenna1()(irow))=true;
     291           0 :       antok(vb.antenna2()(irow))=true;
     292             :     }
     293             :   }
     294             : 
     295             :   // Assume refant is the target ant, for starters
     296           0 :   Int guessant(refant());
     297             : 
     298             :   // If no refant specified, or no data for refant
     299             :   //   base first guess on first good ant
     300           0 :   if (guessant<0 || !antok(guessant)) {
     301           0 :     guessant=0;
     302           0 :     while (antok(guessant)<1) guessant++;
     303             :   }
     304             : 
     305           0 :   AlwaysAssert(guessant>-1,AipsError);
     306             : 
     307           0 :   Cube<Complex>& V(vb.visCube());
     308           0 :   Float amp(0.0),ampave(0.0);
     309           0 :   Int namp(0);
     310           0 :   solveCPar()=Complex(0.0);
     311           0 :   for (Int irow=1;irow<vb.nRow();++irow) {  // why not row zero? copied from Calibrator
     312             : 
     313           0 :     if (rowok(irow)) {
     314           0 :       Int a1=vb.antenna1()(irow);
     315           0 :       Int a2=vb.antenna2()(irow);
     316             : 
     317             :       // If this row contains the guessant
     318           0 :       if (a1 == guessant || a2==guessant) {
     319             :       
     320           0 :         for (Int icorr=0;icorr<nCorr;icorr++) {
     321           0 :           Complex& Vi(V(corridx(icorr),0,irow));
     322           0 :           amp=abs(Vi);
     323           0 :           if (amp>0.0f) {
     324           0 :             if (a1 == guessant)
     325           0 :               solveCPar()(0,0,a2)+=(conj(Vi)/amp/Float(nCorr));
     326             :             //        solveCPar()(0,0,a2)+=(conj(Vi)/Float(nCorr));
     327             :             else
     328           0 :               solveCPar()(0,0,a1)+=((Vi)/amp/Float(nCorr));
     329             :             //        solveCPar()(0,0,a1)+=((Vi)/Float(nCorr));
     330             :             
     331           0 :             ampave+=amp;
     332           0 :             namp++;
     333             :             //  cout << "          " << abs(Vi) << " " << arg(Vi)*180.0/M_PI << endl;
     334             :           }
     335             :         }
     336             :       } // guessant in row
     337             :     } // rowok
     338             :   } // irow
     339             : 
     340             :   //  cout << "Guess:" << endl
     341             :   //   << "amp = " << amplitude(solveCPar())
     342             :   //     << endl;
     343             :  
     344             : 
     345             :   // Scale them by the mean amplitude
     346             : 
     347           0 :   if (namp>0) {
     348           0 :     ampave/=Float(namp);
     349           0 :     ampave=sqrt(ampave);
     350             :     //  solveCPar()*=Complex(ampave);
     351           0 :     solveCPar()/=Complex(ampave);
     352           0 :     solveCPar()(0,0,guessant)=Complex(ampave);
     353           0 :     solveCPar()(LogicalArray(amplitude(solveCPar())==0.0f)) = Complex(ampave);
     354             :   }
     355             :   else
     356           0 :     solveCPar()=Complex(0.3);
     357             : 
     358           0 :   solveParOK()=true;
     359             : 
     360             :   /*
     361             :   cout << "Guess:" << endl
     362             :        << "amp = " << amplitude(solveCPar())
     363             :        << "phase = " << phase(solveCPar())
     364             :        << endl;
     365             :   */
     366           0 : }
     367             : 
     368             : 
     369           0 : void TJones::guessPar(SDBList& sdbs,const Bool&) {
     370             : 
     371           0 :   if (prtlev()>4) cout << "   T::guessPar(sdbs)" << endl;
     372             : 
     373             :   // Assumes:  1. corrs in canonical order
     374             :   
     375             :   // Use just the first SDB in the SDBList, for now
     376           0 :   SolveDataBuffer& sdb(sdbs(0));
     377             :   
     378           0 :   AlwaysAssert(sdb.nChannels()==1,AipsError);
     379             :     
     380             :   // Make an antenna-based guess at T
     381             :   //  Correlation membership-dependence
     382             :   //  nCorr = 1: use icorr=0
     383             :   //  nCorr = 2: use icorr=[0,1]
     384             :   //  nCorr = 4: use icorr=[0,3]
     385             :   
     386           0 :   Int nCorr(1);
     387           0 :   Int nDataCorr(sdb.nCorrelations());
     388           0 :   Vector<Int> corridx(1,0);
     389           0 :   if (nDataCorr==2) {
     390           0 :     nCorr=2;
     391           0 :     corridx.resize(nCorr);
     392           0 :     corridx(0)=0;
     393           0 :     corridx(1)=1;
     394             :   } 
     395           0 :   else if (nDataCorr==4) {
     396           0 :     nCorr=2;
     397           0 :     corridx.resize(nCorr);
     398           0 :     corridx(0)=0;
     399           0 :     corridx(1)=3;
     400             :   }
     401             :   
     402             :   // Find out which ants are available
     403             :   // TBD: count nominal guessant rows, insist not much less than nAnt
     404           0 :   Int nRow=sdb.nRows();
     405           0 :   Vector<Bool> antok(nAnt(),False);
     406           0 :   Vector<Bool> rowok(nRow,False);
     407           0 :   for (Int irow=0;irow<nRow;++irow) {
     408           0 :     const Int& a1(sdb.antenna1()(irow));
     409           0 :     const Int& a2(sdb.antenna2()(irow));
     410             :     // Is this row ok?
     411           0 :     rowok(irow)= (!sdb.flagRow()(irow) &&
     412           0 :                   (a1!=a2) &&
     413           0 :                   nfalse(sdb.flagCube().xyPlane(irow))> 0 );
     414           0 :     if (rowok(irow)) {
     415           0 :       antok(a1)=True;
     416           0 :       antok(a2)=True;
     417             :     }
     418             :   }
     419             :   
     420             :   // Assume refant is the target ant, for starters
     421           0 :   Int guessant(refant());
     422             :   
     423             :   // If no refant specified, or no data for refant
     424             :   //   base first guess on first good ant
     425           0 :   if (guessant<0 || !antok(guessant)) {
     426           0 :     guessant=0;
     427           0 :     while (antok(guessant)<1) guessant++;
     428             :   }
     429             :   
     430           0 :   AlwaysAssert(guessant>-1,AipsError);
     431             :   
     432           0 :   const Cube<Complex>& V(sdb.visCubeCorrected());
     433           0 :   Float amp(0.0),ampave(0.0);
     434           0 :   Int namp(0);
     435           0 :   solveCPar()=Complex(0.0);
     436           0 :   for (Int irow=1;irow<nRow;++irow) {  // why not row zero? copied from Calibrator
     437             :     
     438           0 :     if (rowok(irow)) {
     439           0 :       const Int& a1(sdb.antenna1()(irow));
     440           0 :       const Int& a2(sdb.antenna2()(irow));
     441             :       
     442             :       // If this row contains the guessant
     443           0 :       if (a1 == guessant || a2==guessant) {
     444             :         
     445           0 :         for (Int icorr=0;icorr<nCorr;icorr++) {
     446           0 :           const Complex& Vi(V(corridx(icorr),0,irow));
     447           0 :           amp=abs(Vi);
     448           0 :           if (amp>0.0f) {
     449           0 :             if (a1 == guessant)
     450           0 :               solveCPar()(0,0,a2)+=(conj(Vi)/amp/Float(nCorr));
     451             :             //        solveCPar()(0,0,a2)+=(conj(Vi)/Float(nCorr));
     452             :             else
     453           0 :               solveCPar()(0,0,a1)+=((Vi)/amp/Float(nCorr));
     454             :             //        solveCPar()(0,0,a1)+=((Vi)/Float(nCorr));
     455             :             
     456           0 :             ampave+=amp;
     457           0 :             namp++;
     458             :             //  cout << "          " << abs(Vi) << " " << arg(Vi)*180.0/M_PI << endl;
     459             :           }
     460             :         }
     461             :       } // guessant in row
     462             :     } // rowok
     463             :   } // irow
     464             :   
     465             :   //  cout << "Guess:" << endl
     466             :   //   << "amp = " << amplitude(solveCPar())
     467             :   //     << endl;
     468             :   
     469             : 
     470             :   // Scale them by the mean amplitude
     471             : 
     472           0 :   if (namp>0) {
     473           0 :     ampave/=Float(namp);
     474           0 :     ampave=sqrt(ampave);
     475             :     //  solveCPar()*=Complex(ampave);
     476           0 :     solveCPar()/=Complex(ampave);
     477           0 :     solveCPar()(0,0,guessant)=Complex(ampave);
     478           0 :     solveCPar()(LogicalArray(amplitude(solveCPar())==0.0f)) = Complex(ampave);
     479             :   }
     480             :   else
     481           0 :     solveCPar()=Complex(0.3);
     482             :   
     483           0 :   solveParOK()=True;
     484             :   
     485             :   /*
     486             :     cout << "Guess:" << endl
     487             :     << "amp = " << amplitude(solveCPar())
     488             :     << "phase = " << phase(solveCPar())
     489             :     << endl;
     490             :   */
     491           0 : }
     492             : 
     493             : // Fill the trivial DJ matrix elements
     494           0 : void TJones::initTrivDJ() {
     495             : 
     496           0 :   if (prtlev()>4) cout << "   T::initTrivDJ" << endl;
     497             : 
     498             :   // Must be trivial
     499           0 :   AlwaysAssert((trivialDJ()),AipsError);
     500             : 
     501             :   // This is the unit matrix
     502             :   //  TBD: could we use a Jones::Unit type instead?
     503           0 :   diffJElem().resize(IPosition(4,1,1,1,1));
     504           0 :   diffJElem()=Complex(1.0);
     505             : 
     506           0 : }
     507             : 
     508             : // Same as GJones setSolve?
     509           0 : void TJones::setSolve(const Record& solve) {
     510             : 
     511             :   // call parent to get general stuff
     512           0 :   SolvableVisJones::setSolve(solve);
     513             : 
     514             :   // parse solmode and rmsthresh
     515           0 :   solmode()=String("");
     516           0 :   if (solve.isDefined("solmode"))
     517           0 :     solmode()=solve.asString("solmode");
     518           0 :   solmode().upcase();
     519           0 :   rmsthresh().resize(0);
     520           0 :   if (solve.isDefined("rmsthresh")) {
     521           0 :     Vector<Double> rmsth;
     522           0 :     rmsth=solve.asArrayDouble("rmsthresh");  // parse from record as Vector<Double>
     523           0 :     Int nrms=rmsth.nelements();
     524           0 :     rmsthresh().resize(0);
     525           0 :     if (nrms>0) {
     526           0 :       rmsthresh().resize(nrms);
     527           0 :       convertArray(rmsthresh(), rmsth); // convert into Float array
     528             :     }
     529           0 :   }
     530           0 :   Int nrms=rmsthresh().nelements();
     531           0 :   if (nrms==0 && solmode().contains("R")) {
     532           0 :     rmsthresh().assign(Vector<Float>(std::vector<Float>({7.0,5.0,4.0,3.5,3.0,2.8,2.6,2.4,2.2,2.5})));
     533             :   }
     534             : 
     535           0 :   if (typeName()=="G Jones" || typeName()=="T Jones") {
     536           0 :     if (solmode().contains("L1"))
     537           0 :       logSink() << "Doing L1 solution." << LogIO::POST;
     538           0 :     if (solmode().contains("R"))
     539           0 :       logSink() << "Doing iterative outlier rejection using thresholds=" << rmsthresh() << LogIO::POST;
     540             :   }
     541             : 
     542             : 
     543           0 : }
     544             : 
     545             : 
     546             : 
     547             : //============================================================
     548             : 
     549             : 
     550           0 : void TJones::createCorruptor(const VisIter& vi, const Record& simpar, const Int nSim) {
     551           0 :   LogIO os(LogOrigin("T", "createCorruptor()", WHERE));
     552             : 
     553           0 :   tcorruptor_p = new AtmosCorruptor(nSim);
     554           0 :   corruptor_p=tcorruptor_p;
     555             : 
     556             :   // call generic parent to set corr,spw,etc info
     557           0 :   SolvableVisCal::createCorruptor(vi,simpar,nSim);
     558             :   
     559           0 :   Int Seed(1234);
     560           0 :   if (simpar.isDefined("seed")) {    
     561           0 :     Seed=simpar.asInt("seed");
     562             :   }
     563             :   
     564           0 :   Int rxType(0); // 0=2SB, 1=DSB
     565           0 :   if (simpar.isDefined("rxType")) {    
     566           0 :     rxType=simpar.asInt("rxType");
     567             :   }
     568             :   
     569           0 :   Float Beta(1.1); // exponent for generalized 1/f noise
     570           0 :   if (simpar.isDefined("beta")) {    
     571           0 :     Beta=simpar.asFloat("beta");
     572             :   }
     573             :   
     574           0 :   if (simpar.isDefined("mean_pwv"))
     575           0 :     tcorruptor_p->mean_pwv() = simpar.asFloat("mean_pwv");
     576             :   
     577           0 :   if (tcorruptor_p->mean_pwv()<=0)
     578           0 :     throw(AipsError("AtmCorruptor attempted initialization with undefined PWV"));
     579             :   
     580           0 :   if (simpar.isDefined("mode")) {    
     581           0 :     if (prtlev()>2) 
     582           0 :       cout << "initializing T:Corruptor with mode " << simpar.asString("mode") << endl;
     583           0 :        String simMode=simpar.asString("mode");
     584             :     
     585           0 :     if (simMode == "test")
     586           0 :       tcorruptor_p->initialize(rxType);
     587           0 :     else if (simMode == "individual" or simMode == "screen") {
     588             : 
     589           0 :       Float Scale(1.); // RELATIVE scale of fluctuations (to mean_pwv)
     590           0 :       if (simpar.isDefined("delta_pwv")) {
     591           0 :         if (simpar.asFloat("delta_pwv")>1.) {
     592           0 :           Scale=1.;
     593           0 :           os << LogIO::WARN << " decreasing PWV fluctuation magnitude to 100% of the mean PWV " << LogIO::POST;  
     594             :         } else {
     595           0 :           Scale=simpar.asFloat("delta_pwv");
     596             :         }
     597             :       } else {
     598           0 :         os << LogIO::WARN << " setting PWV fluctuation magnitude to 15% of the mean PWV " << LogIO::POST;  
     599           0 :         Scale=0.15;
     600             :       }
     601             :       
     602           0 :       os << " PWV fluctuations = " << Scale << " of mean PWV which is " << simpar.asFloat("mean_pwv") << "mm " << LogIO::POST;  
     603             :       
     604             :       
     605             :       // slot_times for a fBM-based corruption need to be even even if solTimes are not
     606             :       // so will define startTime and stopTime and reset nsim() here.
     607             :       
     608           0 :       if (simpar.isDefined("startTime")) {    
     609           0 :         corruptor_p->startTime() = simpar.asDouble("startTime");   
     610             :       } else {
     611           0 :         throw(AipsError("start/stop time not defined"));
     612             :       }
     613           0 :       if (simpar.isDefined("stopTime")) {    
     614           0 :         corruptor_p->stopTime() = simpar.asDouble("stopTime");
     615             :       } else {
     616           0 :         throw(AipsError("start/stop time not defined"));
     617             :       }
     618             : 
     619             :       // RI todo T::createCorr make min screen granularity a user parameter
     620           0 :       Float minFBM_interval = 0.1; // generate screens on >0.1s intervals
     621           0 :       Float defaultFBM_interval = 10.; 
     622           0 :       Float fBM_interval=max(interval(), minFBM_interval); 
     623           0 :       if (interval() <= 0.){ // use default value
     624           0 :         fBM_interval = defaultFBM_interval;
     625           0 :       } else if ( (fBM_interval - interval()) > 1E-5 ){
     626           0 :         os << LogIO::WARN << " Requested phase screen time granularity (" << interval() 
     627           0 :            << " s) is too small! Will use the minimum permitted value: " << minFBM_interval << " s." <<  LogIO::POST;
     628             :       }
     629             : 
     630           0 :       corruptor_p->setEvenSlots(fBM_interval);
     631             : 
     632           0 :       if (simpar.asString("mode") == "individual") 
     633           0 :         tcorruptor_p->initialize(Seed,Beta,Scale,rxType);
     634           0 :       else if (simpar.asString("mode") == "screen") {
     635           0 :         const MSAntennaColumns& antcols(vi.msColumns().antenna());
     636           0 :         if (simpar.isDefined("windspeed")) {
     637           0 :           tcorruptor_p->windspeed()=simpar.asFloat("windspeed");
     638           0 :           tcorruptor_p->initialize(Seed,Beta,Scale,rxType,antcols);
     639             :         } else
     640           0 :           throw(AipsError("Unknown wind speed for T:Corruptor"));        
     641             :       }
     642             : 
     643           0 :     } else if (simMode == "tsys-atm" or simMode == "tsys-manual") {
     644             :       // NEW 20100818 change from Mf to Tf
     645             :       // M corruptor initialization didn't matter M or Mf here - it checks mode in 
     646             :       // the Atmoscorruptor init.
     647           0 :       tcorruptor_p->initialize(vi,simpar,VisCal::T,rxType); 
     648           0 :       extraTag()="NoiseScale"; // collapseForSim catches this
     649             :     
     650             :     } else 
     651           0 :         throw(AipsError("Unknown mode for T:Corruptor"));        
     652           0 :   } else {
     653           0 :     throw(AipsError("No Mode specified for T:Corruptor."));
     654             :   }  
     655           0 : }
     656             : 
     657             : 
     658             : 
     659             : 
     660             : 
     661             : // **********************************************************
     662             : //  TfJones Implementations
     663             : //
     664             : 
     665           0 : TfJones::TfJones(VisSet& vs) :
     666             :   VisCal(vs),             // virtual base
     667             :   VisMueller(vs),         // virtual base
     668           0 :   TJones(vs)              // immediate parent
     669             : {
     670           0 :   if (prtlev()>2) cout << "Tf::Tf(vs)" << endl;
     671           0 : }
     672             : 
     673           0 : TfJones::TfJones(String msname,Int MSnAnt,Int MSnSpw) :
     674             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
     675             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
     676           0 :   TJones(msname,MSnAnt,MSnSpw)              // immediate parent
     677             : {
     678           0 :   if (prtlev()>2) cout << "Tf::Tf(msname,MSnAnt,MSnSpw)" << endl;
     679           0 : }
     680             : 
     681           0 : TfJones::TfJones(const MSMetaInfoForCal& msmc) :
     682             :   VisCal(msmc),             // virtual base
     683             :   VisMueller(msmc),         // virtual base
     684           0 :   TJones(msmc)              // immediate parent
     685             : {
     686           0 :   if (prtlev()>2) cout << "Tf::Tf(msmc)" << endl;
     687           0 : }
     688             : 
     689             : 
     690           0 : TfJones::TfJones(const Int& nAnt) :
     691             :   VisCal(nAnt), 
     692             :   VisMueller(nAnt),
     693           0 :   TJones(nAnt)
     694             : {
     695           0 :   if (prtlev()>2) cout << "Tf::Tf(nAnt)" << endl;
     696           0 : }
     697             : 
     698           0 : TfJones::~TfJones() {
     699           0 :   if (prtlev()>2) cout << "Tf::~Tf()" << endl;
     700           0 : }
     701             : 
     702             : 
     703             : // **********************************************************
     704             : //  GJones Implementations
     705             : //
     706             : 
     707           0 : GJones::GJones(VisSet& vs) :
     708             :   VisCal(vs),             // virtual base
     709             :   VisMueller(vs),         // virtual base
     710             :   SolvableVisJones(vs),    // immediate parent
     711           0 :   gcorruptor_p(NULL)
     712             : {
     713           0 :   if (prtlev()>2) cout << "G::G(vs)" << endl;
     714           0 : }
     715             : 
     716           0 : GJones::GJones(String msname,Int MSnAnt,Int MSnSpw) :
     717             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
     718             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
     719             :   SolvableVisJones(msname,MSnAnt,MSnSpw),    // immediate parent
     720           0 :   gcorruptor_p(NULL)
     721             : {
     722           0 :   if (prtlev()>2) cout << "G::G(msname,MSnAnt,MSnSpw)" << endl;
     723           0 : }
     724             : 
     725           1 : GJones::GJones(const MSMetaInfoForCal& msmc) :
     726             :   VisCal(msmc),             // virtual base
     727             :   VisMueller(msmc),         // virtual base
     728             :   SolvableVisJones(msmc),    // immediate parent
     729           1 :   gcorruptor_p(NULL)
     730             : {
     731           1 :   if (prtlev()>2) cout << "G::G(msmc)" << endl;
     732           1 : }
     733             : 
     734           0 : GJones::GJones(const Int& nAnt) :
     735             :   VisCal(nAnt), 
     736             :   VisMueller(nAnt),
     737             :   SolvableVisJones(nAnt),
     738           0 :   gcorruptor_p(NULL)
     739             : {
     740           0 :   if (prtlev()>2) cout << "G::G(nAnt)" << endl;
     741           0 : }
     742             : 
     743           2 : GJones::~GJones() {
     744           1 :   if (prtlev()>2) cout << "G::~G()" << endl;
     745           2 : }
     746             : 
     747           1 : void GJones::setSolve(const Record& solve) {
     748             : 
     749             :   // call parent to get general stuff
     750           1 :   SolvableVisJones::setSolve(solve);
     751             : 
     752             :   // parse solmode and rmsthresh
     753           1 :   solmode()=String("");
     754           1 :   if (solve.isDefined("solmode"))
     755           1 :     solmode()=solve.asString("solmode");
     756           1 :   solmode().upcase();
     757           1 :   rmsthresh().resize(0);
     758           1 :   if (solve.isDefined("rmsthresh")) {
     759           1 :     Vector<Double> rmsth;
     760           1 :     rmsth=solve.asArrayDouble("rmsthresh");  // parse from record as Vector<Double>
     761           1 :     Int nrms=rmsth.nelements();
     762           1 :     rmsthresh().resize(0);
     763           1 :     if (nrms>0) {
     764           0 :       rmsthresh().resize(nrms);
     765           0 :       convertArray(rmsthresh(), rmsth); // convert into Float array
     766             :     }
     767           1 :   }
     768           1 :   Int nrms=rmsthresh().nelements();
     769           1 :   if (nrms==0 && solmode().contains("R")) {
     770           0 :     rmsthresh().assign(Vector<Float>(std::vector<Float>({7.0,5.0,4.0,3.5,3.0,2.8,2.6,2.4,2.2,2.5})));
     771             :   }
     772             : 
     773           1 :   if (typeName()=="G Jones" || typeName()=="T Jones") {
     774           1 :     if (solmode().contains("L1"))
     775           0 :       logSink() << "Doing L1 solution." << LogIO::POST;
     776           1 :     if (solmode().contains("R"))
     777           0 :       logSink() << "Doing iterative outlier rejection using thresholds=" << rmsthresh() << LogIO::POST;
     778             :   }
     779             : 
     780             : 
     781           1 : }
     782             : 
     783             : 
     784           0 : void GJones::guessPar(VisBuffer& vb) {
     785             : 
     786           0 :   if (prtlev()>4) cout << "   G::guessPar(vb)" << endl;
     787             : 
     788             :   // Make a guess at antenna-based G
     789             :   //  Correlation membership-dependencexm
     790             :   //  assumes corrs in canonical order
     791             :   //  nCorr = 1: use icorr=0
     792             :   //  nCorr = 2: use icorr=[0,1]
     793             :   //  nCorr = 4: use icorr=[0,3]
     794             : 
     795           0 :   Int nCorr(2);
     796           0 :   Int nDataCorr(vb.visCube().shape()(0));
     797           0 :   Vector<Int> corridx(nCorr,0);
     798           0 :   if (nDataCorr==2) {
     799           0 :     corridx(0)=0;
     800           0 :     corridx(1)=1;
     801             :   } 
     802           0 :   else if (nDataCorr==4) {
     803           0 :     corridx(0)=0;
     804           0 :     corridx(1)=3;
     805             :   }
     806             : 
     807           0 :   Int guesschan(vb.visCube().shape()(1)-1);
     808             : 
     809             :   //  cout << "guesschan = " << guesschan << endl;
     810             :   //  cout << "nCorr = " << nCorr << endl;
     811             :   //  cout << "corridx = " << corridx << endl;
     812             : 
     813             : 
     814             :   // Find out which ants are available
     815           0 :   Vector<Int> antok(nAnt(),0);
     816           0 :   Vector<Bool> rowok(vb.nRow(),false);
     817           0 :   for (Int irow=0;irow<vb.nRow();++irow) {
     818             :     // Is this row ok
     819           0 :     rowok(irow)= (!vb.flagRow()(irow) &&
     820           0 :                   vb.antenna1()(irow)!=vb.antenna2()(irow) &&
     821           0 :                   nfalse(vb.flag().column(irow))> 0 );
     822           0 :     if (rowok(irow)) {
     823           0 :       antok(vb.antenna1()(irow))++;
     824           0 :       antok(vb.antenna2()(irow))++;
     825             :     }
     826             :   }
     827             : 
     828             :   // Assume refant is the target ant, for starters
     829           0 :   Int guessant(refant());
     830             :   //  Int guessant(-1);
     831             : 
     832             :   // If no refant specified, or no data for refant
     833             :   //   base first guess on first good ant
     834           0 :   if (guessant<0 || antok(guessant)<1) {
     835           0 :     guessant=0;
     836           0 :     while (antok(guessant)<1) guessant++;
     837             :   }
     838             : 
     839             :   //  cout << "antok = " << antok << endl;
     840             : 
     841             :   //  cout << "guessant = " << guessant << "  (" << currSpw() << ")" << endl;
     842             : 
     843           0 :   AlwaysAssert(guessant>-1,AipsError);
     844             : 
     845           0 :   Cube<Complex>& V(vb.visCube());
     846           0 :   Float amp(0.0),ampave(0.0);
     847           0 :   Int namp(0);
     848           0 :   solveCPar()=Complex(0.0);
     849           0 :   for (Int irow=1;irow<vb.nRow();++irow) {
     850             : 
     851           0 :     if (rowok(irow) && !vb.flag()(guesschan,irow)) {
     852           0 :       Int a1=vb.antenna1()(irow);
     853           0 :       Int a2=vb.antenna2()(irow);
     854             : 
     855             :       // If this row contains the guessant
     856           0 :       if (a1 == guessant || a2==guessant) {
     857             : 
     858             :         //      cout << a1 << " " << a2 << " " 
     859             :         //           << vb.visCube().xyPlane(irow).column(guesschan) << " "
     860             :         //           << amplitude(vb.visCube().xyPlane(irow).column(guesschan)) << " "
     861             :         //           << endl;
     862             : 
     863           0 :         for (Int icorr=0;icorr<nCorr;icorr++) {
     864           0 :           Complex& Vi(V(corridx(icorr),guesschan,irow));
     865           0 :           amp=abs(Vi);
     866           0 :           if (amp>0.0f) {
     867           0 :             if (a1 == guessant)
     868           0 :               solveCPar()(icorr,0,a2)=conj(Vi);
     869             :             else
     870           0 :               solveCPar()(icorr,0,a1)=(Vi);
     871             :               
     872           0 :             ampave+=amp;
     873           0 :             namp++;
     874             :           }
     875             :         }
     876             :       } // guessant
     877             :     } // rowok
     878             :   } // irow
     879             : 
     880             :   // Scale them by the mean amplitude
     881             : 
     882           0 :   if (namp>0) {
     883           0 :     ampave/=Float(namp);
     884           0 :     ampave=sqrt(ampave);
     885             :     //  solveCPar()*=Complex(ampave);
     886           0 :     solveCPar()/=Complex(ampave);
     887           0 :     solveCPar()(0,0,guessant)=solveCPar()(1,0,guessant)=Complex(ampave);
     888           0 :     solveCPar()(LogicalArray(amplitude(solveCPar())==0.0f)) = Complex(ampave);
     889             :   }
     890             :   else
     891           0 :     solveCPar()=Complex(0.3);
     892             : 
     893           0 :   solveParOK()=true;
     894             : 
     895             :   //For scalar data, Set "other" pol soln to zero
     896           0 :   if (nDataCorr == 1)
     897           0 :     solveCPar()(IPosition(3,1,0,0),IPosition(3,1,0,nAnt()-1))=Complex(0.0);
     898             : 
     899             :   /*
     900             :   cout << "Guess:" << endl;
     901             :   cout << "amplitude(solveCPar())   = " << amplitude(solveCPar()) << endl;
     902             :   cout << "phases       = " << phase(solveCPar())*180.0/M_PI << endl;
     903             :   cout << "solveParOK() = " << solveParOK() << endl;
     904             :   */
     905           0 : }
     906             : 
     907          24 : void GJones::guessPar(SDBList& sdbs, const Bool& corrDepFlags) {
     908             : 
     909          24 :   if (prtlev()>4) cout << "   G::guessPar(sdbs)" << endl;
     910             : 
     911             :   // Use just the first SDB in the SDBList, for now
     912          24 :   SolveDataBuffer& sdb(sdbs(0));
     913             : 
     914             :   // Make a guess at antenna-based G
     915             :   //  Correlation membership-dependencexm
     916             :   //  assumes corrs in canonical order
     917             :   //  nCorr = 1: use icorr=0
     918             :   //  nCorr = 2: use icorr=[0,1]
     919             :   //  nCorr = 4: use icorr=[0,3]
     920             : 
     921          24 :   Int nCorr(2);
     922          24 :   Int nDataCorr(sdb.nCorrelations());
     923          24 :   Vector<Int> corridx(nCorr,0);
     924          24 :   if (nDataCorr==2) {
     925           0 :     corridx(0)=0;
     926           0 :     corridx(1)=1;
     927             :   } 
     928          24 :   else if (nDataCorr==4) {
     929          24 :     corridx(0)=0;
     930          24 :     corridx(1)=3;
     931             :   }
     932             : 
     933          24 :   Int guesschan(sdb.nChannels()-1);
     934             : 
     935             :   /*
     936             :   cout << "guesschan = " << guesschan << endl;
     937             :   cout << "nCorr = " << nCorr << endl;
     938             :   cout << "corridx = " << corridx << endl;
     939             :   */
     940             : 
     941             :   // Find out which ants are available
     942          24 :   Int nRow=sdb.nRows();
     943          24 :   Vector<Int> antok(nAnt(),0);
     944          24 :   Vector<Bool> rowok(nRow,False);
     945        1104 :   for (Int irow=0;irow<nRow;++irow) {
     946             : 
     947        1080 :     const Int& a1(sdb.antenna1()(irow));
     948        1080 :     const Int& a2(sdb.antenna2()(irow));
     949             : 
     950             :     // Is this row ok?
     951        2160 :     rowok(irow)= (!sdb.flagRow()(irow) &&
     952        1080 :                   a1!=a2);
     953             : 
     954        1080 :     if (!corrDepFlags) {
     955             :       // All relevant correlations must be good
     956        3240 :       for (Int icorr=0;icorr<nCorr;++icorr)
     957        2160 :         rowok(irow)=(rowok(irow) && !sdb.flagCube()(corridx[icorr],guesschan,irow));
     958             :     }
     959             : 
     960        1080 :     if (rowok(irow)) {
     961        1080 :       antok(a1)++;
     962        1080 :       antok(a2)++;
     963             :     }
     964             :   }
     965             : 
     966             :   // Assume refant is the target ant, for starters
     967          24 :   Int guessant(refant());
     968             :   //  Int guessant(-1);
     969             : 
     970             :   // If no refant specified, or no data for refant
     971             :   //   base first guess on first good ant
     972          24 :   if (guessant<0 || antok(guessant)<1) {
     973           0 :     guessant=0;
     974           0 :     while (antok(guessant)<1) guessant++;
     975             :   }
     976             : 
     977             :   //  cout << "antok = " << antok << endl;
     978             : 
     979             :   //  cout << "guessant = " << guessant << "  (" << currSpw() << ")" << endl;
     980             : 
     981          24 :   AlwaysAssert(guessant>-1,AipsError);
     982             : 
     983          24 :   const Cube<Complex>& V(sdb.visCubeCorrected());
     984          24 :   Float amp(0.0),ampave(0.0);
     985          24 :   Int namp(0);
     986          24 :   solveCPar()=Complex(0.0);
     987        1104 :   for (Int irow=0;irow<nRow;++irow) {
     988             : 
     989        1080 :     if (rowok(irow)) {
     990        1080 :       const Int& a1=sdb.antenna1()(irow);
     991        1080 :       const Int& a2=sdb.antenna2()(irow);
     992             : 
     993             :       // If this row contains the guessant
     994        1080 :       if (a1 == guessant || a2==guessant) {
     995             : 
     996             :         //      cout << a1 << " " << a2 << " " 
     997             :         //           << sdb.visCube().xyPlane(irow).column(guesschan) << " "
     998             :         //           << amplitude(sdb.visCube().xyPlane(irow).column(guesschan)) << " "
     999             :         //           << endl;
    1000             : 
    1001         648 :         for (Int icorr=0;icorr<nCorr;icorr++) {
    1002         432 :           const Complex& Vi(V(corridx(icorr),guesschan,irow));
    1003         432 :           amp=abs(Vi);
    1004         432 :           if (amp>0.0f) {
    1005         432 :             if (a1 == guessant)
    1006         192 :               solveCPar()(icorr,0,a2)=conj(Vi);
    1007             :             else
    1008         240 :               solveCPar()(icorr,0,a1)=(Vi);
    1009             :               
    1010         432 :             ampave+=amp;
    1011         432 :             namp++;
    1012             :           }
    1013             :         }
    1014             :       } // guessant
    1015             :     } // rowok
    1016             :   } // irow
    1017             : 
    1018             :   // Scale them by the mean amplitude
    1019             : 
    1020          24 :   if (namp>0) {
    1021          24 :     ampave/=Float(namp);
    1022          24 :     ampave=sqrt(ampave);
    1023             :     //  solveCPar()*=Complex(ampave);
    1024          24 :     solveCPar()/=Complex(ampave);
    1025          24 :     solveCPar()(0,0,guessant)=solveCPar()(1,0,guessant)=Complex(ampave);
    1026          24 :     solveCPar()(LogicalArray(amplitude(solveCPar())==0.0f)) = Complex(ampave);
    1027             :   }
    1028             :   else
    1029           0 :     solveCPar()=Complex(0.3);
    1030             : 
    1031          24 :   solveParOK()=True;
    1032             : 
    1033             :   //For scalar data, Set "other" pol soln to zero
    1034          24 :   if (nDataCorr == 1)
    1035           0 :     solveCPar()(IPosition(3,1,0,0),IPosition(3,1,0,nAnt()-1))=Complex(0.0);
    1036             : 
    1037             :   /*
    1038             :     cout << "Guess:" << endl;
    1039             :     cout << "amplitude(solveCPar())   = " << amplitude(solveCPar()) << endl;
    1040             :     cout << "phases       = " << phase(solveCPar())*180.0/M_PI << endl;
    1041             :     cout << "solveParOK() = " << solveParOK() << endl;
    1042             :   */
    1043          24 : }
    1044             : 
    1045             : // Fill the trivial DJ matrix elements
    1046           1 : void GJones::initTrivDJ() {
    1047             : 
    1048           1 :   if (prtlev()>4) cout << "   G::initTrivDJ" << endl;
    1049             : 
    1050             :   // Must be trivial
    1051           1 :   AlwaysAssert((trivialDJ()),AipsError);
    1052             : 
    1053             :   //  1 0     0 0
    1054             :   //  0 0  &  0 1
    1055             :   // 
    1056           1 :   if (diffJElem().nelements()==0) {
    1057           1 :     diffJElem().resize(IPosition(4,2,2,1,1));
    1058           1 :     diffJElem()=0.0;
    1059           1 :     diffJElem()(IPosition(4,0,0,0,0))=Complex(1.0);
    1060           1 :     diffJElem()(IPosition(4,1,1,0,0))=Complex(1.0);
    1061             :   }
    1062             : 
    1063           1 : }
    1064             : 
    1065             : 
    1066           0 : void GJones::createCorruptor(const VisIter& vi, const Record& simpar, const Int nSim) {
    1067             : {
    1068             : 
    1069           0 :   LogIO os(LogOrigin("G", "createCorruptor()", WHERE));  
    1070           0 :   if (prtlev()>2) cout << "   G::createCorruptor()" << endl;
    1071             : 
    1072           0 :   gcorruptor_p = new GJonesCorruptor(nSim);
    1073           0 :   corruptor_p = gcorruptor_p;
    1074             : 
    1075             :   // call generic parent to set corr,spw,etc info
    1076           0 :   SolvableVisCal::createCorruptor(vi,simpar,nSim);
    1077             :   
    1078           0 :   Int Seed(1234);
    1079           0 :   if (simpar.isDefined("seed")) {    
    1080           0 :     Seed=simpar.asInt("seed");
    1081             :   }
    1082             : 
    1083           0 :   if (simpar.isDefined("tsys")) {
    1084           0 :     gcorruptor_p->tsys() = simpar.asFloat("tsys");
    1085             :   } 
    1086             :   
    1087           0 :   if (simpar.isDefined("mode")) {    
    1088           0 :     if (prtlev()>2)
    1089           0 :       cout << "initializing GCorruptor with mode " << simpar.asString("mode") << endl;
    1090             :     
    1091             :     // slot_times for a fBM-based corruption need to be even even if solTimes are not
    1092             :     // so will define startTime and stopTime and reset nsim() here.
    1093             :     
    1094           0 :     if (simpar.isDefined("startTime")) {    
    1095           0 :       corruptor_p->startTime() = simpar.asDouble("startTime");
    1096             :     } else {
    1097           0 :       throw(AipsError("start/stop time not defined"));
    1098             :     }
    1099           0 :     if (simpar.isDefined("stopTime")) {    
    1100           0 :       corruptor_p->stopTime() = simpar.asDouble("stopTime");
    1101             :     } else {
    1102           0 :       throw(AipsError("start/stop time not defined"));
    1103             :     }
    1104             :         
    1105           0 :     if (simpar.asString("mode")=="fbm") {
    1106             : 
    1107           0 :       Float Beta(1.1); // exponent for generalized 1/f noise
    1108           0 :       if (simpar.isDefined("beta")) {    
    1109           0 :         Beta=simpar.asFloat("beta");
    1110             :       }
    1111             :       
    1112           0 :       Float Scale(.15); // scale of fluctuations 
    1113           0 :       if (simpar.isDefined("amplitude")) {
    1114           0 :         Scale=simpar.asFloat("amplitude");
    1115           0 :         if (Scale>=.9) {
    1116           0 :           os << LogIO::WARN << " decreasing gain fluctuations from " << Scale << " to 0.9 " << LogIO::POST;  
    1117           0 :           Scale=.9;
    1118             :         }
    1119             :       }
    1120             : 
    1121           0 :       Float fBM_interval=max(interval(),5.); // generate screens on 5s intervals or longer
    1122           0 :       corruptor_p->setEvenSlots(fBM_interval);
    1123           0 :       gcorruptor_p->initialize(Seed,Beta,Scale);
    1124             :     
    1125           0 :     } else if (simpar.asString("mode")=="random") {
    1126             : 
    1127           0 :       Complex Scale(0.1,0.1); // scale of fluctuations 
    1128           0 :       if (simpar.isDefined("camp")) {
    1129           0 :         Scale=simpar.asComplex("camp");
    1130             :       }
    1131           0 :       gcorruptor_p->initialize(Seed,Scale);
    1132             : 
    1133           0 :     } else throw AipsError("incompatible mode "+simpar.asString("mode"));
    1134             :       
    1135             :     
    1136             :   } else 
    1137           0 :     throw(AipsError("Unknown mode for GJonesCorruptor"));        
    1138           0 :  }
    1139           0 : }
    1140             : 
    1141             : 
    1142             : 
    1143             : 
    1144             : 
    1145             : 
    1146             : 
    1147             : // **********************************************************
    1148             : //  BJones Implementations
    1149             : //
    1150             : 
    1151           0 : BJones::BJones(VisSet& vs) :
    1152             :   VisCal(vs),             // virtual base
    1153             :   VisMueller(vs),         // virtual base
    1154             :   GJones(vs),             // immediate parent
    1155           0 :   maxchangap_p(0)
    1156             : {
    1157           0 :   if (prtlev()>2) cout << "B::B(vs)" << endl;
    1158           0 : }
    1159             : 
    1160           0 : BJones::BJones(String msname,Int MSnAnt,Int MSnSpw) :
    1161             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    1162             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    1163             :   GJones(msname,MSnAnt,MSnSpw),             // immediate parent
    1164           0 :   maxchangap_p(0)
    1165             : {
    1166           0 :   if (prtlev()>2) cout << "B::B(msname,MSnAnt,MSnSpw)" << endl;
    1167           0 : }
    1168             : 
    1169           0 : BJones::BJones(const MSMetaInfoForCal& msmc) :
    1170             :   VisCal(msmc),             // virtual base
    1171             :   VisMueller(msmc),         // virtual base
    1172             :   GJones(msmc),             // immediate parent
    1173           0 :   maxchangap_p(0)
    1174             : {
    1175           0 :   if (prtlev()>2) cout << "B::B(msmc)" << endl;
    1176           0 : }
    1177             : 
    1178           0 : BJones::BJones(const Int& nAnt) :
    1179             :   VisCal(nAnt), 
    1180             :   VisMueller(nAnt),
    1181             :   GJones(nAnt),
    1182           0 :   maxchangap_p(0)
    1183             : {
    1184           0 :   if (prtlev()>2) cout << "B::B(nAnt)" << endl;
    1185           0 : }
    1186             : 
    1187           0 : BJones::~BJones() {
    1188           0 :   if (prtlev()>2) cout << "B::~B()" << endl;
    1189           0 : }
    1190             : 
    1191           0 : void BJones::setSolve(const Record& solve) {
    1192             : 
    1193             :   // call parent to get general stuff
    1194           0 :   GJones::setSolve(solve);
    1195             : 
    1196           0 :   if (solmode()!="") {
    1197           0 :     solmode()="";
    1198           0 :     cout << "solmode options not yet supported for B solutions; ignoring." << endl;
    1199             :   }
    1200             : 
    1201             :   // get max chan gap from user
    1202           0 :   maxchangap_p=0;
    1203           0 :   if (solve.isDefined("maxgap"))
    1204           0 :     maxchangap_p=solve.asInt("maxgap");
    1205             : 
    1206           0 : }
    1207             : 
    1208           0 : void BJones::normalize() {
    1209             : 
    1210             :   // Only if we have a CalTable, and it is not empty
    1211           0 :   if (ct_ && ct_->nrow()>0) {
    1212             : 
    1213             :     // TBD: trap attempts to normalize a caltable containing FPARAM (non-Complex)?
    1214             : 
    1215           0 :     logSink() << "Normalizing solutions per spw, time, ant, pol with " << solNorm().normtypeString()
    1216             :               << " in amplitude (and center channel in phase)."
    1217           0 :               << LogIO::POST;
    1218             : 
    1219             :     // Bandpass is normalized per spw, time, antenna, and pol
    1220           0 :     Block<String> col(3);
    1221           0 :     col[0]="SPECTRAL_WINDOW_ID";
    1222           0 :     col[1]="TIME";
    1223           0 :     col[2]="ANTENNA1";
    1224           0 :     CTIter ctiter(*ct_,col);
    1225             : 
    1226             :     // Cube iteration axes are pol and ant (ant is degenerate)
    1227           0 :     IPosition itax(2,0,2);
    1228             :    
    1229           0 :     while (!ctiter.pastEnd()) {
    1230           0 :       Cube<Bool> fl(ctiter.flag());
    1231             :       
    1232           0 :       if (nfalse(fl)>0) {
    1233           0 :         Cube<Complex> p(ctiter.cparam());
    1234           0 :         ArrayIterator<Complex> soliter(p,itax,false);
    1235           0 :         ArrayIterator<Bool> fliter(fl,itax,false);
    1236           0 :         Int ipol(0);
    1237           0 :         while (!soliter.pastEnd()) {
    1238           0 :           Complex normfactor=normSolnArray(soliter.array(),!fliter.array(),true); // Do phase
    1239           0 :           logSink() << " Normalization factor (" << solNorm().normtypeString() << ") for"
    1240             :                     << " spw=" << ctiter.thisSpw() 
    1241           0 :                     << " time=" << MVTime(ctiter.thisTime()/C::day).string(MVTime::YMD,7)
    1242             :                     << " ant=" << ctiter.thisAntenna1() 
    1243             :                     << " pol " << ipol%2
    1244           0 :                     << " = " << abs(normfactor) << ", " << arg(normfactor)*180.0/M_PI << "deg"
    1245           0 :                     << LogIO::POST;
    1246           0 :           soliter.next();
    1247           0 :           fliter.next();
    1248           0 :           ++ipol;
    1249             :         }
    1250             :         
    1251             :         // record result...     
    1252           0 :         ctiter.setcparam(p);
    1253           0 :       }
    1254           0 :       ctiter.next();
    1255           0 :     }
    1256           0 :   }
    1257             : 
    1258           0 : }
    1259             : 
    1260           0 : void BJones::globalPostSolveTinker() {
    1261             : 
    1262             :   // Call parent to do more general things
    1263           0 :   SolvableVisJones::globalPostSolveTinker();
    1264             : 
    1265             :   // Fill gaps in channels, if necessary
    1266           0 :   if (maxchangap_p>0)
    1267           0 :     fillChanGaps();
    1268             : 
    1269           0 : }
    1270             : 
    1271           0 : void BJones::fillChanGaps() {
    1272             : 
    1273             :   // TBD: Can this be consolidated with normalization (should be done before norm!)
    1274             : 
    1275             :   logSink() << "Filling in flagged solution channels by interpolation." 
    1276           0 :             << LogIO::POST;
    1277             : 
    1278             :   // Iteration axes (norm per spw, pol, ant, timestamp)
    1279           0 :   IPosition itax(3,0,2,3);
    1280             : 
    1281             : 
    1282             :   // Only if we have a CalTable, and it is not empty
    1283           0 :   if (ct_ && ct_->nrow()>0) {
    1284             : 
    1285             :     // TBD: trap attempts to normalize a caltable containing FPARAM (non-Complex)?
    1286             : 
    1287             :     logSink() << "Normalizing solutions per spw, pol, ant, time." 
    1288           0 :               << LogIO::POST;
    1289             : 
    1290             :     // In this generic version, one normalization factor per spw
    1291           0 :     Block<String> col(3);
    1292           0 :     col[0]="SPECTRAL_WINDOW_ID";
    1293           0 :     col[1]="TIME";
    1294           0 :     col[2]="ANTENNA1";
    1295           0 :     CTIter ctiter(*ct_,col);
    1296             : 
    1297             :     // Cube iteration axes are pol and ant
    1298           0 :     IPosition itax(2,0,2);
    1299             :    
    1300           0 :     while (!ctiter.pastEnd()) {
    1301           0 :       Cube<Bool> fl(ctiter.flag());
    1302             :       
    1303           0 :       if (nfalse(fl)>0) {
    1304           0 :         Cube<Complex> p(ctiter.cparam());
    1305           0 :         ArrayIterator<Complex> soliter(p,itax,false);
    1306           0 :         ArrayIterator<Bool> fliter(fl,itax,false);
    1307           0 :         Array<Bool> sok;
    1308           0 :         while (!soliter.pastEnd()) {
    1309           0 :           Array<Bool> thfl(fliter.array());
    1310           0 :           sok.assign(!thfl);
    1311           0 :           fillChanGapArray(soliter.array(),sok);
    1312           0 :           thfl=!sok;  // sok is revised (shapes necessarily match)
    1313           0 :           soliter.next();
    1314           0 :           fliter.next();
    1315           0 :         }
    1316             :         
    1317             :         // record result...     
    1318           0 :         ctiter.setcparam(p);
    1319           0 :         ctiter.setflag(fl);
    1320           0 :       }
    1321           0 :       ctiter.next();
    1322           0 :     }
    1323           0 :   }
    1324           0 : }
    1325             : 
    1326           0 : void BJones::fillChanGapArray(Array<Complex>& sol,
    1327             :                               Array<Bool>& solOK) {
    1328             : 
    1329             :   // TBD: Do this with InterpolateArray1D a la CTPatchedInterp::resampleInFreq
    1330             : 
    1331             :   // Make the arrays 1D
    1332           0 :   Vector<Complex> solv(sol.reform(IPosition(1,sol.nelements())));
    1333           0 :   Vector<Bool> solOKv(solOK.reform(IPosition(1,solOK.nelements())));
    1334             : 
    1335           0 :   Int nChan(solv.nelements());
    1336           0 :   Bool done(false);
    1337           0 :   Int ich(0), ch1(-1), ch2(-1);
    1338           0 :   Int dch(1);
    1339             :   Float a0, da, a, p0, dp, p, fch;
    1340             : 
    1341             :   // Advance to first unflagged channel
    1342           0 :   while(!solOKv(ich) && ich<nChan) ++ich;
    1343             : 
    1344             :   // Found no unflagged channels, so signal escape
    1345           0 :   if (ich==nChan) done=true;
    1346             : 
    1347             :   // done turns true if we reach nChan, and nothing more to do
    1348           0 :   while (!done) {
    1349             : 
    1350             :     // Advance to next flagged channel
    1351           0 :     while(solOKv(ich) && ich<nChan) ++ich;
    1352             : 
    1353           0 :     if (ich<nChan) {
    1354             : 
    1355             :       // Left boundary of gap
    1356           0 :       ch1=ich-1;     // (NB: above logic prevents ch1 < 0)
    1357             : 
    1358             :       // Find right boundary:
    1359           0 :       ch2=ich+1;
    1360           0 :       while (!solOKv(ch2) && ch2<nChan) ++ch2;
    1361             : 
    1362           0 :       if (ch2<nChan) {
    1363             :         
    1364             :         // The span of the interpolation (in channels)
    1365           0 :         dch=ch2-ch1;
    1366             : 
    1367             :         //cout << ch1 << " " << ch2 << " " << dch << endl;
    1368             : 
    1369             :         // Interpolate only if gap is narrower than maxchangap_p
    1370           0 :         if (dch<=maxchangap_p+1) {
    1371             : 
    1372             :           // calculate interp params
    1373           0 :           a0=abs(solv(ch1));
    1374           0 :           da=abs(solv(ch2))-a0;
    1375           0 :           p0=arg(solv(ch1));
    1376           0 :           dp=arg(solv(ch2))-p0;
    1377           0 :           if (dp>M_PI) dp-=(2*M_PI);
    1378           0 :           if (dp<-M_PI) dp+=(2*M_PI);        
    1379             : 
    1380             :           //cout << a0 << " " << da << " " << p0 << " " << dp << endl;
    1381             : 
    1382             : 
    1383             :           // interpolate the intervening channels
    1384           0 :           while (ich<ch2) {
    1385           0 :             fch=Float(ich-ch1)/Float(dch);
    1386           0 :             a=a0 + da*fch;
    1387           0 :             p=p0 + dp*fch;
    1388             : 
    1389             :             // cout << " " << ich << " " << a << " " << p << endl;
    1390             : 
    1391           0 :             solv(ich)=a*Complex(cos(p),sin(p));
    1392           0 :             solOKv(ich)=true;
    1393           0 :             ++ich;
    1394             :           }
    1395             : 
    1396             :           // Begin looking for new gap on next round
    1397           0 :           ++ich;
    1398             :           
    1399             :         }
    1400             :         else
    1401             :           // we skipped a gap, look beyond it on next round
    1402           0 :           ich=ch2+1;
    1403             :       }
    1404             :       else
    1405             :         // Reached nChan looking for ch2
    1406           0 :         done=true;
    1407             :     }
    1408             :     else
    1409             :       // Reach nChan looking for gaps 
    1410           0 :       done=true;
    1411             :   } // done
    1412             : 
    1413           0 : }
    1414             : 
    1415           0 : void BJones::calcWtScale() {
    1416             : 
    1417             :   //  cout << "BJones::calcWtScale()" << endl;
    1418             : 
    1419             : 
    1420             :   // Access pre-chan-interp'd bandpass amplitude/flags
    1421           0 :   Cube<Float> amps;
    1422           0 :   Cube<Bool> ampfl;
    1423             : 
    1424             : 
    1425           0 :   if (cpp_) {
    1426           0 :     Cube<Float> tr;
    1427           0 :     cpp_->getTresult(tr,ampfl,currObs(),currScan(),currField(),currIntent(),currSpw());
    1428           0 :     amps.reference(tr(Slice(0,2,2),Slice(),Slice()));
    1429           0 :   }
    1430           0 :   else if (ci_) {
    1431           0 :     amps=Cube<Float>(ci_->tresultF(currObs(),currScan(),currField(),currSpw()))(Slice(0,2,2),Slice(),Slice());
    1432           0 :     ampfl=ci_->tresultFlag(currObs(),currScan(),currField(),currSpw());
    1433             :   }
    1434             :   else
    1435             :     // BPOLY?
    1436           0 :     throw(AipsError("Can't BJones::calcWtScale because there is no solution interpolation...."));
    1437             :     
    1438             : 
    1439             :   // Initialize
    1440           0 :   currWtScale()=1.0;
    1441             : 
    1442             :   
    1443           0 :   IPosition ash(amps.shape());
    1444           0 :   ash(1)=1;  // only one channel in the weights
    1445           0 :   Cube<Float> cWS(currWtScale());
    1446             : 
    1447           0 :   IPosition it3(2,0,2);
    1448           0 :   ArrayIterator<Float> A(amps,it3,false);
    1449           0 :   ArrayIterator<Bool> Aok(ampfl,it3,false);
    1450           0 :   ArrayIterator<Float> cWSi(cWS,it3,false);
    1451             :     
    1452           0 :   while (!A.pastEnd()) {
    1453             : 
    1454             :     // the weight scale factor is just the square of the 
    1455             :     //   freq-dep normalization
    1456           0 :     cWSi.array()*=(float)pow(calcPowerNorm(A.array(),!Aok.array()),2);
    1457             : 
    1458           0 :     A.next();
    1459           0 :     Aok.next();
    1460           0 :     cWSi.next();
    1461             : 
    1462             :   }
    1463             : 
    1464           0 : }
    1465             : 
    1466             : 
    1467             : 
    1468             : 
    1469             : 
    1470             : // **********************************************************
    1471             : //  JJones Implementations
    1472             : //
    1473             : 
    1474           0 : JJones::JJones(VisSet& vs) :
    1475             :   VisCal(vs),             // virtual base
    1476             :   VisMueller(vs),         // virtual base
    1477           0 :   SolvableVisJones(vs)    // immediate parent
    1478             : {
    1479           0 :   if (prtlev()>2) cout << "J::J(vs)" << endl;
    1480           0 : }
    1481             : 
    1482           0 : JJones::JJones(String msname,Int MSnAnt,Int MSnSpw) :
    1483             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    1484             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    1485           0 :   SolvableVisJones(msname,MSnAnt,MSnSpw)    // immediate parent
    1486             : {
    1487           0 :   if (prtlev()>2) cout << "J::J(msname,MSnAnt,MSnSpw)" << endl;
    1488           0 : }
    1489             : 
    1490           0 : JJones::JJones(const MSMetaInfoForCal& msmc) :
    1491             :   VisCal(msmc),             // virtual base
    1492             :   VisMueller(msmc),         // virtual base
    1493           0 :   SolvableVisJones(msmc)    // immediate parent
    1494             : {
    1495           0 :   if (prtlev()>2) cout << "J::J(msmc)" << endl;
    1496           0 : }
    1497             : 
    1498           0 : JJones::JJones(const Int& nAnt) :
    1499             :   VisCal(nAnt), 
    1500             :   VisMueller(nAnt),
    1501           0 :   SolvableVisJones(nAnt)
    1502             : {
    1503           0 :   if (prtlev()>2) cout << "J::J(nAnt)" << endl;
    1504           0 : }
    1505             : 
    1506           0 : JJones::~JJones() {
    1507           0 :   if (prtlev()>2) cout << "J::~J()" << endl;
    1508           0 : }
    1509             : 
    1510           0 : void JJones::setSolve(const Record& solvepar) {
    1511             : 
    1512             :   // Call parent
    1513           0 :   SolvableVisJones::setSolve(solvepar);
    1514             : 
    1515             :   // For J insist preavg is meaningful (5 minutes or user-supplied)
    1516           0 :   if (preavg()<0.0)
    1517           0 :     preavg()=300.0;
    1518             : 
    1519           0 : }
    1520             : 
    1521             : 
    1522           0 : void JJones::guessPar(VisBuffer& vb) {
    1523             : 
    1524           0 :   if (prtlev()>4) cout << "   ::guessPar(vb)" << endl;
    1525             : 
    1526             :   // Make a guess at antenna-based J
    1527             :   //  Correlation membership-dependence
    1528             :   //  assumes corrs in canonical order
    1529             :   //  nCorr = 1: use icorr=0
    1530             :   //  nCorr = 2: use icorr=[0,1]
    1531             :   //  nCorr = 4: use icorr=[0,3]
    1532             : 
    1533             :   // This method sets the off-diag = 0.0,
    1534             :   //  and the on-diag as if this were G
    1535             : 
    1536           0 :   Int nCorr(2);
    1537           0 :   Int nDataCorr(vb.visCube().shape()(0));
    1538           0 :   Vector<Int> corridx(nCorr,0);
    1539           0 :   if (nDataCorr==2) {
    1540           0 :     corridx(0)=0;
    1541           0 :     corridx(1)=1;
    1542             :   } 
    1543           0 :   else if (nDataCorr==4) {
    1544           0 :     corridx(0)=0;
    1545           0 :     corridx(1)=3;
    1546             :   }
    1547             : 
    1548           0 :   Cube<Complex>& V(vb.visCube());
    1549           0 :   Float amp(0.0),ampave(0.0);
    1550           0 :   Int namp(0);
    1551           0 :   solveCPar()=Complex(0.0);
    1552           0 :   for (Int irow=1;irow<nAnt();++irow) {
    1553             : 
    1554           0 :     for (Int icorr=0;icorr<nCorr;icorr++) {
    1555           0 :       Complex& Vi(V(corridx(icorr),0,irow));
    1556           0 :       amp=abs(Vi);
    1557           0 :       if (amp>0.0f) {
    1558           0 :         solveCPar()(3*icorr,0,irow)=(conj(Vi)/amp);
    1559           0 :         ampave+=amp;
    1560           0 :         namp++;
    1561             :         //      cout << "          " << abs(Vi) << " " << arg(Vi)*180.0/M_PI << endl;
    1562             :       }
    1563             :     }
    1564             : 
    1565             :   }
    1566             : 
    1567             :   // Scale them by the mean amplitude
    1568           0 :   ampave/=Float(namp);
    1569           0 :   ampave=sqrt(ampave);
    1570           0 :   solveCPar()*=Complex(ampave);
    1571           0 :   solveParOK()=true;
    1572             : 
    1573             :   //  cout << "post-guess:" << endl;
    1574             :   //  cout << "solveCPar()   = " << solveCPar() << endl;
    1575             :   //  cout << "phases       = " << phase(solveCPar())*180.0/M_PI << endl;
    1576             :   //  cout << "solveParOK() = " << solveParOK() << endl;
    1577             : 
    1578           0 : }
    1579             : 
    1580             : // Fill the trivial DJ matrix elements
    1581           0 : void JJones::initTrivDJ() {
    1582             : 
    1583           0 :   if (prtlev()>4) cout << "   J::initTrivDJ" << endl;
    1584             : 
    1585             :   // Must be trivial
    1586           0 :   AlwaysAssert((trivialDJ()),AipsError);
    1587             : 
    1588             :   //  1 0     0 1     0 0     0 0
    1589             :   //  0 0     0 0     1 0     0 1
    1590             : 
    1591           0 :   diffJElem().resize(IPosition(4,4,4,1,1));
    1592           0 :   diffJElem()=0.0;
    1593           0 :   diffJElem()(IPosition(4,0,0,0,0))=Complex(1.0);
    1594           0 :   diffJElem()(IPosition(4,1,1,0,0))=Complex(1.0);
    1595           0 :   diffJElem()(IPosition(4,2,2,0,0))=Complex(1.0);
    1596           0 :   diffJElem()(IPosition(4,3,3,0,0))=Complex(1.0);
    1597             : 
    1598           0 : }
    1599             : 
    1600             : 
    1601             : // **********************************************************
    1602             : //  JfJones Implementations
    1603             : //
    1604             : 
    1605           0 : JfJones::JfJones(VisSet& vs) :
    1606             :   VisCal(vs),             // virtual base
    1607             :   VisMueller(vs),         // virtual base
    1608           0 :   JJones(vs)              // immediate parent
    1609             : {
    1610           0 :   if (prtlev()>2) cout << "Jf::Jf(vs)" << endl;
    1611           0 : }
    1612             : 
    1613           0 : JfJones::JfJones(String msname,Int MSnAnt,Int MSnSpw) :
    1614             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    1615             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    1616           0 :   JJones(msname,MSnAnt,MSnSpw)              // immediate parent
    1617             : {
    1618           0 :   if (prtlev()>2) cout << "Jf::Jf(msname,MSnAnt,MSnSpw)" << endl;
    1619           0 : }
    1620             : 
    1621           0 : JfJones::JfJones(const MSMetaInfoForCal& msmc) :
    1622             :   VisCal(msmc),             // virtual base
    1623             :   VisMueller(msmc),         // virtual base
    1624           0 :   JJones(msmc)              // immediate parent
    1625             : {
    1626           0 :   if (prtlev()>2) cout << "Jf::Jf(msmc)" << endl;
    1627           0 : }
    1628             : 
    1629           0 : JfJones::JfJones(const Int& nAnt) :
    1630             :   VisCal(nAnt), 
    1631             :   VisMueller(nAnt),
    1632           0 :   JJones(nAnt)
    1633             : {
    1634           0 :   if (prtlev()>2) cout << "Jf::Jf(nAnt)" << endl;
    1635           0 : }
    1636             : 
    1637           0 : JfJones::~JfJones() {
    1638           0 :   if (prtlev()>2) cout << "Jf::~Jf()" << endl;
    1639           0 : }
    1640             : 
    1641             : 
    1642             : /*
    1643             : 
    1644             : // **********************************************************
    1645             : //  MMueller: baseline-based (closure) solution
    1646             : //
    1647             : 
    1648             : MMueller::MMueller(VisSet& vs) :
    1649             :   VisCal(vs),             // virtual base
    1650             :   VisMueller(vs),         // virtual base
    1651             :   SolvableVisMueller(vs)    // immediate parent
    1652             : {
    1653             :   if (prtlev()>2) cout << "M::M(vs)" << endl;
    1654             : }
    1655             : 
    1656             : MMueller::MMueller(String msname,Int MSnAnt,Int MSnSpw) :
    1657             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    1658             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    1659             :   SolvableVisMueller(msname,MSnAnt,MSnSpw)    // immediate parent
    1660             : {
    1661             :   if (prtlev()>2) cout << "M::M(msname,MSnAnt,MSnSpw)" << endl;
    1662             : }
    1663             : 
    1664             : MMueller::MMueller(const MSMetaInfoForCal& msmc) :
    1665             :   VisCal(msmc),             // virtual base
    1666             :   VisMueller(msmc),         // virtual base
    1667             :   SolvableVisMueller(msmc)  // immediate parent
    1668             : {
    1669             :   if (prtlev()>2) cout << "M::M(msmc)" << endl;
    1670             : }
    1671             : 
    1672             : MMueller::MMueller(const Int& nAnt) :
    1673             :   VisCal(nAnt), 
    1674             :   VisMueller(nAnt),
    1675             :   SolvableVisMueller(nAnt)
    1676             : {
    1677             :   if (prtlev()>2) cout << "M::M(nAnt)" << endl;
    1678             : }
    1679             : 
    1680             : MMueller::~MMueller() {
    1681             :   if (prtlev()>2) cout << "M::~M()" << endl;
    1682             : }
    1683             : 
    1684             : void MMueller::setApply(const Record& apply) {
    1685             : 
    1686             :   SolvableVisCal::setApply(apply);
    1687             : 
    1688             :   // Force calwt to false for now
    1689             :   calWt()=false;
    1690             : 
    1691             : }
    1692             : 
    1693             : void MMueller::newselfSolve(VisSet& vs, VisEquation& ve) {
    1694             : 
    1695             :   if (prtlev()>4) cout << "   M::selfSolve(ve)" << endl;
    1696             : 
    1697             :   // Inform logger/history
    1698             :   logSink() << "Solving for " << typeName()
    1699             :             << LogIO::POST;
    1700             : 
    1701             :   // Initialize the svc according to current VisSet
    1702             :   //  (this counts intervals, sizes CalSet)
    1703             :   Vector<Int> nChunkPerSol;
    1704             :   Int nSol = sizeUpSolve(vs,nChunkPerSol);
    1705             :   
    1706             :   // Create the Caltable
    1707             :   createMemCalTable();
    1708             : 
    1709             :   // The iterator, VisBuffer
    1710             :   VisIter& vi(vs.iter());
    1711             :   VisBuffer vb(vi);
    1712             : 
    1713             :   //  cout << "nSol = " << nSol << endl;
    1714             :   //  cout << "nChunkPerSol = " << nChunkPerSol << endl;
    1715             : 
    1716             :   Vector<Int> slotidx(vs.numberSpw(),-1);
    1717             : 
    1718             :   Int nGood(0);
    1719             :   vi.originChunks();
    1720             :   for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
    1721             : 
    1722             :     // Arrange to accumulate
    1723             :     VisBuffAccumulator vba(nAnt(),preavg(),false);
    1724             :     
    1725             :     for (Int ichunk=0;ichunk<nChunkPerSol(isol);++ichunk) {
    1726             : 
    1727             :       // Current _chunk_'s spw
    1728             :       Int spw(vi.spectralWindow());
    1729             : 
    1730             :       // Abort if we encounter a spw for which a priori cal not available
    1731             :       if (!ve.spwOK(spw))
    1732             :         throw(AipsError("Pre-applied calibration not available for at least 1 spw. Check spw selection carefully."));
    1733             : 
    1734             : 
    1735             :       // Collapse each timestamp in this chunk according to VisEq
    1736             :       //  with calibration and averaging
    1737             :       for (vi.origin(); vi.more(); vi++) {
    1738             : 
    1739             :         // Force read of the field Id
    1740             :         vb.fieldId();
    1741             : 
    1742             :         // Apply the channel mask
    1743             :         this->applyChanMask(vb);
    1744             : 
    1745             :         // This forces the data/model/wt I/O, and applies
    1746             :         //   any prior calibrations
    1747             :         ve.collapse(vb);
    1748             : 
    1749             :         // If permitted/required by solvable component, normalize
    1750             :         if (normalizable())
    1751             :           vb.normalize();
    1752             : 
    1753             :         // If this solve not freqdep, and channels not averaged yet, do so
    1754             :         if (!freqDepMat() && vb.nChannel()>1) 
    1755             :           vb.freqAveCubes();
    1756             : 
    1757             :         // Accumulate collapsed vb in a time average
    1758             :         vba.accumulate(vb);
    1759             :       }
    1760             :       // Advance the VisIter, if possible
    1761             :       if (vi.moreChunks()) vi.nextChunk();
    1762             : 
    1763             :     }
    1764             : 
    1765             :     // Finalize the averged VisBuffer
    1766             :     vba.finalizeAverage();
    1767             : 
    1768             :     // The VisBuffer to solve with
    1769             :     VisBuffer& svb(vba.aveVisBuff());
    1770             : 
    1771             :     // Make data amp- or phase-only
    1772             :     enforceAPonData(svb);
    1773             : 
    1774             :     // Establish meta-data for this interval
    1775             :     //  (some of this may be used _during_ solve)
    1776             :     //  (this sets currSpw() in the SVC)
    1777             :     Bool vbOk=syncSolveMeta(svb,-1);
    1778             : 
    1779             :     Int thisSpw=spwMap()(svb.spectralWindow());
    1780             :     slotidx(thisSpw)++;
    1781             : 
    1782             :     // We are actually solving for all channels simultaneously
    1783             :     solveCPar().reference(solveAllCPar());
    1784             :     solveParOK().reference(solveAllParOK());
    1785             :     solveParErr().reference(solveAllParErr());
    1786             :     solveParSNR().reference(solveAllParSNR());
    1787             : 
    1788             :     // Fill solveCPar() with 1, nominally, and flagged
    1789             :     solveCPar()=Complex(1.0);
    1790             :     solveParOK()=false;
    1791             :     
    1792             :     if (vbOk && svb.nRow()>0) {
    1793             : 
    1794             :       // Insist that channel,row shapes match
    1795             :       IPosition visshape(svb.visCube().shape());
    1796             :       AlwaysAssert(solveCPar().shape().getLast(2)==visshape.getLast(2),AipsError);
    1797             :       
    1798             :       // Zero flagged data
    1799             :       IPosition vblc(3,0,0,0);
    1800             :       IPosition vtrc(visshape);  vtrc-=1;      
    1801             :       Int nCorr(visshape(0));
    1802             :       for (Int i=0;i<nCorr;++i) {
    1803             :         vblc(0)=vtrc(0)=i;
    1804             :         svb.visCube()(vblc,vtrc).reform(visshape.getLast(2))(svb.flag())=Complex(1.0);
    1805             :       }
    1806             :       
    1807             :       // Form correct slice of visCube to copy to solveCPar
    1808             :       IPosition vcblc(3,0,0,0);
    1809             :       IPosition vctrc(svb.visCube().shape()); vctrc-=1;
    1810             :       IPosition vcstr(3,1,1,1);
    1811             : 
    1812             :       IPosition spblc(3,0,0,0);
    1813             :       IPosition sptrc(solveCPar().shape()); sptrc-=1;
    1814             : 
    1815             :       IPosition flshape(svb.flag().shape());
    1816             :       
    1817             :       switch (nCorr) {
    1818             :       case 1: {
    1819             :         // fill 1st par only
    1820             :         spblc(0)=sptrc(0)=0; 
    1821             :         solveCPar()(spblc,sptrc)=svb.visCube();
    1822             :         // first pol flags
    1823             :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    1824             :         break;
    1825             :       }
    1826             :       case 2: {
    1827             :         // shapes match
    1828             :         solveCPar()=svb.visCube();
    1829             :         spblc(0)=sptrc(0)=0; 
    1830             :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    1831             :         spblc(0)=sptrc(0)=1; 
    1832             :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    1833             : 
    1834             :         break;
    1835             :       }
    1836             :       case 4: {
    1837             :         // Slice visCube with stride
    1838             :         vcstr(0)=3;
    1839             :         solveCPar()=svb.visCube()(vcblc,vctrc,vcstr);
    1840             :         spblc(0)=sptrc(0)=0; 
    1841             :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    1842             :         spblc(0)=sptrc(0)=1; 
    1843             :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    1844             : 
    1845             :         break;
    1846             :       }
    1847             :       default:
    1848             :         throw(AipsError("Problem in MMueller::selfSolve."));
    1849             :         break;
    1850             :       }
    1851             : 
    1852             :       nGood++;
    1853             : 
    1854             :       // record in in-memory caltable
    1855             :       keepNCT();
    1856             :     }
    1857             :   }
    1858             :   
    1859             :   logSink() << "  Found good "
    1860             :             << typeName() << " solutions in "
    1861             :             << nGood << " intervals."
    1862             :             << LogIO::POST;
    1863             : 
    1864             :   // Store whole of result in a caltable
    1865             :   if (nGood==0)
    1866             :     logSink() << "No output calibration table written."
    1867             :               << LogIO::POST;
    1868             :   else {
    1869             : 
    1870             :     // Do global post-solve tinkering (e.g., normalization)
    1871             :     globalPostSolveTinker();
    1872             : 
    1873             :     // write the table
    1874             :     storeNCT();
    1875             :   }
    1876             : 
    1877             : }
    1878             : 
    1879             : void MMueller::globalPostSolveTinker() {
    1880             : 
    1881             :   // normalize, if requested
    1882             :   if (solnorm()) normalize();
    1883             : 
    1884             : }
    1885             : 
    1886             : void MMueller::createCorruptor(const VisIter& vi, const Record& simpar, const Int nSim) 
    1887             : {
    1888             :   LogIO os(LogOrigin("MM", "createCorruptor()", WHERE));
    1889             : 
    1890             :   if (prtlev()>2) cout << "   MM::createCorruptor()" << endl;
    1891             :   os << LogIO::DEBUG1 << "   MM::createCorruptor()" 
    1892             :      << LogIO::POST;
    1893             : 
    1894             :   atmcorruptor_p = new AtmosCorruptor();
    1895             :   corruptor_p = atmcorruptor_p;
    1896             : 
    1897             :   // call generic parent to set corr,spw,etc info
    1898             :   SolvableVisCal::createCorruptor(vi,simpar,nSim);
    1899             : 
    1900             :   Int rxType(0); // 0=2SB, 1=DSB
    1901             :   if (simpar.isDefined("rxType")) {    
    1902             :     rxType=simpar.asInt("rxType");
    1903             :   }
    1904             :  
    1905             :   // this is the M type corruptor - maybe we should make the corruptor 
    1906             :   // take the VC as an argument
    1907             :   atmcorruptor_p->initialize(vi,simpar,VisCal::M,rxType); 
    1908             : }
    1909             : 
    1910             : 
    1911             : 
    1912             : 
    1913             : 
    1914             : 
    1915             : // **********************************************************
    1916             : //  MfMueller: freq-dep MMueller
    1917             : //
    1918             : 
    1919             : MfMueller::MfMueller(VisSet& vs) :
    1920             :   VisCal(vs),             // virtual base
    1921             :   VisMueller(vs),         // virtual base
    1922             :   MMueller(vs)            // immediate parent
    1923             : {
    1924             :   if (prtlev()>2) cout << "Mf::Mf(vs)" << endl;
    1925             : }
    1926             : 
    1927             : MfMueller::MfMueller(String msname,Int MSnAnt,Int MSnSpw) :
    1928             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    1929             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    1930             :   MMueller(msname,MSnAnt,MSnSpw)            // immediate parent
    1931             : {
    1932             :   if (prtlev()>2) cout << "Mf::Mf(msname,MSnAnt,MSnSpw)" << endl;
    1933             : }
    1934             : 
    1935             : MfMueller::MfMueller(const MSMetaInfoForCal& msmc) :
    1936             :   VisCal(msmc),             // virtual base
    1937             :   VisMueller(msmc),         // virtual base
    1938             :   MMueller(msmc)            // immediate parent
    1939             : {
    1940             :   if (prtlev()>2) cout << "Mf::Mf(msmc)" << endl;
    1941             : }
    1942             : 
    1943             : MfMueller::MfMueller(const Int& nAnt) :
    1944             :   VisCal(nAnt), 
    1945             :   VisMueller(nAnt),
    1946             :   MMueller(nAnt)
    1947             : {
    1948             :   if (prtlev()>2) cout << "Mf::Mf(nAnt)" << endl;
    1949             : }
    1950             : 
    1951             : MfMueller::~MfMueller() {
    1952             :   if (prtlev()>2) cout << "Mf::~Mf()" << endl;
    1953             : }
    1954             : 
    1955             : void MfMueller::normalize() {
    1956             : 
    1957             :   // This is just like BJones
    1958             :   // TBD:  consolidate (via generalized SVC::normalize(Block<String> cols) )
    1959             : 
    1960             :   // Only if we have a CalTable, and it is not empty
    1961             :   if (ct_ && ct_->nrow()>0) {
    1962             : 
    1963             :     // TBD: trap attempts to normalize a caltable containing FPARAM (non-Complex)?
    1964             : 
    1965             :     logSink() << "Normalizing solutions per spw, pol, baseline, time"
    1966             :               << LogIO::POST;
    1967             : 
    1968             :     Block<String> col(4);
    1969             :     col[0]="SPECTRAL_WINDOW_ID";
    1970             :     col[1]="TIME";
    1971             :     col[2]="ANTENNA1";
    1972             :     col[3]="ANTENNA2";
    1973             :     CTIter ctiter(*ct_,col);
    1974             : 
    1975             :     // Cube iteration axes are pol and ant
    1976             :     IPosition itax(2,0,2);
    1977             :    
    1978             :     while (!ctiter.pastEnd()) {
    1979             :       Cube<Bool> fl(ctiter.flag());
    1980             :       
    1981             :       if (nfalse(fl)>0) {
    1982             :         Cube<Complex> p(ctiter.cparam());
    1983             :         ArrayIterator<Complex> soliter(p,itax,false);
    1984             :         ArrayIterator<Bool> fliter(fl,itax,false);
    1985             :         while (!soliter.pastEnd()) {
    1986             :           normSolnArray(soliter.array(),!fliter.array(),true); // Do phase
    1987             :           soliter.next();
    1988             :           fliter.next();
    1989             :         }
    1990             :         
    1991             :         // record result...     
    1992             :         ctiter.setcparam(p);
    1993             :       }
    1994             :       ctiter.next();
    1995             :     }
    1996             :   }
    1997             :   cout << "End of MfMueller::normalize()" << endl;
    1998             : }
    1999             : 
    2000             : */
    2001             : 
    2002             : // **********************************************************
    2003             : //  TOpac
    2004             : //
    2005             : 
    2006           0 : TOpac::TOpac(VisSet& vs) :
    2007             :   VisCal(vs), 
    2008             :   VisMueller(vs),
    2009             :   TJones(vs),
    2010           0 :   za_()
    2011             : {
    2012           0 :   if (prtlev()>2) cout << "TOpac::TOpac(vs)" << endl;
    2013           0 : }
    2014             : 
    2015           0 : TOpac::TOpac(String msname,Int MSnAnt,Int MSnSpw) :
    2016             :   VisCal(msname,MSnAnt,MSnSpw), 
    2017             :   VisMueller(msname,MSnAnt,MSnSpw),
    2018             :   TJones(msname,MSnAnt,MSnSpw),
    2019           0 :   za_()
    2020             : {
    2021           0 :   if (prtlev()>2) cout << "TOpac::TOpac(msname,MSnAnt,MSnSpw)" << endl;
    2022           0 : }
    2023             : 
    2024           0 : TOpac::TOpac(const MSMetaInfoForCal& msmc) :
    2025             :   VisCal(msmc), 
    2026             :   VisMueller(msmc),
    2027             :   TJones(msmc),
    2028           0 :   za_()
    2029             : {
    2030           0 :   if (prtlev()>2) cout << "TOpac::TOpac(msmc)" << endl;
    2031           0 : }
    2032             : 
    2033           0 : TOpac::~TOpac() {
    2034           0 :   if (prtlev()>2) cout << "TOpac::~TOpac()" << endl;
    2035           0 : }
    2036             : 
    2037           0 : void TOpac::setApply(const Record& applypar) {
    2038             : 
    2039             :   // TBD: Handle spwmap properly?
    2040             : 
    2041             :   // Prepare zenith angle storage
    2042           0 :   za().resize(nAnt());
    2043           0 :   za().set(0.0);
    2044             : 
    2045           0 :   String table("");
    2046           0 :   if (applypar.isDefined("table"))
    2047           0 :     table=applypar.asString("table");
    2048             : 
    2049           0 :   if (table!="")
    2050             :     // Attempt new-fashioned opacity table
    2051           0 :     SolvableVisCal::setApply(applypar);
    2052             :   else {
    2053             : 
    2054             :     // We are applying
    2055           0 :     setSolved(false);
    2056           0 :     setApplied(true);
    2057             : 
    2058           0 :     LogMessage message;
    2059           0 :     { ostringstream o;
    2060           0 :       o<< "Invoking opacity application without a caltable (e.g., " << endl
    2061           0 :        << " via opacity=[...] in calibration tasks) will soon be disabled." << endl
    2062           0 :        << " Please begin using gencal to generate an opacity caltable, " << endl
    2063           0 :        << " and then supply that table in the standard manner." << endl;
    2064           0 :       message.message(o);
    2065           0 :       message.priority(LogMessage::WARN);
    2066           0 :       logSink().post(message);
    2067           0 :     }
    2068             : 
    2069             :     // Detect and extract opacities from applypar record (old way)
    2070           0 :     if (applypar.isDefined("opacity")) {
    2071           0 :       opacity_.resize();
    2072           0 :       opacity_=applypar.asArrayDouble("opacity");
    2073             :     }
    2074           0 :     Int nopac=opacity_.nelements();
    2075             :     
    2076           0 :     if (nopac>0 && sum(opacity_)>0.0) {
    2077             : 
    2078             :       // Old-fashioned opacity_ is non-trivial, so adopt them
    2079             :       
    2080           0 :       if (nopac<nSpw()) {
    2081             :         // Resize (with copy) to match nSpw, 
    2082             :         //  duplicating last specified entry
    2083           0 :         opacity_.resize(nSpw(),true);
    2084           0 :         opacity_(IPosition(1,nopac),IPosition(1,nSpw()-1))=opacity_(nopac-1);
    2085             :       }
    2086             :     
    2087           0 :       Int oldspw; oldspw=currSpw();
    2088           0 :       for (Int ispw=0;ispw<nSpw();++ispw) {
    2089           0 :         currSpw()=ispw;
    2090           0 :         currRPar().resize(1,1,nAnt());
    2091           0 :         currRPar()=Float(opacity_(ispw));
    2092           0 :         currParOK().resize(1,1,nAnt());
    2093           0 :         currParOK()=true;
    2094             :       }
    2095           0 :       currSpw()=oldspw;
    2096             :       
    2097             :     }
    2098             :     else
    2099           0 :       throw(AipsError("No opacity info specified."));
    2100           0 :   }
    2101             : 
    2102           0 : }
    2103             : 
    2104           0 : String TOpac::applyinfo() {
    2105             : 
    2106           0 :   if (opacity_.nelements()==0)
    2107           0 :     return TJones::applyinfo();
    2108             :   else {
    2109           0 :     ostringstream o;
    2110           0 :     o << typeName();
    2111           0 :     o << ": opacity=" << opacity_;
    2112           0 :     o << boolalpha
    2113           0 :     << " calWt=" << calWt();
    2114           0 :     return String(o);
    2115           0 :   }
    2116             : }
    2117             : 
    2118             : // TOpac needs zenith angle (old VB version)
    2119           0 : void TOpac::syncMeta(const VisBuffer& vb) {
    2120             : 
    2121             :   // Call parent (sets currTime())
    2122           0 :   TJones::syncMeta(vb);
    2123             : 
    2124             :   // Current time's zenith angle...
    2125           0 :   za().resize(nAnt());
    2126           0 :   Vector<MDirection> antazel(vb.azel(currTime()));
    2127           0 :   Double* a=za().data();
    2128           0 :   for (Int iant=0;iant<nAnt();++iant,++a) 
    2129           0 :     (*a)=M_PI_2 - antazel(iant).getAngle().getValue()(1);
    2130             : 
    2131           0 : }
    2132             : 
    2133             : // TOpac needs zenith angle  (VB2 version) 
    2134           0 : void TOpac::syncMeta2(const vi::VisBuffer2& vb) {
    2135             : 
    2136             :   // Call parent (sets currTime())
    2137           0 :   TJones::syncMeta2(vb);
    2138             : 
    2139             :   // Current time's zenith angle...
    2140           0 :   za().resize(nAnt());
    2141           0 :   Vector<MDirection> antazel(vb.azel(currTime()));
    2142           0 :   Double* a=za().data();
    2143           0 :   for (Int iant=0;iant<nAnt();++iant,++a) 
    2144           0 :     (*a)=M_PI_2 - antazel(iant).getAngle().getValue()(1);
    2145             : 
    2146           0 : }
    2147             : 
    2148             : 
    2149           0 : void TOpac::calcPar() {
    2150             : 
    2151           0 :   if (prtlev()>6) cout << "      TOpac::calcPar()" << endl;
    2152             :   
    2153             :   // If we are interpolating from a table, get opacity(time)
    2154           0 :   if (ci_ || cpp_)
    2155           0 :     SolvableVisCal::calcPar();
    2156             :   else
    2157           0 :     throw(AipsError("Error in TOpac::calcPar()"));
    2158             : 
    2159             :   // Pars now valid, matrices not yet
    2160           0 :   validateP();
    2161           0 :   invalidateJ();  // Force new calculation of za-dep matrix elements
    2162             : 
    2163           0 : }
    2164             : 
    2165             : 
    2166           0 : void TOpac::calcAllJones() {
    2167             : 
    2168           0 :   if (prtlev()>6) cout << "       TOpac::calcAllJones()" << endl;
    2169             : 
    2170             :   // Nominally no opacity
    2171           0 :   currJElem()=Complex(1.0);
    2172           0 :   currJElemOK()=currParOK();
    2173             : 
    2174           0 :   Complex* J=currJElem().data();
    2175           0 :   Float*  op=currRPar().data();
    2176           0 :   Bool*   opok=currParOK().data();
    2177           0 :   Double* a=za().data();
    2178           0 :   for (Int iant=0; iant<nAnt(); ++iant,++J,++op,++opok,++a) {
    2179           0 :     if ((*opok) && (*a)<M_PI_2) 
    2180           0 :       (*J) = Complex(sqrt(exp(-1.0 * Double(*op)/cos(*a))));
    2181             :   }
    2182             : 
    2183           0 : }
    2184             : 
    2185             : 
    2186             : // **********************************************************
    2187             : //  TfOpac
    2188             : //
    2189             : 
    2190           0 : TfOpac::TfOpac(VisSet& vs) :
    2191             :   VisCal(vs),             // virtual base
    2192             :   VisMueller(vs),         // virtual base
    2193           0 :   TOpac(vs)              // immediate parent
    2194             : {
    2195           0 :   if (prtlev()>2) cout << "TfOpac::TfOpac(vs)" << endl;
    2196           0 : }
    2197             : 
    2198           0 : TfOpac::TfOpac(String msname,Int MSnAnt,Int MSnSpw) :
    2199             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    2200             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    2201           0 :   TOpac(msname,MSnAnt,MSnSpw)              // immediate parent
    2202             : {
    2203           0 :   if (prtlev()>2) cout << "TfOpac::TfOpac(msname,MSnAnt,MSnSpw)" << endl;
    2204           0 : }
    2205             : 
    2206           0 : TfOpac::TfOpac(const MSMetaInfoForCal& msmc) :
    2207             :   VisCal(msmc),             // virtual base
    2208             :   VisMueller(msmc),         // virtual base
    2209           0 :   TOpac(msmc)              // immediate parent
    2210             : {
    2211           0 :   if (prtlev()>2) cout << "TfOpac::TfOpac(msmc)" << endl;
    2212           0 : }
    2213             : 
    2214             : 
    2215             : //TfOpac::TfOpac(const Int& nAnt) :
    2216             : //  VisCal(nAnt), 
    2217             : //  VisMueller(nAnt),
    2218             : //  TOpac(nAnt)
    2219             : //{
    2220             : //  if (prtlev()>2) cout << "TfOpac::TfOpac(nAnt)" << endl;
    2221             : //}
    2222             : 
    2223           0 : TfOpac::~TfOpac() {
    2224           0 :   if (prtlev()>2) cout << "TfOpac::~TfOpac()" << endl;
    2225           0 : }
    2226             : 
    2227           0 : void TfOpac::calcAllJones() {
    2228             : 
    2229           0 :   if (prtlev()>6) cout << "       TfOpac::calcAllJones()" << endl;
    2230             : 
    2231             :   // Nominally no opacity
    2232           0 :   currJElem()=Complex(1.0);
    2233           0 :   currJElemOK()=currParOK();
    2234             : 
    2235           0 :   Complex* J=currJElem().data();
    2236           0 :   Float*  op=currRPar().data();
    2237           0 :   Bool*   opok=currParOK().data();
    2238           0 :   Double* a=za().data();
    2239           0 :   for (Int iant=0; iant<nAnt(); ++iant,++a) {
    2240           0 :     for (Int ich=0; ich<nChanMat(); ich++, J++, op++, opok++) {
    2241           0 :       if ((*opok) && (*a)<M_PI_2) 
    2242           0 :         (*J) = Complex(sqrt(exp(-1.0 * Double(*op)/cos(*a))));
    2243             :     }
    2244             :   }
    2245           0 : }
    2246             : 
    2247             : 
    2248           0 : void TfOpac::calcWtScale() {
    2249             : 
    2250             :   // Initialize - not used for TfOpac, but we need to overwrite the
    2251             :   // single channel version or it will throw an exception
    2252           0 :   currWtScale()=1.0;
    2253             : 
    2254           0 : }
    2255             : 
    2256             : 
    2257             : // **********************************************************
    2258             : //  MMueller: baseline-based (closure) solution
    2259             : //
    2260             : 
    2261           0 : MMueller::MMueller(VisSet& vs) :
    2262             :   VisCal(vs),             // virtual base
    2263             :   VisMueller(vs),         // virtual base
    2264             :   SolvableVisMueller(vs),    // immediate parent
    2265           0 :   useGenGathSolve_p(false)  // VisSet-driven ctor
    2266             : {
    2267           0 :   if (prtlev()>2) cout << "M::M(vs)" << endl;
    2268           0 : }
    2269             : 
    2270           0 : MMueller::MMueller(String msname,Int MSnAnt,Int MSnSpw) :
    2271             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    2272             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    2273             :   SolvableVisMueller(msname,MSnAnt,MSnSpw),    // immediate parent
    2274           0 :   useGenGathSolve_p(true)  // modern ctor
    2275             : {
    2276           0 :   if (prtlev()>2) cout << "M::M(msname,MSnAnt,MSnSpw)" << endl;
    2277           0 : }
    2278             : 
    2279           0 : MMueller::MMueller(const MSMetaInfoForCal& msmc) :
    2280             :   VisCal(msmc),             // virtual base
    2281             :   VisMueller(msmc),         // virtual base
    2282             :   SolvableVisMueller(msmc),  // immediate parent
    2283           0 :   useGenGathSolve_p(true)  // modern ctor
    2284             : {
    2285           0 :   if (prtlev()>2) cout << "M::M(msmc)" << endl;
    2286           0 : }
    2287             : 
    2288           0 : MMueller::MMueller(const Int& nAnt) :
    2289             :   VisCal(nAnt), 
    2290             :   VisMueller(nAnt),
    2291             :   SolvableVisMueller(nAnt),
    2292           0 :   useGenGathSolve_p(true)  // modern ctor
    2293             : {
    2294           0 :   if (prtlev()>2) cout << "M::M(nAnt)" << endl;
    2295           0 : }
    2296             : 
    2297           0 : MMueller::~MMueller() {
    2298           0 :   if (prtlev()>2) cout << "M::~M()" << endl;
    2299           0 : }
    2300             : 
    2301           0 : void MMueller::setApply(const Record& apply) {
    2302             : 
    2303           0 :   SolvableVisCal::setApply(apply);
    2304             : 
    2305             :   // Force calwt to false for now
    2306           0 :   calWt()=false;
    2307             : 
    2308           0 : }
    2309             : 
    2310           0 : void MMueller::newselfSolve(VisSet& vs, VisEquation& ve) {
    2311             : 
    2312           0 :   if (prtlev()>4) cout << "   M::selfSolve(ve)" << endl;
    2313             : 
    2314           0 :   AlwaysAssert(!useGenGathSolve_p,AipsError);
    2315             : 
    2316             :   // Inform logger/history
    2317           0 :   logSink() << "Solving for " << typeName()
    2318           0 :             << LogIO::POST;
    2319             : 
    2320             :   // Initialize the svc according to current VisSet
    2321             :   //  (this counts intervals, sizes CalSet)
    2322           0 :   Vector<Int> nChunkPerSol;
    2323           0 :   Int nSol = sizeUpSolve(vs,nChunkPerSol);
    2324             :   
    2325             :   // Create the Caltable
    2326           0 :   createMemCalTable();
    2327             : 
    2328             :   // The iterator, VisBuffer
    2329           0 :   VisIter& vi(vs.iter());
    2330           0 :   VisBuffer vb(vi);
    2331             : 
    2332             :   //  cout << "nSol = " << nSol << endl;
    2333             :   //  cout << "nChunkPerSol = " << nChunkPerSol << endl;
    2334             : 
    2335           0 :   Vector<Int> slotidx(vs.numberSpw(),-1);
    2336             : 
    2337           0 :   Int nGood(0);
    2338           0 :   vi.originChunks();
    2339           0 :   for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
    2340             : 
    2341             :     // Arrange to accumulate
    2342           0 :     VisBuffAccumulator vba(nAnt(),preavg(),false);
    2343             :     
    2344           0 :     for (Int ichunk=0;ichunk<nChunkPerSol(isol);++ichunk) {
    2345             : 
    2346             :       // Current _chunk_'s spw
    2347           0 :       Int spw(vi.spectralWindow());
    2348             : 
    2349             :       // Abort if we encounter a spw for which a priori cal not available
    2350           0 :       if (!ve.spwOK(spw))
    2351           0 :         throw(AipsError("Pre-applied calibration not available for at least 1 spw. Check spw selection carefully."));
    2352             : 
    2353             : 
    2354             :       // Collapse each timestamp in this chunk according to VisEq
    2355             :       //  with calibration and averaging
    2356           0 :       for (vi.origin(); vi.more(); vi++) {
    2357             : 
    2358             :         // Force read of the field Id
    2359           0 :         vb.fieldId();
    2360             : 
    2361             :         // Apply the channel mask
    2362           0 :         this->applyChanMask(vb);
    2363             : 
    2364             :         // This forces the data/model/wt I/O, and applies
    2365             :         //   any prior calibrations
    2366           0 :         ve.collapse(vb);
    2367             : 
    2368             :         // If permitted/required by solvable component, normalize
    2369           0 :         if (normalizable())
    2370           0 :           vb.normalize();
    2371             : 
    2372             :         // If this solve not freqdep, and channels not averaged yet, do so
    2373           0 :         if (!freqDepMat() && vb.nChannel()>1) 
    2374           0 :           vb.freqAveCubes();
    2375             : 
    2376             :         // Accumulate collapsed vb in a time average
    2377           0 :         vba.accumulate(vb);
    2378             :       }
    2379             :       // Advance the VisIter, if possible
    2380           0 :       if (vi.moreChunks()) vi.nextChunk();
    2381             : 
    2382             :     }
    2383             : 
    2384             :     // Finalize the averged VisBuffer
    2385           0 :     vba.finalizeAverage();
    2386             : 
    2387             :     // The VisBuffer to solve with
    2388           0 :     VisBuffer& svb(vba.aveVisBuff());
    2389             : 
    2390             :     // Make data amp- or phase-only
    2391           0 :     enforceAPonData(svb);
    2392             : 
    2393             :     // Establish meta-data for this interval
    2394             :     //  (some of this may be used _during_ solve)
    2395             :     //  (this sets currSpw() in the SVC)
    2396           0 :     Bool vbOk=syncSolveMeta(svb,-1);
    2397             : 
    2398           0 :     Int thisSpw=spwMap()(svb.spectralWindow());
    2399           0 :     slotidx(thisSpw)++;
    2400             : 
    2401             :     // We are actually solving for all channels simultaneously
    2402           0 :     solveCPar().reference(solveAllCPar());
    2403           0 :     solveParOK().reference(solveAllParOK());
    2404           0 :     solveParErr().reference(solveAllParErr());
    2405           0 :     solveParSNR().reference(solveAllParSNR());
    2406             : 
    2407             :     // Fill solveCPar() with 1, nominally, and flagged
    2408           0 :     solveCPar()=Complex(1.0);
    2409           0 :     solveParOK()=false;
    2410             :     
    2411           0 :     if (vbOk && svb.nRow()>0) {
    2412             : 
    2413             :       // Insist that channel,row shapes match
    2414           0 :       IPosition visshape(svb.visCube().shape());
    2415           0 :       AlwaysAssert(solveCPar().shape().getLast(2)==visshape.getLast(2),AipsError);
    2416             :       
    2417             :       // Zero flagged data
    2418           0 :       IPosition vblc(3,0,0,0);
    2419           0 :       IPosition vtrc(visshape);  vtrc-=1;      
    2420           0 :       Int nCorr(visshape(0));
    2421           0 :       for (Int i=0;i<nCorr;++i) {
    2422           0 :         vblc(0)=vtrc(0)=i;
    2423           0 :         svb.visCube()(vblc,vtrc).reform(visshape.getLast(2))(svb.flag())=Complex(1.0);
    2424             :       }
    2425             :       
    2426             :       // Form correct slice of visCube to copy to solveCPar
    2427           0 :       IPosition vcblc(3,0,0,0);
    2428           0 :       IPosition vctrc(svb.visCube().shape()); vctrc-=1;
    2429           0 :       IPosition vcstr(3,1,1,1);
    2430             : 
    2431           0 :       IPosition spblc(3,0,0,0);
    2432           0 :       IPosition sptrc(solveCPar().shape()); sptrc-=1;
    2433             : 
    2434           0 :       IPosition flshape(svb.flag().shape());
    2435             :       
    2436           0 :       switch (nCorr) {
    2437           0 :       case 1: {
    2438             :         // fill 1st par only
    2439           0 :         spblc(0)=sptrc(0)=0; 
    2440           0 :         solveCPar()(spblc,sptrc)=svb.visCube();
    2441             :         // first pol flags
    2442           0 :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    2443           0 :         break;
    2444             :       }
    2445           0 :       case 2: {
    2446             :         // shapes match
    2447           0 :         solveCPar()=svb.visCube();
    2448           0 :         spblc(0)=sptrc(0)=0; 
    2449           0 :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    2450           0 :         spblc(0)=sptrc(0)=1; 
    2451           0 :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    2452             : 
    2453           0 :         break;
    2454             :       }
    2455           0 :       case 4: {
    2456             :         // Slice visCube with stride
    2457           0 :         vcstr(0)=3;
    2458           0 :         solveCPar()=svb.visCube()(vcblc,vctrc,vcstr);
    2459           0 :         spblc(0)=sptrc(0)=0; 
    2460           0 :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    2461           0 :         spblc(0)=sptrc(0)=1; 
    2462           0 :         solveParOK()(spblc,sptrc).reform(flshape)=!svb.flag();
    2463             : 
    2464           0 :         break;
    2465             :       }
    2466           0 :       default:
    2467           0 :         throw(AipsError("Problem in MMueller::selfSolve."));
    2468             :         break;
    2469             :       }
    2470             : 
    2471           0 :       nGood++;
    2472             : 
    2473             :       // record in in-memory caltable
    2474           0 :       keepNCT();
    2475           0 :     }
    2476           0 :   }
    2477             :   
    2478             :   logSink() << "  Found good "
    2479           0 :             << typeName() << " solutions in "
    2480             :             << nGood << " intervals."
    2481           0 :             << LogIO::POST;
    2482             : 
    2483             :   // Store whole of result in a caltable
    2484           0 :   if (nGood==0)
    2485             :     logSink() << "No output calibration table written."
    2486           0 :               << LogIO::POST;
    2487             :   else {
    2488             : 
    2489             :     // Do global post-solve tinkering (e.g., normalization)
    2490           0 :     globalPostSolveTinker();
    2491             : 
    2492             :     // write the table
    2493           0 :     storeNCT();
    2494             :   }
    2495             : 
    2496           0 : }
    2497             : 
    2498           0 : void MMueller::globalPostSolveTinker() {
    2499             : 
    2500             :   // normalize, if requested
    2501           0 :   if (solnorm()) normalize();
    2502             : 
    2503           0 : }
    2504             : 
    2505           0 : void MMueller::selfSolveOne(SDBList& sdbs) {
    2506             : 
    2507           0 :   AlwaysAssert(useGenGathSolve_p,AipsError);
    2508             :   
    2509             :   // Call the implementation...
    2510           0 :   this->solveOne(sdbs);
    2511             : 
    2512           0 : }
    2513             : 
    2514           0 : void MMueller::createCorruptor(const VisIter& vi, const Record& simpar, const Int nSim) 
    2515             : {
    2516           0 :   LogIO os(LogOrigin("MM", "createCorruptor()", WHERE));
    2517             : 
    2518           0 :   if (prtlev()>2) cout << "   MM::createCorruptor()" << endl;
    2519             :   os << LogIO::DEBUG1 << "   MM::createCorruptor()" 
    2520           0 :      << LogIO::POST;
    2521             : 
    2522           0 :   atmcorruptor_p = new AtmosCorruptor();
    2523           0 :   corruptor_p = atmcorruptor_p;
    2524             : 
    2525             :   // call generic parent to set corr,spw,etc info
    2526           0 :   SolvableVisCal::createCorruptor(vi,simpar,nSim);
    2527             : 
    2528           0 :   Int rxType(0); // 0=2SB, 1=DSB
    2529           0 :   if (simpar.isDefined("rxType")) {    
    2530           0 :     rxType=simpar.asInt("rxType");
    2531             :   }
    2532             :  
    2533             :   // this is the M type corruptor - maybe we should make the corruptor 
    2534             :   // take the VC as an argument
    2535           0 :   atmcorruptor_p->initialize(vi,simpar,VisCal::M,rxType); 
    2536           0 : }
    2537             : 
    2538           0 : void MMueller::solveOne(SDBList& sdbs) {
    2539             : 
    2540           0 :   AlwaysAssert(useGenGathSolve_p,AipsError);
    2541             :   
    2542             :   // This just a simple average of the parallel-hand
    2543             : 
    2544           0 :   Int nSDB=sdbs.nSDB();
    2545             : 
    2546             :   //cout << "nSDB=" << nSDB << endl;
    2547             : 
    2548             :   // We are actually solving for all channels simultaneously
    2549           0 :   solveCPar().reference(solveAllCPar());
    2550           0 :   solveParOK().reference(solveAllParOK());
    2551           0 :   solveParErr().reference(solveAllParErr());
    2552           0 :   solveParSNR().reference(solveAllParSNR());
    2553             :   
    2554             :   // Fill solveCPar() with 0, nominally, and flagged
    2555           0 :   solveCPar()=Complex(0.0);
    2556           0 :   solveParOK()=false;
    2557             : 
    2558           0 :   Cube<Float> sumwt(solveCPar().shape(),0.0f);
    2559           0 :   Int nChan=sdbs.nChannels();
    2560           0 :   AlwaysAssert(nChan==nChanPar(),AipsError);  // channelization should be consistent
    2561           0 :   Int nCorr=sdbs.nCorrelations();
    2562           0 :   Int dCorr=( nCorr==4 ? 3 : 1 );
    2563             : 
    2564           0 :   for (Int isdb=0;isdb<nSDB;++isdb) {
    2565           0 :     SolveDataBuffer& sdb(sdbs(isdb));
    2566             :     
    2567           0 :     Int nRow=sdb.nRows();
    2568             : 
    2569             :     // Zero flagged data
    2570           0 :     Cube<Complex> vc(sdb.visCubeCorrected()); // non-const access
    2571           0 :     vc(sdb.flagCube())=Complex(0.0);
    2572             : 
    2573           0 :     const Vector<Int>& a1(sdb.antenna1()), a2(sdb.antenna2());
    2574             : 
    2575           0 :     Cube<Complex> vis,sol;
    2576           0 :     Cube<Float> wt,swt;
    2577           0 :     Cube<Bool> fl,solok;
    2578           0 :     Slice chsl; // whole slice on chan axis
    2579           0 :     for (Int irow=0;irow<nRow;++irow) {
    2580           0 :       Slice vrsl(irow,1,1), srsl(blnidx(a1(irow),a2(irow)),1,1);
    2581           0 :       for (Int icor=0;icor<nCorr;icor+=dCorr) {
    2582           0 :         Slice vcsl(icor,1,1), scsl(icor%2,1,1);
    2583             : 
    2584           0 :         vis.reference(sdb.visCubeCorrected()(vcsl,chsl,vrsl));
    2585           0 :         wt.reference(sdb.weightSpectrum()(vcsl,chsl,vrsl));
    2586           0 :         fl.reference(sdb.flagCube()(vcsl,chsl,vrsl));
    2587           0 :         sol.reference(solveCPar()(scsl,chsl,srsl));
    2588           0 :         solok.reference(solveParOK()(scsl,chsl,srsl));
    2589           0 :         swt.reference(sumwt(scsl,chsl,srsl));
    2590             : 
    2591             :         // Accumulate
    2592           0 :         sol+=(vis*wt);
    2593           0 :         swt+=wt;
    2594           0 :         solok|=!fl;
    2595             :       }
    2596             :     }
    2597           0 :   }
    2598             : 
    2599             :   // Normalize
    2600           0 :   sumwt(!solveParOK())=(1.0);
    2601           0 :   solveCPar()/=sumwt;
    2602             : 
    2603             :   // TBD....  (move to MMueller::postSolveTinker, since this is wrong for AMueller!)
    2604             :   //solveCPar()(!solveParOK())=Complex(1.0); // set flagged ones to 1.0
    2605             : 
    2606           0 : }
    2607             : 
    2608             : 
    2609             : // **********************************************************
    2610             : //  MfMueller: freq-dep MMueller
    2611             : //
    2612             : 
    2613           0 : MfMueller::MfMueller(VisSet& vs) :
    2614             :   VisCal(vs),             // virtual base
    2615             :   VisMueller(vs),         // virtual base
    2616           0 :   MMueller(vs)            // immediate parent
    2617             : {
    2618           0 :   if (prtlev()>2) cout << "Mf::Mf(vs)" << endl;
    2619           0 : }
    2620             : 
    2621           0 : MfMueller::MfMueller(String msname,Int MSnAnt,Int MSnSpw) :
    2622             :   VisCal(msname,MSnAnt,MSnSpw),             // virtual base
    2623             :   VisMueller(msname,MSnAnt,MSnSpw),         // virtual base
    2624           0 :   MMueller(msname,MSnAnt,MSnSpw)            // immediate parent
    2625             : {
    2626           0 :   if (prtlev()>2) cout << "Mf::Mf(msname,MSnAnt,MSnSpw)" << endl;
    2627           0 : }
    2628             : 
    2629           0 : MfMueller::MfMueller(const MSMetaInfoForCal& msmc) :
    2630             :   VisCal(msmc),             // virtual base
    2631             :   VisMueller(msmc),         // virtual base
    2632           0 :   MMueller(msmc)            // immediate parent
    2633             : {
    2634           0 :   if (prtlev()>2) cout << "Mf::Mf(msmc)" << endl;
    2635           0 : }
    2636             : 
    2637           0 : MfMueller::MfMueller(const Int& nAnt) :
    2638             :   VisCal(nAnt), 
    2639             :   VisMueller(nAnt),
    2640           0 :   MMueller(nAnt)
    2641             : {
    2642           0 :   if (prtlev()>2) cout << "Mf::Mf(nAnt)" << endl;
    2643           0 : }
    2644             : 
    2645           0 : MfMueller::~MfMueller() {
    2646           0 :   if (prtlev()>2) cout << "Mf::~Mf()" << endl;
    2647           0 : }
    2648             : 
    2649           0 : void MfMueller::normalize() {
    2650             : 
    2651             :   // This is just like BJones
    2652             :   // TBD:  consolidate (via generalized SVC::normalize(Block<String> cols) )
    2653             : 
    2654             :   // Only if we have a CalTable, and it is not empty
    2655           0 :   if (ct_ && ct_->nrow()>0) {
    2656             : 
    2657             :     // TBD: trap attempts to normalize a caltable containing FPARAM (non-Complex)?
    2658             : 
    2659             :     logSink() << "Normalizing solutions per spw, pol, baseline, time"
    2660           0 :               << LogIO::POST;
    2661             : 
    2662           0 :     Block<String> col(4);
    2663           0 :     col[0]="SPECTRAL_WINDOW_ID";
    2664           0 :     col[1]="TIME";
    2665           0 :     col[2]="ANTENNA1";
    2666           0 :     col[3]="ANTENNA2";
    2667           0 :     CTIter ctiter(*ct_,col);
    2668             : 
    2669             :     // Cube iteration axes are pol and ant
    2670           0 :     IPosition itax(2,0,2);
    2671             :    
    2672           0 :     while (!ctiter.pastEnd()) {
    2673           0 :       Cube<Bool> fl(ctiter.flag());
    2674             :       
    2675           0 :       if (nfalse(fl)>0) {
    2676           0 :         Cube<Complex> p(ctiter.cparam());
    2677           0 :         ArrayIterator<Complex> soliter(p,itax,false);
    2678           0 :         ArrayIterator<Bool> fliter(fl,itax,false);
    2679           0 :         while (!soliter.pastEnd()) {
    2680           0 :           normSolnArray(soliter.array(),!fliter.array(),true); // Do phase
    2681           0 :           soliter.next();
    2682           0 :           fliter.next();
    2683             :         }
    2684             :         
    2685             :         // record result...     
    2686           0 :         ctiter.setcparam(p);
    2687           0 :       }
    2688           0 :       ctiter.next();
    2689           0 :     }
    2690           0 :   }
    2691           0 :   cout << "End of MfMueller::normalize()" << endl;
    2692           0 : }
    2693             : 
    2694             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16