LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - SkyEquation.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 261 849 30.7 %
Date: 2024-10-04 18:58:15 Functions: 27 61 44.3 %

          Line data    Source code
       1             : //# SkyEquation.cc: Implementation of Sky Equation classes
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : #include <casacore/casa/BasicSL/Complex.h>
      28             : #include <casacore/casa/Arrays/Matrix.h>
      29             : #include <casacore/measures/Measures/MeasConvert.h>
      30             : #include <synthesis/MeasurementEquations/SkyEquation.h>
      31             : #include <casacore/images/Images/ImageInterface.h>
      32             : #include <casacore/images/Images/SubImage.h>
      33             : #include <casacore/images/Regions/ImageRegion.h>
      34             : #include <synthesis/TransformMachines/SkyJones.h>
      35             : #include <synthesis/TransformMachines/FTMachine.h>
      36             : 
      37             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      38             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      39             : 
      40             : #include <components/ComponentModels/Flux.h>
      41             : #include <components/ComponentModels/PointShape.h>
      42             : #include <components/ComponentModels/ConstantSpectrum.h>
      43             : 
      44             : #include <synthesis/TransformMachines/ComponentFTMachine.h>
      45             : #include <synthesis/MeasurementComponents/SkyModel.h>
      46             : 
      47             : #include <msvis/MSVis/VisSet.h>
      48             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      49             : #include <msvis/MSVis/StokesVector.h>
      50             : #include <msvis/MSVis/VisBufferUtil.h>
      51             : 
      52             : #include <casacore/casa/Arrays/ArrayMath.h>
      53             : #include <casacore/casa/Arrays/MatrixMath.h>
      54             : #include <casacore/casa/Utilities/Assert.h>
      55             : #include <casacore/casa/BasicSL/String.h>
      56             : #include <casacore/lattices/Lattices/Lattice.h>
      57             : #include <casacore/measures/Measures/UVWMachine.h>
      58             : #include <casacore/lattices/Lattices/ArrayLattice.h>
      59             : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
      60             : #include <casacore/lattices/LEL/LatticeExpr.h>
      61             : #include <casacore/lattices/Lattices/TiledLineStepper.h>
      62             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      63             : #include <casacore/lattices/Lattices/LatticeStepper.h>
      64             : #include <casacore/lattices/LRegions/LCRegion.h>
      65             : #include <casacore/casa/Containers/Block.h>
      66             : 
      67             : #include <casacore/casa/Exceptions/Error.h>
      68             : #include <msvis/MSVis/VisibilityIterator.h>
      69             : #include <msvis/MSVis/VisBuffer.h>
      70             : ///////////////#include <msvis/MSVis/VisBufferAsync.h>
      71             : #include <iostream>
      72             : 
      73             : #include <casacore/casa/System/ProgressMeter.h>
      74             : 
      75             : #include <memory>
      76             : 
      77             : using namespace casacore;
      78             : namespace casa { //# NAMESPACE CASA - BEGIN
      79             : 
      80             : // ***************************************************************************
      81             : // ********************  Start of public member functions ********************
      82             : // ***************************************************************************
      83             : 
      84             : 
      85             : //----------------------------------------------------------------------
      86           0 : SkyEquation::SkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft,
      87           0 :                          FTMachine& ift)
      88           0 :   : sm_(&sm), vs_(&vs), ft_(&ft), ift_(&ift), cft_(0), ej_(0), dj_(0), 
      89           0 :     tj_(0), fj_(0), iDebug_p(0), isPSFWork_p(false), noModelCol_p(false), isBeginingOfSkyJonesCache_p(true), doflat_p(false)
      90             : {
      91           0 :   rvi_p=&(vs_->iter());
      92           0 :   wvi_p=&(vs_->iter());
      93             : 
      94           0 :   vb_p.set (rvi_p);
      95           0 : };
      96             : 
      97             : //----------------------------------------------------------------------
      98           0 : SkyEquation::SkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft)
      99           0 :   : sm_(&sm), vs_(&vs), ft_(&ft), ift_(&ft), cft_(0), ej_(0), dj_(0), 
     100           0 :     tj_(0), fj_(0), iDebug_p(0), isPSFWork_p(false),noModelCol_p(false), isBeginingOfSkyJonesCache_p(true), doflat_p(false)
     101             : {
     102           0 :   rvi_p=&(vs_->iter());
     103           0 :   wvi_p=&(vs_->iter());
     104             : 
     105             : 
     106           0 :   vb_p.set (rvi_p);
     107           0 : };
     108             : 
     109             : //----------------------------------------------------------------------
     110           0 : SkyEquation::SkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft,
     111           0 :                          FTMachine& ift, ComponentFTMachine& cft)
     112           0 :   : sm_(&sm), vs_(&vs), ft_(&ft), ift_(&ift), cft_(&cft), ej_(0),
     113           0 :     dj_(0), tj_(0), fj_(0), iDebug_p(0), isPSFWork_p(false),noModelCol_p(false),isBeginingOfSkyJonesCache_p(true), doflat_p(false)
     114             : {
     115           0 :   rvi_p=&(vs_->iter());
     116           0 :   wvi_p=&(vs_->iter());
     117             : 
     118             : 
     119           0 :   vb_p.set (rvi_p);
     120           0 : };
     121             : 
     122             : //----------------------------------------------------------------------
     123          22 : SkyEquation::SkyEquation(SkyModel& sm, VisSet& vs, FTMachine& ft,
     124          22 :                          ComponentFTMachine& cft, Bool noModelCol)
     125          22 :   : sm_(&sm), vs_(&vs), ft_(&ft), ift_(&ft), cft_(&cft), ej_(0),
     126          66 :     dj_(0), tj_(0), fj_(0), iDebug_p(0), isPSFWork_p(false), 
     127          22 :     noModelCol_p(noModelCol),isBeginingOfSkyJonesCache_p(true),doflat_p(false)
     128             : {
     129             : 
     130          22 :   rvi_p=&(vs_->iter());
     131             : 
     132          22 :   wvi_p=&(vs_->iter());
     133          22 :   vb_p.set (rvi_p);
     134          22 : };
     135             : 
     136          14 : SkyEquation::SkyEquation(SkyModel& sm, ROVisibilityIterator& vi, FTMachine& ft,
     137          14 :                          ComponentFTMachine& cft, Bool noModelCol)
     138          14 :   : sm_(&sm), ft_(&ft), ift_(&ft), cft_(&cft), ej_(0),
     139          42 :     dj_(0), tj_(0), fj_(0), iDebug_p(0), isPSFWork_p(false), 
     140          14 :     noModelCol_p(noModelCol),isBeginingOfSkyJonesCache_p(true), doflat_p(false){
     141             : 
     142             : 
     143             :   //visiter is read only
     144          14 :   rvi_p=&vi;
     145          14 :   if(rvi_p->ms().isWritable())
     146          14 :     wvi_p=static_cast<VisibilityIterator *>(&vi);
     147             :   else
     148           0 :     wvi_p=NULL;
     149             : 
     150          14 :   vb_p.set (rvi_p);
     151          14 : }
     152             : 
     153             : //----------------------------------------------------------------------
     154          58 : SkyEquation::~SkyEquation() {
     155          58 : }
     156             : 
     157             : //---------------------------------------------------------------------- 
     158           0 : SkyEquation& SkyEquation::operator=(const SkyEquation& other)
     159             : {
     160           0 :   if(this!=&other) {
     161           0 :     sm_=other.sm_;
     162           0 :     vs_=other.vs_;
     163           0 :     ft_=other.ft_;
     164           0 :     ift_=other.ift_;
     165           0 :     cft_=other.cft_;
     166           0 :     ej_=other.ej_;
     167           0 :     dj_=other.dj_;
     168           0 :     tj_=other.tj_;
     169           0 :     fj_=other.fj_;
     170           0 :     rvi_p=other.rvi_p;
     171           0 :     wvi_p=other.wvi_p;
     172           0 :     doflat_p=other.doflat_p;
     173           0 :     vb_p = other.vb_p;
     174             :   };
     175           0 :   return *this;
     176             : };
     177             : 
     178             : //----------------------------------------------------------------------
     179           0 : SkyEquation::SkyEquation(const SkyEquation& other)
     180             : {
     181           0 :   operator=(other);
     182           0 : }
     183             : 
     184             : //----------------------------------------------------------------------
     185          14 : void SkyEquation::setSkyJones(SkyJones& j) {
     186          14 :   SkyJones::Type t=j.type();
     187          14 :   switch(t) {
     188          14 :   case SkyJones::E: 
     189          14 :     ej_=&j;
     190          14 :     break;
     191           0 :   case SkyJones::D: 
     192           0 :     dj_=&j;
     193           0 :     break;
     194           0 :   case SkyJones::T: 
     195           0 :     tj_=&j;
     196           0 :     break;
     197           0 :   case SkyJones::F: 
     198           0 :     fj_=&j;
     199           0 :     break;
     200             :   }
     201          14 : };
     202             : 
     203             : //----------------------------------------------------------------------
     204             : // Predict the Sky coherence
     205             : //void SkyEquation::predictComponents(Bool& incremental, Bool& initialized){
     206             : //  predictComponents(incrementa,initialized,MS::MODEL_DATA);
     207             : //}
     208             : 
     209          22 : void SkyEquation::predictComponents(Bool& incremental, Bool& initialized,  MS::PredefinedColumns Type){
     210             :   // Initialize 
     211             :   
     212             :    // Do the component model only if this is not an incremental update;
     213          22 :   if(sm_->hasComponentList() &&  !incremental ) {
     214             :     //if(noModelCol_p)
     215             :     //    throw(AipsError("Cannot deal with componentlists without using scratch columns yet"));
     216           7 :     if(wvi_p==NULL)
     217           0 :       throw(AipsError("Cannot save model in non-writable ms"));
     218           7 :     VisIter& vi=*wvi_p;
     219           7 :     checkVisIterNumRows(vi);
     220           7 :     VisBufferAutoPtr vb(vi);
     221             : 
     222             :     // Reset the various SkyJones
     223           7 :     resetSkyJones();
     224             : 
     225             :     // Loop over all visibilities
     226             : 
     227             : //    This code is currently commented out because numberCoh
     228             : //    called on the VI is weird relative to the VI Async semantics,
     229             : //    at least at first glance
     230             : //
     231             : //    Int cohDone=0;
     232             : //    ProgressMeter pm(1.0, Double(vi.numberCoh()),
     233             : //                   "Predicting component coherences",
     234             : //                   "", "", "", true);
     235           7 :     Int oldmsid=-1;
     236             : 
     237          44 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     238         273 :       for (vi.origin(); vi.more(); vi++) {
     239         236 :         if(!noModelCol_p){
     240         236 :           if(!incremental&&!initialized) {
     241         236 :             vb->setModelVisCube(Complex(0.0,0.0));
     242             :             //    vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     243             :           }
     244             :           
     245             : 
     246             :           // get always fills Model
     247         236 :           get(* vb, sm_->componentList() );
     248             :           
     249             :           // and write it to the model MS
     250         236 :           switch(Type) {
     251           0 :           case MS::MODEL_DATA:    
     252           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     253           0 :             break;
     254         236 :           case MS::DATA:          
     255         236 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Observed);
     256         236 :             break;
     257           0 :           case MS::CORRECTED_DATA:        
     258           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Corrected);
     259           0 :             break;
     260           0 :           default:
     261           0 :             throw (AipsError("Programmer made a wrong call"));
     262             :           }
     263             :         }
     264             :         else{
     265           0 :           if(vb->msId() != oldmsid){
     266           0 :             oldmsid=vb->msId();
     267           0 :             String err;
     268           0 :             Record clrec;
     269             :             //cerr << "in componentlist saving" << endl;
     270           0 :             if(anyGT(Int(Stokes::RR), vb->corrType())){
     271           0 :               throw(AipsError("Invalid MS: correlation type cannot be decomposed into feed product; DataDescId="+String::toString(vb->dataDescriptionId()) ));
     272             :             } 
     273           0 :             if(!sm_->componentList().toRecord(err, clrec))
     274           0 :               throw(AipsError("Error saving componentlist: "+err));
     275           0 :             vi.putModel(clrec, true, true);
     276           0 :           }
     277             : 
     278             :         }
     279             : //  See above commented-out code
     280             : //      cohDone+=vb->nRow();
     281             : //      pm.update(Double(cohDone));
     282             :       }
     283             :     }
     284           7 :     if(!incremental&&!initialized) initialized=true;
     285           7 :   }
     286             : 
     287             : 
     288          22 : }
     289             : 
     290          22 : void SkyEquation::predict(Bool incremental,  MS::PredefinedColumns Type) {
     291             : 
     292             : 
     293             : 
     294             :   //  if(noModelCol_p)
     295             :   //        throw(AipsError("Cannot predict model vis without using scratch columns yet"));
     296          22 :   AlwaysAssert(cft_, AipsError);
     297          22 :   AlwaysAssert(sm_, AipsError);
     298             :   //AlwaysAssert(vs_, AipsError);
     299          22 :   if(sm_->numberOfModels()!= 0)  AlwaysAssert(ok(),AipsError);
     300             :   // Initialize 
     301          22 :   VisIter& vi= *wvi_p;
     302          22 :   checkVisIterNumRows(vi);
     303             : 
     304          22 :   VisBufferAutoPtr vb(vi);
     305             : 
     306             :   // Reset the visibilities only if this is not an incremental
     307             :   // change to the model
     308          22 :   Bool initialized=false;
     309             :   // **** predictcomponents doesn't do anything if incremental!
     310             :   // it gets components into vb->model, and writes to vi::(Type)
     311          22 :   predictComponents(incremental, initialized, Type);
     312             : 
     313             :   // Now do the images
     314          40 :   for (Int model=0;model<sm_->numberOfModels();model++) {      
     315             :     
     316          18 :     if( (sm_->isEmpty(model)) && (model==0) && !initialized && !incremental){ 
     317             :       // We are at the begining with an empty model start
     318           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     319           0 :         for (vi.origin(); vi.more(); vi++) {
     320           0 :           switch(Type) {
     321           0 :           case MS::MODEL_DATA:
     322           0 :             vb->setModelVisCube(Complex(0.0,0.0));
     323           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     324           0 :             break;
     325           0 :           case MS::DATA:
     326           0 :             vb->setModelVisCube(Complex(0.0,0.0));
     327           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Observed);
     328           0 :             break;
     329           0 :           case MS::CORRECTED_DATA:
     330           0 :             vb->setModelVisCube(Complex(0.0,0.0));
     331           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Corrected);
     332           0 :             break;
     333           0 :           default:
     334           0 :             throw (AipsError("Programmer made a wrong call"));
     335             :           }
     336             :         }
     337             :       }
     338             :       //if (!incremental&&!initialized) initialized=true;
     339             : 
     340             : 
     341             :     }
     342             :     // Don't bother with empty images
     343          18 :     if(!sm_->isEmpty(model)) {
     344             :       
     345             :       // Change the model polarization frame
     346          18 :       if(vb->polFrame()==MSIter::Linear) {
     347          18 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     348             :                                           StokesImageUtil::LINEAR);
     349             :       }
     350             :       else {
     351           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     352             :                                           StokesImageUtil::CIRCULAR);
     353             :       }
     354             :       
     355          18 :       scaleImage(model, incremental);
     356             : 
     357             :       // Reset the various SkyJones
     358          18 :       resetSkyJones();
     359             :       
     360             : 
     361             :       // Initialize get (i.e. Transform from Sky)
     362          18 :       vi.originChunks();
     363          18 :       vi.origin();      
     364          18 :       initializeGet(* vb, 0, model, incremental);
     365          18 :       Int cohDone=0;
     366             :       
     367          18 :       ostringstream modelName;modelName<<"Model "<<model+1
     368          18 :                                     <<" : predicting coherences";
     369          18 :       ProgressMeter pm(1.0, Double(vi.numberCoh()),
     370          54 :                        modelName, "", "", "", true);
     371             :       // Loop over all visibilities
     372         352 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     373         692 :         for (vi.origin(); vi.more(); vi++) {
     374         358 :           if(!incremental&&!initialized) {
     375         343 :             vb->setModelVisCube(Complex(0.0,0.0));
     376             :             //      vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     377         343 :             switch(Type) {
     378           0 :             case MS::MODEL_DATA:
     379           0 :               vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     380           0 :               break;
     381         343 :             case MS::DATA:
     382         343 :               vi.setVis(vb->modelVisCube(),VisibilityIterator::Observed);
     383         343 :               break;
     384           0 :             case MS::CORRECTED_DATA:
     385           0 :               vi.setVis(vb->modelVisCube(),VisibilityIterator::Corrected);
     386           0 :               break;
     387           0 :             default:
     388           0 :               throw (AipsError("Programmer made a wrong call"));
     389             :             }
     390             :           }
     391             :           // get the model visibility (adds to vb->model)
     392             :           //get(vb,model,incremental);
     393             :           // this version takes Type and reads existing Type col instead 
     394             :           // of hardcoded existing MODEL column
     395         358 :           get(* vb,model,incremental,Type);
     396             :           // and write it to VI   
     397         358 :           switch(Type) {
     398           0 :           case MS::MODEL_DATA:
     399           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Model);
     400           0 :             break;
     401         358 :           case MS::DATA:
     402         358 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Observed);
     403         358 :             break;
     404           0 :           case MS::CORRECTED_DATA:
     405           0 :             vi.setVis(vb->modelVisCube(),VisibilityIterator::Corrected);
     406           0 :             break;
     407           0 :           default:
     408           0 :             throw (AipsError("Programmer made a wrong call"));
     409             :           }
     410         358 :           cohDone+=vb->nRow();
     411         358 :           pm.update(Double(cohDone));
     412             :         }
     413             :       }
     414          18 :       finalizeGet();
     415          18 :       unScaleImage(model, incremental);
     416          18 :       if(!incremental&&!initialized) initialized=true;
     417             :     
     418          18 :     } else {
     419           0 :       cout << "WARN: model is empty." << endl;
     420             :     }
     421             :   }
     422          22 : }
     423             : 
     424             : //----------------------------------------------------------------------
     425           0 : void SkyEquation::gradientsChiSquared(const Matrix<Bool>&,
     426             :                                       SkyJones&) {
     427           0 :   throw(AipsError("SkyEquation:: solution for SkyJones not yet implemented"));
     428             : }
     429             : 
     430             : //----------------------------------------------------------------------
     431           0 : void SkyEquation::gradientsChiSquared(Bool incremental, Bool commitModel) {
     432           0 :   AlwaysAssert(ok(),AipsError);
     433             : 
     434           0 :   if ((ft_->name() == "PBWProjectFT"))
     435             :     {
     436           0 :       ft_->setNoPadding(false);
     437           0 :       fullGradientsChiSquared(incremental);
     438             :     }
     439             :   else
     440             :     {
     441           0 :   Bool forceFull=true;
     442             :   // for these 2 gridders force incremental
     443           0 :   if((ft_->name() == "MosaicFT") || (ft_->name() == "WProjectFT"))
     444           0 :     forceFull=true;
     445             : 
     446           0 :   if( (sm_->numberOfModels() != 1) || !ft_->isFourier() || !incremental 
     447           0 :       || forceFull){
     448           0 :     if(commitModel || !noModelCol_p){
     449           0 :       ft_->setNoPadding(false);
     450           0 :       fullGradientsChiSquared(incremental);
     451             :     }
     452             :     else{
     453             :       // For now use corrected_data...
     454           0 :       ft_->setNoPadding(true);
     455           0 :       cout << "This mode is gone...we should not be coming here" << endl;
     456             :     }
     457             :   }
     458             :   else {
     459           0 :     incrementGradientsChiSquared();
     460             :   }
     461             :     }
     462           0 : }
     463             : //----------------------------------------------------------------------
     464           0 : void SkyEquation::fullGradientsChiSquared(Bool incremental) {
     465             : 
     466           0 :   AlwaysAssert(ok(),AipsError);
     467             : 
     468             :   // Predict the visibilities
     469           0 :   predict(incremental);
     470             : 
     471           0 :   sumwt = 0.0;
     472           0 :   chisq = 0.0;
     473             : 
     474             :   // Initialize the gradients
     475           0 :   sm_->initializeGradients();
     476             : 
     477           0 :   ROVisIter& vi(*rvi_p);
     478             : 
     479             :   // Loop over all models in SkyModel
     480           0 :   for (Int model=0;model<sm_->numberOfModels();model++) {
     481             : 
     482             :     // Reset the various SkyJones
     483           0 :     resetSkyJones();
     484             : 
     485             :     // Loop over all visibilities and pixels
     486           0 :     checkVisIterNumRows(vi);
     487           0 :     VisBuffer vb(vi);
     488             :       
     489           0 :     if(sm_->isSolveable(model)) {
     490             : 
     491             :       // Initialize 
     492           0 :       scaleImage(model, incremental);
     493             : 
     494           0 :       vi.originChunks();
     495           0 :       vi.origin();
     496             : 
     497             :       // Change the model polarization frame
     498           0 :       if(vb.polFrame()==MSIter::Linear) {
     499           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     500             :                                           StokesImageUtil::LINEAR);
     501             :       }
     502             :       else {
     503           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     504             :                                           StokesImageUtil::CIRCULAR);
     505             :       }
     506             : 
     507           0 :       initializePut(vb, model);
     508           0 :       Int cohDone=0;
     509             :       
     510           0 :       ostringstream modelName;modelName<<"Model "<<model+1
     511           0 :                                     <<" : transforming residuals";
     512           0 :       ProgressMeter pm(1.0, Double(vi.numberCoh()),
     513           0 :                        modelName, "", "", "", true);
     514             :       // Loop over the visibilities, putting VisBuffers
     515             :       
     516           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     517           0 :         for (vi.origin(); vi.more(); vi++) {
     518           0 :           vb.modelVisCube()-=vb.correctedVisCube();
     519             :           //      vb.setVisCube(vb.modelVisCube());
     520           0 :           put(vb, model, false, FTMachine::MODEL);
     521           0 :           cohDone+=vb.nRow();
     522           0 :           pm.update(Double(cohDone));
     523             :         }
     524             :       }
     525             :       // Do the transform, apply the SkyJones transformation
     526             :       // and sum the statistics for this model
     527           0 :       finalizePut(* vb_p, model);
     528           0 :       unScaleImage(model, incremental);
     529           0 :     }
     530           0 :   }
     531             : 
     532           0 :   fixImageScale();
     533             : 
     534             :   // Finish off any calculations needed internal to SkyModel
     535           0 :   sm_->finalizeGradients();
     536             : 
     537           0 : }
     538             : 
     539             : //----------------------------------------------------------------------
     540             : 
     541             : 
     542             : //----------------------------------------------------------------------
     543             : 
     544             : 
     545           0 : void SkyEquation::incrementGradientsChiSquared() {
     546             : 
     547           0 :   AlwaysAssert(ok(),AipsError);
     548             : 
     549             :   // Check to see if we need to make the XFRs
     550           0 :   if(!sm_->hasXFR(0)) makeComplexXFRs();
     551             : 
     552           0 :   ROVisIter& vi(*rvi_p);
     553             : 
     554             :   // Reset the various SkyJones
     555           0 :   resetSkyJones();
     556             : 
     557             :   // Loop over all models in SkyModel
     558           0 :   for (Int model=0;model<sm_->numberOfModels();model++) {
     559             : 
     560           0 :     if(sm_->isSolveable(model)) {
     561             : 
     562           0 :       iDebug_p++;
     563             : 
     564           0 :       scaleDeltaImage(model);
     565           0 :       VisBuffer vb(vi);
     566           0 :       vi.origin();
     567             : 
     568             :       // Change the model polarization frame
     569           0 :       if(vb.polFrame()==MSIter::Linear) {
     570           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     571             :                                           StokesImageUtil::LINEAR);
     572             :       }
     573             :       else {
     574           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     575             :                                           StokesImageUtil::CIRCULAR);
     576             :       }
     577             : 
     578           0 :       Int numXFR=0;
     579           0 :       vi.originChunks();
     580           0 :       vi.origin();
     581           0 :       initializePutConvolve(vb, model, numXFR);
     582             :       // Iterate
     583           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     584           0 :         for (vi.origin(); vi.more(); vi++) {
     585           0 :           putConvolve(vb, model, numXFR);
     586             :         }
     587             :       }
     588             :       // Finish off
     589           0 :       finalizePutConvolve(* vb_p, model, numXFR);
     590           0 :       unScaleDeltaImage(model);    
     591           0 :     }
     592             :   }
     593             : 
     594             : 
     595             :   // Finish off any calculations needed internal to SkyModel
     596           0 :   sm_->finalizeGradients();
     597           0 : };
     598             : 
     599             : //----------------------------------------------------------------------
     600           0 : void SkyEquation::makeComplexXFRs() 
     601             : {
     602             : 
     603           0 :   AlwaysAssert(ok(),AipsError);
     604             : 
     605           0 :   ROVisIter& vi(*rvi_p);
     606             : 
     607             :   // Loop over all models in SkyModel
     608           0 :   for (Int model=0;model<sm_->numberOfModels();model++) {
     609             : 
     610           0 :     if(sm_->isSolveable(model)) {
     611             : 
     612             :       // Loop over all visibilities and pixels
     613           0 :       VisBuffer vb(vi);
     614             :       
     615             :       // Change the model polarization frame
     616           0 :       if(vb.polFrame()==MSIter::Linear) {
     617           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     618             :                                           StokesImageUtil::LINEAR);
     619             :       }
     620             :       else {
     621           0 :         StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     622             :                                           StokesImageUtil::CIRCULAR);
     623             :       }
     624             : 
     625             :       // Initialize put (i.e. transform to Sky) for this model
     626             :       // and XFR
     627           0 :       vi.origin();
     628           0 :       Int numXFR=0;
     629           0 :       vi.originChunks();
     630           0 :       vi.origin();
     631           0 :       initializePutXFR(vb, model, numXFR);
     632           0 :       Int cohDone=0;
     633             :       
     634           0 :       ostringstream modelName;modelName<<"Model "<<model+1
     635           0 :                                     <<" : transforming to PSF";
     636           0 :       ProgressMeter pm(1.0, Double(vi.numberCoh()),
     637           0 :                        modelName, "", "", "", true);
     638             :       // Loop over the visibilities, putting VisBuffers
     639             :       
     640           0 :       for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     641           0 :         for (vi.origin(); vi.more(); vi++) {
     642             :           
     643           0 :           vb.setVisCube(Complex(1.0,0.0));
     644           0 :           putXFR(vb, model, numXFR);
     645           0 :           cohDone+=vb.nRow();
     646           0 :           pm.update(Double(cohDone));
     647             :         }
     648             :       }
     649             :       // Do the transform, apply the SkyJones transformation
     650             :       // and sum the statistics for this model
     651           0 :       finalizePutXFR(* vb_p, model, numXFR);
     652           0 :     }
     653             :   }
     654           0 : }
     655             : 
     656             : //----------------------------------------------------------------------
     657             : // Solve for a SkyJones
     658           0 : Bool SkyEquation::solveSkyJones(SkyJones& sj) {
     659           0 :   setSkyJones(sj);
     660           0 :   return sj.solve(*this);
     661             : }
     662             : 
     663             : //----------------------------------------------------------------------
     664             : // We make an approximate PSF for each plane.We only do this per model
     665             : // since we may not need all PSFs.
     666             : // ************* Note that this overwrites the model! ******************
     667           0 : void SkyEquation::makeApproxPSF(Int model, ImageInterface<Float>& psf) {
     668             : 
     669           0 :   LogIO os(LogOrigin("SkyEquation", "makeApproxPSF"));
     670             : 
     671           0 :   AlwaysAssert(ok(), AipsError);
     672           0 :   AlwaysAssert(cft_, AipsError);
     673           0 :   AlwaysAssert(sm_, AipsError);
     674             :   //AlwaysAssert(vs_, AipsError);
     675             :   
     676           0 :   ft_->setNoPadding(noModelCol_p);
     677             : 
     678           0 :   isPSFWork_p= true; // avoid PB correction etc for PSF estimation
     679           0 :   Bool doPSF=true;
     680           0 :   if(ft_->name() == "MosaicFT") {
     681             :     // Reset the various SkyJones
     682           0 :     doPSF=false;
     683           0 :     resetSkyJones();
     684             :     
     685           0 :     VisIter& vi(*wvi_p);
     686           0 :     checkVisIterNumRows(vi);
     687             :     // Loop over all visibilities and pixels
     688           0 :     VisBuffer vb(vi);
     689             :     
     690           0 :     vi.originChunks();
     691           0 :     vi.origin();
     692             :     
     693             :     // Change the model polarization frame
     694           0 :     if(vb.polFrame()==MSIter::Linear) {
     695           0 :       StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     696             :                                         StokesImageUtil::LINEAR);
     697             :     }
     698             :     else {
     699           0 :       StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     700             :                                         StokesImageUtil::CIRCULAR);
     701             :     }
     702             :     
     703           0 :     IPosition start(4, sm_->image(model).shape()(0)/2,
     704           0 :                     sm_->image(model).shape()(1)/2, 0, 0);
     705           0 :     IPosition shape(4, 1, 1, sm_->image(model).shape()(2), sm_->image(model).shape()(3));
     706           0 :     Array<Float> line(shape);
     707           0 :     TempImage<Float> savedModel(sm_->image(model).shape(),
     708           0 :                                 sm_->image(model).coordinates());
     709           0 :     savedModel.copyData(sm_->image(model));
     710           0 :     sm_->image(model).set(0.0);
     711           0 :     line=1.0;
     712           0 :     sm_->image(model).putSlice(line, start);
     713             :     //initializeGet(vb, -1, model, false);
     714           0 :     StokesImageUtil::From(sm_->cImage(model), static_cast <const ImageInterface<Float>& >(sm_->image(model)));
     715           0 :     ft_->initializeToVis(sm_->cImage(model),vb);
     716             :     // Loop over all visibilities
     717           0 :     for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     718           0 :       for (vi.origin(); vi.more(); vi++) {
     719           0 :         vb.setModelVisCube(Complex(0.0,0.0));
     720             :         //      get(vb, model, false);
     721           0 :         ft_->get(vb);
     722           0 :         vi.setVis(vb.modelVisCube(),VisibilityIterator::Model);
     723             :       }
     724             :     }
     725           0 :     finalizeGet();
     726             :     
     727           0 :     sm_->image(model).copyData(savedModel);
     728           0 :   }
     729             :   
     730             :   // Initialize the gradients
     731           0 :   sm_->initializeGradients();
     732             :   
     733             : 
     734           0 :   ROVisIter& vi(*rvi_p);
     735             :   
     736             :   // Reset the various SkyJones
     737           0 :   resetSkyJones();
     738             :   
     739           0 :   checkVisIterNumRows(vi);
     740             :   // Loop over all visibilities and pixels
     741           0 :   VisBuffer vb(vi);
     742             : 
     743             : 
     744           0 :   vi.originChunks();
     745           0 :   vi.origin();
     746             :   
     747             :   // Change the model polarization frame
     748           0 :   if(vb.polFrame()==MSIter::Linear) {
     749           0 :     StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     750             :                                       StokesImageUtil::LINEAR);
     751             :   }
     752             :   else {
     753           0 :     StokesImageUtil::changeCStokesRep(sm_->cImage(model),
     754             :                                       StokesImageUtil::CIRCULAR);
     755             :   }
     756             : 
     757             : 
     758           0 :   initializePut(vb, model);
     759             :   
     760             :   // Loop over the visibilities, putting VisBuffers
     761           0 :   for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
     762           0 :     for (vi.origin(); vi.more(); vi++) {
     763             :       // vb.setVisCube(vb.modelVisCube());
     764           0 :       put(vb, model, doPSF, FTMachine::MODEL);
     765             :     }
     766             :   }
     767             :   
     768             :   // Do the transform, apply the SkyJones transformation
     769           0 :   finalizePut(* vb_p, model);
     770           0 :   sm_->finalizeGradients();
     771           0 :   fixImageScale();
     772           0 :   LatticeExpr<Float> le(iif(sm_->ggS(model)>(0.0),
     773           0 :                             (sm_->gS(model)/sm_->ggS(model)), 0.0));
     774           0 :   psf.copyData(le);
     775           0 :   LatticeExprNode maxPSF=max(psf);
     776           0 :   Float maxpsf=maxPSF.getFloat();
     777           0 :   if(abs(maxpsf-1.0) > 1e-3) {
     778             :     os << "Maximum of approximate PSF for field " << model << " = "
     779           0 :        << maxpsf << " : renormalizing to unity" <<  LogIO::POST;
     780             :   }
     781           0 :   if(maxpsf > 0.0 ){
     782           0 :     LatticeExpr<Float> len(psf/maxpsf);
     783           0 :     psf.copyData(len);
     784             :  
     785           0 :   }
     786             :   else{
     787           0 :      throw(AipsError("SkyEquation:: PSF calculation resulted in a PSF lesser than 0 !"));
     788             : 
     789             :   }
     790             :  
     791             : 
     792             : 
     793           0 :   isPSFWork_p=false; // resseting this flag so that subsequent calculation uses
     794             :   // the right SkyJones correction;
     795             :   
     796             :   
     797           0 : }
     798             : 
     799           0 : void SkyEquation::makeApproxPSF(PtrBlock<ImageInterface<Float> *>& PSFs) {
     800             : 
     801           0 :   Int nmodels=PSFs.nelements();
     802           0 :   for (Int model=0; model < nmodels; ++model){
     803           0 :     makeApproxPSF(model, *(PSFs[model]));
     804             :     
     805             :   }
     806             : 
     807             : 
     808           0 : }
     809             : //----------------------------------------------------------------------
     810             : // Solve for a SkyModel
     811           0 : Bool SkyEquation::solveSkyModel() {
     812           0 :   return sm_->solve(*this);
     813             : }
     814             : 
     815             : // ***************************************************************************
     816             : // ********************  Start of private member functions *******************
     817             : // ***************************************************************************
     818             : 
     819             : // Initialize
     820          48 : void SkyEquation::initializeGet(const VisBuffer& vb, Int row, Int model,
     821             :                                 Bool incremental) {
     822             : 
     823          48 :   AlwaysAssert(ok(),AipsError);
     824          48 :   if(incremental) {
     825           0 :     applySkyJones(vb, row, sm_->deltaImage(model), sm_->cImage(model));
     826             :   }
     827             :   else {
     828          48 :     applySkyJones(vb, row, sm_->image(model), sm_->cImage(model));
     829             :   }
     830          48 :   ft_->initializeToVis(sm_->cImage(model),vb);
     831          48 : }
     832             : //
     833             : 
     834             : // Add the sky visibility for this coherence sample
     835         358 : VisBuffer& SkyEquation::get(VisBuffer& result, Int model,
     836             :                             Bool incremental,
     837             :                             MS::PredefinedColumns Type) {
     838             : 
     839         358 :   AlwaysAssert(ok(),AipsError);
     840         358 :   Int nRow=result.nRow();
     841             : 
     842             :   // we'll always return MODEL, but maybe expect existing data in another col 
     843             :   // yes this is a bit convoluted - probably should change whatever calls 
     844             :   // get to expect different columns.
     845         358 :   switch(Type) {
     846           0 :   case MS::MODEL_DATA:    
     847           0 :     result.modelVisCube(); 
     848           0 :     break;
     849         358 :   case MS::DATA:          
     850         358 :     result.visCube(); 
     851         358 :     result.setModelVisCube(result.visCube()); 
     852         358 :     break;
     853           0 :   case MS::CORRECTED_DATA:        
     854           0 :     result.correctedVisCube(); 
     855           0 :     result.setModelVisCube(result.correctedVisCube()); 
     856           0 :     break;
     857           0 :   default:
     858           0 :     throw (AipsError("Programmer made a wrong call"));
     859             :   }
     860             : 
     861             :   //result.modelVisCube(); // get the visibility so vb will have it
     862             :   //VisBufferAutoPtr vb (result);
     863             :   // We need msId and mscolumns from result in the vb passed to FT below.
     864             :   // I can't find a public method to copy that ms info over, so instead, 
     865             :   // save the datacube and add it back at the end of this method.
     866             :   VisBuffer *oldvb,*vb;
     867         358 :   vb = &result; // this will get replaced by FT->get
     868         358 :   oldvb = new VisBuffer(result);
     869         358 :   oldvb->setModelVisCube(result.modelVisCube());
     870             : 
     871         358 :   Bool FTChanged=changedFTMachine(* vb);
     872             : 
     873             :   // we might need to recompute the "sky" for every single row, but we
     874             :   // avoid this if possible.
     875         358 :   Bool internalChanges=false;  // Does this VB change inside itself?
     876         358 :   Bool firstOneChanges=false;  // Has this VB changed from the previous one?
     877         358 :   if(ft_->name()!="MosaicFT"){
     878         358 :     changedSkyJonesLogic(result, firstOneChanges, internalChanges);
     879             :   } 
     880         358 :   if(internalChanges) {
     881             :     // Yes there are changes within this buffer: go row by row.
     882             :     // This will automatically catch a change in the FTMachine so
     883             :     // we don't have to check for that.
     884           0 :     for (Int row=0; row<nRow; row++) {
     885           0 :       finalizeGet();
     886           0 :       initializeGet(result, row, model, incremental);
     887           0 :       ft_->get(* vb,row);
     888             :     }
     889             :   }
     890         358 :   else if (FTChanged||firstOneChanges) {
     891             :     // This buffer has changed wrt the previous buffer, but
     892             :     // this buffer has no changes within it. Again we don't need to
     893             :     // check for the FTMachine changing.
     894          30 :     finalizeGet();
     895          30 :     initializeGet(result, 0, model, incremental);
     896          30 :     ft_->get(* vb);
     897             :   }
     898             :   else {
     899         328 :     ft_->get(* vb);
     900             :   }
     901         358 :   result.modelVisCube()+=oldvb->modelVisCube();
     902         358 :   return result;
     903             : }
     904             : 
     905          48 : void SkyEquation::finalizeGet()
     906             : {
     907             :   // Do nothing
     908             :   // MFSkyEquation has something to do, we just
     909             :   // need to have "get()" calling finalizeGet()
     910          48 : };
     911             : 
     912             : 
     913             : // Add the sky visibility for this component
     914           0 : VisBuffer& SkyEquation::get(VisBuffer& result,
     915             :                             const SkyComponent& component)
     916             : {
     917             : 
     918           0 :   AlwaysAssert(sm_,AipsError);
     919           0 :   AlwaysAssert(cft_,AipsError);
     920             : 
     921           0 :   Int nRow=result.nRow();
     922             : 
     923           0 :   result.modelVisCube(); // get the visibility so vb will have it
     924           0 :   VisBufferAutoPtr vb (result);
     925           0 :   SkyComponent corruptedComponent = component.copy();
     926           0 :   if(vb->polFrame()==MSIter::Linear) {
     927           0 :     if(corruptedComponent.flux().pol()==ComponentType::STOKES) {
     928           0 :       corruptedComponent.flux().convertPol(ComponentType::LINEAR);
     929             :     }
     930             :   }
     931             :   else {
     932           0 :     if(corruptedComponent.flux().pol()==ComponentType::STOKES) {
     933           0 :       corruptedComponent.flux().convertPol(ComponentType::CIRCULAR);
     934             :     }
     935             :   }
     936             :   // we might need to recompute the "sky" for every single row, but
     937             :   // we avoid this, if possible
     938           0 :   Bool internalChanges=false; // Does this VB change inside itself
     939           0 :   Bool firstOneChanges=false; // Has this VB changed from the previous one?
     940           0 :   changedSkyJonesLogic(result,firstOneChanges,internalChanges);
     941           0 :   if (internalChanges) // yes, we have to go row by row
     942           0 :       for (Int row=0;row<nRow;++row) {
     943           0 :            SkyComponent tempComponent=corruptedComponent.copy();
     944           0 :            applySkyJones(tempComponent,result,row);
     945           0 :            cft_->get(* vb,tempComponent,row);
     946           0 :       }
     947             :   else { // we don't have a cache of corruptedComponent, therefore
     948             :          // firstOneChanges is equivalent to the default case
     949           0 :       applySkyJones(corruptedComponent, result, 0);
     950           0 :       cft_->get(* vb, corruptedComponent);
     951             :   }
     952           0 :   result.modelVisCube()+=vb->modelVisCube();
     953           0 :   return result;
     954           0 : }
     955             : 
     956             : 
     957             : 
     958             : // Add the sky visibility for this component
     959         236 : VisBuffer& SkyEquation::get(VisBuffer& result,
     960             :                             const ComponentList& compList)
     961             : //                          MS::PredefinedColumns Type) {
     962             :   {
     963             : 
     964         236 :   AlwaysAssert(sm_,AipsError);
     965         236 :   AlwaysAssert(cft_,AipsError);
     966             : 
     967         236 :   Int nRow=result.nRow();
     968             : 
     969         236 :   result.modelVisCube(); // get the visibility so vb will have it
     970             :   //VisBufferAutoPtr vb(result);
     971         236 :   VisBuffer vb(result); // method only called using writable VI so no ROVIA
     972             :   //Above state copy  is incomplete like msId is not copied...make sure to use
     973             :   //result when metadata is important.
     974         236 :   result.setModelVisCube(Complex(0.0,0.0));
     975             :     
     976             :   // CURRENTLY we do not have the applySkyJones code which
     977             :   // works on ComponentLists;  so we need to get out the
     978             :   // individual SkyComponents here
     979             :   
     980             :   // we might need to recompute the "sky" for every single row, but
     981             :   // we avoid this, if possible
     982         236 :   Bool internalChanges=false; // Does this VB change inside itself
     983         236 :   Bool firstOneChanges=false; // Has this VB changed from the previous one?
     984         236 :   changedSkyJonesLogic(result,firstOneChanges,internalChanges);
     985             : 
     986         236 :   uInt ncomponents=compList.nelements();
     987         633 :   for (uInt icomp=0;icomp<ncomponents;icomp++) {
     988         397 :     SkyComponent component=compList.component(icomp).copy();
     989         397 :     if(vb.polFrame()==MSIter::Linear) {
     990         397 :       if(component.flux().pol()==ComponentType::STOKES) {
     991         397 :         component.flux().convertPol(ComponentType::LINEAR);
     992             :       }
     993             :     }
     994             :     else {
     995           0 :       if(component.flux().pol()==ComponentType::STOKES) {
     996           0 :         component.flux().convertPol(ComponentType::CIRCULAR);
     997             :       }
     998             :     }
     999         397 :     if (internalChanges) // yes, we have to go row by row
    1000           0 :         for (Int row=0;row<nRow;++row) {
    1001           0 :              SkyComponent tempComponent=component.copy();
    1002           0 :              applySkyJones(tempComponent,result,row);
    1003           0 :              cft_->get(vb,tempComponent,row);
    1004           0 :         }
    1005             :     else { // we don't have a cache for component, therefore
    1006             :            // firstOneChanges is equivalent to the default case
    1007         397 :          applySkyJones(component, result, 0);
    1008         397 :          cft_->get(vb, component);
    1009             :     }
    1010         397 :     result.modelVisCube()+=vb.modelVisCube();
    1011         397 :   }
    1012             :   // Now add into the existing model visibility cube
    1013         236 :   return result;
    1014         236 : }
    1015             : 
    1016             : 
    1017             : // Corrupt a SkyComponent
    1018         397 : SkyComponent& SkyEquation::applySkyJones(SkyComponent& corruptedComponent,
    1019             :                                          const VisBuffer& vb,
    1020             :                                          Int row)
    1021             : {
    1022         397 :   if(!isPSFWork_p){
    1023             :     //The last of the bolean in the following line forces a full spectral corruption
    1024             :     // May be should do it on detection of fractional bandwidth 
    1025         397 :     if(ej_) ej_->apply(corruptedComponent,corruptedComponent,vb,row, True, True);
    1026         397 :     if(dj_) dj_->apply(corruptedComponent,corruptedComponent,vb,row);
    1027         397 :     if(tj_) tj_->apply(corruptedComponent,corruptedComponent,vb,row);
    1028         397 :     if(fj_) fj_->apply(corruptedComponent,corruptedComponent,vb,row);
    1029             :   }
    1030         397 :   return corruptedComponent;
    1031             : }
    1032             : 
    1033           0 : void SkyEquation::initializePut(const VisBuffer& vb, Int model) {
    1034           0 :   AlwaysAssert(ok(),AipsError);
    1035           0 :   ift_->initializeToSky(sm_->cImage(model),sm_->weight(model),vb);
    1036           0 :   assertSkyJones(vb, -1);
    1037           0 :   vb_p->assign(vb, false);
    1038           0 :   vb_p->updateCoordInfo();
    1039           0 : }
    1040             : 
    1041             : 
    1042           0 : void SkyEquation::put(const VisBuffer & vb, Int model, Bool dopsf, FTMachine::Type col) {
    1043             : 
    1044           0 :   AlwaysAssert(ok(),AipsError);
    1045             : 
    1046           0 :   Bool IFTChanged=changedIFTMachine(vb);
    1047             : 
    1048             :   // we might need to recompute the "sky" for every single row, but we
    1049             :   // avoid this if possible.
    1050             : 
    1051             :   
    1052           0 :   Int nRow=vb.nRow();
    1053           0 :   Bool internalChanges=false;  // Does this VB change inside itself?
    1054           0 :   Bool firstOneChanges=false;  // Has this VB changed from the previous one?
    1055           0 :   if(ft_->name() != "MosaicFT"){
    1056           0 :     changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
    1057             :   }
    1058           0 :   if(internalChanges) {
    1059             :     // Yes there are changes: go row by row. 
    1060           0 :     for (Int row=0; row<nRow; row++) {
    1061           0 :       if(IFTChanged||changedSkyJones(vb,row)) {
    1062             :         // Need to apply the SkyJones from the previous row
    1063             :         // and finish off before starting with this row
    1064           0 :         finalizePut(* vb_p, model);
    1065           0 :         initializePut(vb, model);
    1066             :       }
    1067           0 :       ift_->put(vb, row, dopsf, col);
    1068             :     }
    1069             :   }
    1070           0 :   else if (IFTChanged||firstOneChanges) {
    1071             : 
    1072           0 :     if(!isBeginingOfSkyJonesCache_p){
    1073           0 :       finalizePut(* vb_p, model);
    1074             :     }
    1075           0 :     initializePut(vb, model);
    1076           0 :     isBeginingOfSkyJonesCache_p=false;
    1077           0 :     ift_->put(vb, -1, dopsf, col);
    1078             :   }
    1079             :   else {
    1080           0 :     ift_->put(vb, -1, dopsf, col);
    1081             :   }
    1082             : 
    1083           0 :   isBeginingOfSkyJonesCache_p=false;
    1084           0 : }
    1085             : 
    1086             : 
    1087             : 
    1088             : 
    1089           0 : void SkyEquation::finalizePut(const VisBuffer& vb, Int model) {
    1090             : 
    1091             :   // Actually do the transform. Update weights as we do so.
    1092           0 :   ift_->finalizeToSky();
    1093             :   // 1. Now get the (unnormalized) image and add the 
    1094             :   // weight to the summed weights
    1095           0 :   Matrix<Float> delta;
    1096           0 :   sm_->cImage(model).copyData(ift_->getImage(delta, false));
    1097           0 :   sm_->weight(model)+=delta;
    1098             :   // 2. Apply the SkyJones and add to grad chisquared
    1099           0 :   applySkyJonesInv(vb, -1, sm_->cImage(model), sm_->work(model),
    1100           0 :                    sm_->gS(model));
    1101             : 
    1102             :   // 3. Apply the square of the SkyJones and add this to gradgrad chisquared
    1103           0 :   applySkyJonesSquare(vb, -1, sm_->weight(model), sm_->work(model),
    1104           0 :                       sm_->ggS(model));
    1105             : 
    1106             :   
    1107             :   // 4. Finally, we add the statistics
    1108           0 :   sm_->addStatistics(sumwt, chisq);
    1109           0 : }
    1110             : 
    1111             : 
    1112             : 
    1113             : 
    1114           0 : void SkyEquation::initializePutXFR(const VisBuffer& vb, Int model,
    1115             :                                    Int numXFR) {
    1116           0 :   AlwaysAssert(ok(),AipsError);
    1117           0 :   Matrix<Float> weight;
    1118           0 :   ift_->initializeToSky(sm_->XFR(model, numXFR), weight, vb);
    1119           0 :   assertSkyJones(vb, -1);
    1120           0 :   vb_p->assign(vb, false);
    1121           0 :   vb_p->updateCoordInfo();
    1122           0 : }
    1123             : 
    1124           0 : void SkyEquation::putXFR(const VisBuffer & vb, Int model, Int& numXFR) {
    1125             : 
    1126           0 :   AlwaysAssert(ok(),AipsError);
    1127             : 
    1128           0 :   Bool IFTChanged=changedIFTMachine(vb);
    1129             : 
    1130           0 :   Bool internalChanges=false;  // Does this VB change inside itself?
    1131           0 :   Bool firstOneChanges=false;  // Has this VB changed from the previous one?
    1132           0 :   changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
    1133           0 :   if(internalChanges) {
    1134             :     // Yes there are changes within this buffer: go row by row. 
    1135           0 :     Int nRow=vb.nRow();
    1136           0 :     for (Int row=0; row<nRow; row++) {
    1137           0 :       if(IFTChanged||changedSkyJones(vb,row)) {
    1138             :         // Need to apply the SkyJones from the previous row
    1139             :         // and finish off before starting with this row
    1140           0 :         finalizePutXFR(* vb_p, model, numXFR);  //  also, this needs to know about
    1141             :                                               //  the vb row number 
    1142           0 :         numXFR++; 
    1143           0 :         initializePutXFR(vb, model, numXFR);
    1144             :       }
    1145           0 :       ift_->put(vb, row, true);
    1146             :     }
    1147             :   }
    1148           0 :   else if (IFTChanged||firstOneChanges) {
    1149           0 :     finalizePutXFR(* vb_p, model, numXFR);
    1150           0 :     numXFR++; 
    1151           0 :     initializePutXFR(vb, model, numXFR);
    1152           0 :     ift_->put(vb, -1, true);
    1153             :   } else {
    1154           0 :     ift_->put(vb, -1, true);
    1155             :   }
    1156           0 : }
    1157             : 
    1158           0 : void SkyEquation::finalizePutXFR(const VisBuffer& vb, Int model, Int numXFR) 
    1159             : {
    1160             :   // Actually do the transform. FFT back to the visibility plane
    1161           0 :   ift_->finalizeToSky();
    1162           0 :   Matrix<Float> weights;
    1163           0 :   sm_->XFR(model, numXFR).copyData(ift_->getImage(weights, false));
    1164           0 :   LatticeFFT::cfft2d(sm_->XFR(model, numXFR));
    1165           0 :   assertSkyJones(vb, -1);
    1166             :   //  TempImage<Complex> *tip = ( TempImage<Complex> *) ( &(sm_->XFR(model, numXFR)) );
    1167             :   //  tip->tempClose();
    1168           0 : }
    1169             : 
    1170             : // Here we do the whole thing: apply SkyJones, FFT, cross-multiply
    1171             : // by the XFR, inverseFFT and then apply SkyJones again
    1172           0 : void SkyEquation::initializePutConvolve(const VisBuffer& vb, Int model,
    1173             :                                         Int numXFR) 
    1174             : {
    1175           0 :   LogIO os(LogOrigin("SkyEquation", "initializePutConvolve"));
    1176           0 :   AlwaysAssert(ok(),AipsError);
    1177           0 :   AlwaysAssert(model>-1, AipsError);
    1178           0 :   AlwaysAssert(numXFR>-1, AipsError);
    1179           0 :   assertSkyJones(vb, -1);
    1180           0 :   vb_p->assign(vb, false);
    1181           0 :   vb_p->updateCoordInfo();
    1182           0 : }
    1183             : 
    1184             : // Here we step through the visbuffer and do the convolution
    1185             : // if something changes
    1186           0 : void SkyEquation::putConvolve(const VisBuffer & vb, Int model, Int& numXFR) {
    1187             : 
    1188           0 :   AlwaysAssert(ok(),AipsError);
    1189             : 
    1190           0 :   Int nRow=vb.nRow();
    1191           0 :   Bool internalChanges=false;  // Does this VB change inside itself?
    1192           0 :   Bool firstOneChanges=false;  // Has this VB changed from the previous one?
    1193           0 :   changedSkyJonesLogic(vb, firstOneChanges, internalChanges);
    1194           0 :   if(internalChanges) {
    1195             :     // Yes there are changes within this buffer: go row by row. 
    1196           0 :     for (Int row=0; row<nRow; row++) {
    1197           0 :       if(changedSkyJones(vb,row)) {
    1198             :         // Need to apply the SkyJones from the previous row
    1199             :         // and finish off before starting with this row
    1200           0 :         finalizePutConvolve(* vb_p, model, numXFR);
    1201           0 :         numXFR++;
    1202           0 :         initializePutConvolve(vb, model, numXFR);
    1203             :       }
    1204             :     }
    1205             :   }
    1206           0 :   else if (firstOneChanges) {
    1207           0 :     finalizePutConvolve(* vb_p, model, numXFR);
    1208           0 :     numXFR++;
    1209           0 :     initializePutConvolve(vb, model, numXFR);
    1210             :   }
    1211           0 : };
    1212             : 
    1213             : // Here we do the convolution and transform back
    1214           0 : void SkyEquation::finalizePutConvolve(const VisBuffer& vb, Int model,
    1215             :                                       Int numXFR) 
    1216             : {
    1217           0 :   LogIO os(LogOrigin("SkyEquation", "finalizePutConvolve"));
    1218             : 
    1219           0 :   applySkyJones(vb, -1, sm_->deltaImage(model), sm_->cImage(model));
    1220           0 :   LatticeFFT::cfft2d(sm_->cImage(model));
    1221           0 :   LatticeExpr<Complex> latticeExpr(conj(sm_->XFR(model, numXFR))*sm_->cImage(model));
    1222           0 :   sm_->cImage(model).copyData(latticeExpr);
    1223           0 :   LatticeFFT::cfft2d(sm_->cImage(model), false);
    1224           0 :   applySkyJonesInv(vb, -1, sm_->cImage(model), sm_->work(model),
    1225           0 :                    sm_->gS(model));
    1226           0 : }
    1227             : 
    1228         857 : void SkyEquation::changedSkyJonesLogic(const VisBuffer& vb, 
    1229             :                                        Bool& firstOneChanges,
    1230             :                                        Bool& internalChanges)
    1231             : {
    1232         857 :   if(changedSkyJones(vb,0)) {
    1233          67 :     firstOneChanges=true;
    1234             :   }
    1235         857 :   Int lastrow = -1;
    1236         857 :   if(changedSkyJonesBuffer(vb, 0, lastrow)) {
    1237           0 :     internalChanges=true;
    1238             :   } 
    1239        1714 :   return;
    1240             : };
    1241             : 
    1242             : 
    1243             : // Has the total SkyJones changed since the last application of the SkyJones?
    1244         857 : Bool SkyEquation::changedSkyJones(const VisBuffer& vb, Int row) {
    1245         857 :   if(ej_) if(ej_->changed(vb,row)) return true; // Electric field pattern
    1246         790 :   if(dj_) if(dj_->changed(vb,row)) return true; // Polarization field pattern
    1247         790 :   if(tj_) if(tj_->changed(vb,row)) return true; // Atmospheric gain
    1248         790 :   if(fj_) if(fj_->changed(vb,row)) return true; // Faraday rotation
    1249         790 :   return false;
    1250             : };
    1251             : 
    1252             : 
    1253             : // Has the FT Machine changed since the last application ?
    1254         358 : Bool SkyEquation::changedFTMachine(const VisBuffer& vb) {
    1255         358 :   return ft_->changed(vb);
    1256             : };
    1257             : 
    1258             : // Has the Inverse FT Machine changed since the last application ?
    1259           0 : Bool SkyEquation::changedIFTMachine(const VisBuffer& vb) {
    1260           0 :   return ift_->changed(vb);
    1261             : };
    1262             : 
    1263             : 
    1264             : // Does the SkyJones change in this buffer starting at row1?
    1265         857 : Bool SkyEquation::changedSkyJonesBuffer
    1266             : (const VisBuffer& vb, Int row1, Int& row2) {
    1267         857 :   Int row2temp = 0;
    1268         857 :   row2 = vb.nRow() - 1;
    1269         857 :   Bool didChange = false;
    1270         857 :   if(ej_) {  // Electric field pattern
    1271         276 :     if(ej_->changedBuffer(vb,row1, row2temp)) {
    1272           0 :       didChange = true;
    1273           0 :       row2 = min (row2, row2temp);
    1274             :     }
    1275             :   }
    1276         857 :   if(dj_) {  // Polarization field pattern
    1277           0 :     if(dj_->changedBuffer(vb,row1, row2temp)) {
    1278           0 :       didChange = true;
    1279           0 :       row2 = min (row2, row2temp);
    1280             :     }
    1281             :   }
    1282         857 :   if(tj_) {  // Atmospheric gain
    1283           0 :     if(tj_->changedBuffer(vb,row1, row2temp)) {
    1284           0 :       didChange = true;
    1285           0 :       row2 = min (row2, row2temp);
    1286             :     }
    1287             :   }
    1288         857 :   if(fj_) {  // Faraday rotation
    1289           0 :     if(fj_->changedBuffer(vb,row1, row2temp)) {
    1290           0 :       didChange = true;
    1291           0 :       row2 = min (row2, row2temp);
    1292             :     }
    1293             :   }
    1294         857 :   return didChange;
    1295             : };
    1296             : 
    1297             : 
    1298           0 : void SkyEquation::setPhaseCenterTime(const Double time){
    1299             : 
    1300           0 :   if(cft_)
    1301           0 :     cft_->setPhaseCenterTime(time);
    1302           0 :   if(ft_)
    1303           0 :     ft_->setPhaseCenterTime(time);
    1304           0 :   if(ift_)
    1305           0 :     ift_->setPhaseCenterTime(time);
    1306           0 : }
    1307           0 : Double SkyEquation::getPhaseCenterTime(){
    1308           0 :   if(cft_)
    1309           0 :     return cft_->getPhaseCenterTime();
    1310           0 :   if(ft_)
    1311           0 :     return ft_->getPhaseCenterTime();
    1312           0 :   return -1.0;
    1313             : }
    1314             : 
    1315             : // Reset all of the SkyJones to initial state
    1316          39 : void SkyEquation::resetSkyJones() 
    1317             : {
    1318          39 :   if(ej_) ej_->reset(); // Electric field pattern
    1319          39 :   if(dj_) dj_->reset(); // Polarization field pattern
    1320          39 :   if(tj_) tj_->reset(); // Atmospheric gain
    1321          39 :   if(fj_) fj_->reset(); // Faraday rotation
    1322             : 
    1323          39 :   isBeginingOfSkyJonesCache_p=true;
    1324             :   
    1325          39 : };
    1326             : 
    1327             : // Assure that we've taken care of the SkyJones terms
    1328             : // (needed for e.g. putXFR)
    1329          14 : void SkyEquation::assertSkyJones(const VisBuffer& vb, Int row) {
    1330          14 :   if(ej_) ej_->assure(vb,row); // Electric field pattern
    1331          14 :   if(dj_) dj_->assure(vb,row); // Polarization field pattern
    1332          14 :   if(tj_) tj_->assure(vb,row); // Atmospheric gain
    1333          14 :   if(fj_) fj_->assure(vb,row); // Faraday rotation
    1334          14 : };
    1335             : 
    1336          48 : ImageInterface<Complex>& SkyEquation::applySkyJones(const VisBuffer& vb,
    1337             :                                                     Int row,
    1338             :                                                     ImageInterface<Float>& in,
    1339             :                                                     ImageInterface<Complex>& out) {
    1340             : 
    1341             :   //Pol axis need not be same
    1342          48 :   AlwaysAssert(in.shape()[0]==out.shape()[0], AipsError);
    1343          48 :   AlwaysAssert(in.shape()[1]==out.shape()[1], AipsError);
    1344          48 :   AlwaysAssert(in.shape()[3]==out.shape()[3], AipsError);
    1345             :   // Convert from Stokes to Complex
    1346          48 :   StokesImageUtil::From(out, in);
    1347             : 
    1348             :   // Now apply the SkyJones as needed
    1349          48 :   if(!isPSFWork_p  && (!(ift_->name().contains("MosaicFT")))){
    1350          48 :     if(ej_) ej_->apply(out,out,vb,row,true);
    1351          48 :     if(dj_) dj_->apply(out,out,vb,row,true);
    1352          48 :     if(tj_) tj_->apply(out,out,vb,row,true);
    1353          48 :     if(fj_) fj_->apply(out,out,vb,row,true);
    1354             :   }
    1355          48 :   return out;
    1356             : };
    1357             : 
    1358             : 
    1359             : // Calculate gradChisq. In the SkyModel, this is used to update
    1360             : // the estimated image.
    1361          14 : void SkyEquation::applySkyJonesInv(const VisBuffer& vb, Int row,
    1362             :                                    ImageInterface<Complex>& in,
    1363             :                                    ImageInterface<Float>& work,
    1364             :                                    ImageInterface<Float>& gS) {
    1365             : 
    1366          14 :   AlwaysAssert(in.shape()[0]==work.shape()[0], AipsError);
    1367          14 :   AlwaysAssert(in.shape()[1]==work.shape()[1], AipsError);
    1368          14 :   AlwaysAssert(in.shape()[3]==work.shape()[3], AipsError);
    1369          14 :   AlwaysAssert(gS.shape()==work.shape(), AipsError);
    1370             : 
    1371             :   // Apply the various SkyJones to the current image
    1372             :   // remembering to apply the Jones in the backward
    1373             :   // direction
    1374          14 :   if(!isPSFWork_p && (ift_->name() != "MosaicFT")){
    1375             : 
    1376           0 :     if(ej_) ej_->apply(in,in,vb,row,false);
    1377           0 :     if(dj_) dj_->apply(in,in,vb,row,false);
    1378           0 :     if(tj_) tj_->apply(in,in,vb,row,false);
    1379           0 :     if(fj_) fj_->apply(in,in,vb,row,false);
    1380             :   }
    1381             :   // Convert to IQUV format
    1382          14 :   if(isPSFWork_p) 
    1383             :     { 
    1384             :        // For the PSF, choose only those stokes planes that have a valid PSF
    1385          14 :        StokesImageUtil::ToStokesPSF(work,in);
    1386             :     }
    1387             :   else 
    1388             :     {
    1389           0 :        StokesImageUtil::To(work,in);
    1390             :     }
    1391             : 
    1392             :   // Now add to the existing gradChisq image
    1393          28 :   LatticeExpr<Float> le(gS+work);
    1394          14 :   gS.copyData(le);
    1395             : 
    1396          14 : };
    1397             : 
    1398             : 
    1399             : 
    1400             : // Calculate gradgradChisq. In the SkyModel, this is
    1401             : // used to update the estimated image.
    1402          14 : void SkyEquation::applySkyJonesSquare(const VisBuffer& vb, Int row,
    1403             :                                       Matrix<Float>& weights,
    1404             :                                       ImageInterface<Float>& work,
    1405             :                                       ImageInterface<Float>& ggS) {
    1406             : 
    1407          14 :   AlwaysAssert(work.shape()==ggS.shape(), AipsError);
    1408             : 
    1409             :   // First fill the work image with the appropriate value
    1410             :   // of the weight.
    1411          14 :   ift_->getWeightImage(work, weights);
    1412             :    // Apply SkyJones as needed
    1413          14 :   if((ft_->name() != "MosaicFT") ){
    1414          14 :     if(ej_) ej_->applySquare(work,work,vb,row);
    1415          14 :     if(dj_) dj_->applySquare(work,work,vb,row);
    1416          14 :     if(tj_) tj_->applySquare(work,work,vb,row);
    1417          14 :     if(fj_) fj_->applySquare(work,work,vb,row);
    1418             :   }
    1419             :   // Now add to the existing gradgradChisq image
    1420          14 :   if((ft_->name() != "MosaicFT")){
    1421          28 :     LatticeExpr<Float> le(ggS+work);
    1422          14 :     ggS.copyData(le);
    1423          14 :   }
    1424             :   else{
    1425           0 :     ggS.copyData(work);
    1426             :   }
    1427             :  
    1428          14 : };
    1429             : 
    1430             : 
    1431         715 : Bool SkyEquation::ok() {
    1432             : 
    1433         715 :   AlwaysAssert(sm_,AipsError);
    1434             :   //AlwaysAssert(vs_,AipsError);
    1435         715 :   AlwaysAssert(ft_,AipsError);
    1436         715 :   AlwaysAssert(ift_,AipsError);
    1437         715 :   AlwaysAssert(rvi_p, AipsError);
    1438             : 
    1439         715 :   return(true);
    1440             : }
    1441             : 
    1442             : 
    1443          18 : void SkyEquation::scaleImage(Int model)
    1444             : {
    1445             :   
    1446          18 :   if (sm_->doFluxScale(model)){  
    1447             : 
    1448           0 :     LatticeExpr<Float> latticeExpr( iif(sm_->fluxScale(model) <= (0.0), 0.0, (sm_->image(model))/(sm_->fluxScale(model))) );
    1449           0 :     sm_->image(model).copyData(latticeExpr);
    1450           0 :     sm_->fluxScale(model).clearCache();
    1451           0 :     sm_->image(model).clearCache();
    1452           0 :   }
    1453          18 : };
    1454             : 
    1455          18 : void SkyEquation::unScaleImage(Int model)
    1456             : {
    1457             : 
    1458          18 :   if ( sm_->doFluxScale(model)){
    1459             : 
    1460           0 :     LatticeExpr<Float> latticeExpr( sm_->image(model) * (sm_->fluxScale(model)) );
    1461           0 :     sm_->image(model).copyData(latticeExpr);
    1462           0 :     sm_->fluxScale(model).clearCache();
    1463           0 :     sm_->image(model).clearCache();
    1464           0 :   }
    1465          18 : };
    1466             : 
    1467          18 : void SkyEquation::scaleImage(Int model, Bool incremental)
    1468             : {
    1469          18 :   if (incremental) {
    1470           0 :     scaleDeltaImage(model);
    1471             :   } else {
    1472          18 :     scaleImage(model);
    1473             :   }
    1474          18 : };
    1475             : 
    1476          18 : void SkyEquation::unScaleImage(Int model, Bool incremental)
    1477             : {
    1478          18 :   if (incremental) {
    1479           0 :     unScaleDeltaImage(model);
    1480             :   } else {
    1481          18 :     unScaleImage(model);
    1482             :   }
    1483          18 : };
    1484             : 
    1485           0 : void SkyEquation::scaleDeltaImage(Int model)
    1486             : {
    1487           0 :   if ((sm_->doFluxScale(model))){
    1488           0 :     sm_->deltaImage(model).copyData( (LatticeExpr<Float>)
    1489           0 :                                      (iif(sm_->fluxScale(model) <= (0.0), 0.0,
    1490           0 :                                           ((sm_->deltaImage(model))/(sm_->fluxScale(model))) )) );
    1491           0 :     sm_->fluxScale(model).clearCache();
    1492           0 :     sm_->deltaImage(model).clearCache();
    1493             :   }
    1494             :   
    1495           0 : };
    1496             : 
    1497           0 : void SkyEquation::getCoverageImage(Int model, ImageInterface<Float>& im){
    1498           0 :   if ((sm_->doFluxScale(model))){
    1499           0 :     ift_->getFluxImage(im);
    1500             :   }
    1501             : 
    1502           0 : }
    1503             : 
    1504             : 
    1505           0 : void SkyEquation::unScaleDeltaImage(Int model)
    1506             : {
    1507           0 :   if ( (sm_->doFluxScale(model))){
    1508           0 :     LatticeExpr<Float> latticeExpr( sm_->deltaImage(model) * (sm_->fluxScale(model)) );
    1509           0 :     sm_->deltaImage(model).copyData(latticeExpr);
    1510           0 :     sm_->fluxScale(model).clearCache();
    1511           0 :     sm_->deltaImage(model).clearCache();
    1512           0 :   } 
    1513           0 : };
    1514             : 
    1515           0 : void SkyEquation::fixImageScale()
    1516             : {
    1517           0 :   LogIO os(LogOrigin("SkyEquation", "fixImageScale"));
    1518             : 
    1519             :   // make a minimum value to ggS
    1520             :   // This has the same effect as Sault Weighting, but 
    1521             :   // is implemented somewhat differently.
    1522             :   // We also keep the fluxScale(mod) images around to
    1523             :   // undo the weighting.
    1524             :   
    1525           0 :   if(ej_ || (ft_->name() == "MosaicFT") ) {
    1526           0 :     Float ggSMax=0.0;
    1527           0 :     for (Int model=0;model<sm_->numberOfModels();model++) {
    1528             :     
    1529           0 :       LatticeExprNode LEN = max( sm_->ggS(model) );
    1530           0 :       ggSMax =  max(ggSMax,LEN.getFloat());
    1531           0 :     }
    1532             : 
    1533           0 :     ggSMax_p=ggSMax;
    1534             :     Float ggSMin1;
    1535             :     Float ggSMin2;
    1536             :     
    1537           0 :     ggSMin1 = ggSMax * constPB_p * constPB_p;
    1538           0 :     ggSMin2 = ggSMax * minPB_p * minPB_p;
    1539             :     
    1540             : 
    1541             :     /*Don't print this for now
    1542             :     if (scaleType_p == "SAULT") {
    1543             :         os << "Using SAULT image plane weighting" << LogIO::POST;
    1544             :     }
    1545             :     else {
    1546             :         os << "Using No image plane weighting" << LogIO::POST;
    1547             :     }
    1548             :     */
    1549             :         
    1550           0 :     for (Int model=0;model<sm_->numberOfModels();model++) {
    1551           0 :       sm_->fluxScale(model).removeRegion ("mask0", RegionHandler::Any, false);
    1552           0 :       if ((ft_->name()!="MosaicFT")) {
    1553           0 :         if(scaleType_p=="SAULT"){
    1554             :           
    1555             :           // Adjust flux scale to account for ggS being truncated at ggSMin1
    1556             :           // Below ggSMin2, set flux scale to 0.0
    1557             :           // FluxScale * image => true brightness distribution, but
    1558             :           // noise increases at edge.
    1559             :           // if ggS < ggSMin2, set to Zero;
    1560             :           // if ggS > ggSMin2 && < ggSMin1, set to ggSMin1/ggS
    1561             :           // if ggS > ggSMin1, set to 1.0
    1562           0 :           sm_->fluxScale(model).copyData( (LatticeExpr<Float>) 
    1563           0 :                                           (iif(sm_->ggS(model) < (ggSMin2), 0.0,
    1564           0 :                                                sqrt((sm_->ggS(model))/ggSMin1) )) );
    1565           0 :           sm_->fluxScale(model).copyData( (LatticeExpr<Float>) 
    1566           0 :                                           (iif(sm_->ggS(model) > (ggSMin1), 1.0,
    1567           0 :                                                (sm_->fluxScale(model)) )) );
    1568             :           // truncate ggS at ggSMin1
    1569           0 :           sm_->ggS(model).copyData( (LatticeExpr<Float>) 
    1570           0 :                                     (iif(sm_->ggS(model) < (ggSMin1), ggSMin1*(sm_->fluxScale(model)), 
    1571           0 :                                          sm_->ggS(model)) )
    1572             :                                     );
    1573             :         }
    1574             : 
    1575             :         else{
    1576             : 
    1577           0 :           sm_->fluxScale(model).copyData( (LatticeExpr<Float>) 
    1578           0 :                                           (iif(sm_->ggS(model) < (ggSMin2), 0.0,
    1579           0 :                                                sqrt((sm_->ggS(model))/ggSMax) )) );
    1580           0 :           sm_->ggS(model).copyData( (LatticeExpr<Float>) 
    1581           0 :                                           (iif(sm_->ggS(model) < (ggSMin2), 0.0,
    1582           0 :                                                sqrt((sm_->ggS(model))*ggSMax) )) );
    1583             : 
    1584             :         }
    1585             : 
    1586             :       } else {
    1587             :         /*
    1588             :         if(ft_->name() != "MosaicFT"){
    1589             :           sm_->fluxScale(model).copyData( (LatticeExpr<Float>) 1.0 );
    1590             :           sm_->ggS(model).copyData( (LatticeExpr<Float>) 
    1591             :                                     (iif(sm_->ggS(model) < (ggSMin2), 0.0, 
    1592             :                                          sm_->ggS(model)) ));
    1593             :          
    1594             : 
    1595             :         }
    1596             :         else{
    1597             : 
    1598             :         */
    1599             :          
    1600             :         
    1601           0 :           Int nXX=sm_->ggS(model).shape()(0);
    1602           0 :           Int nYY=sm_->ggS(model).shape()(1);
    1603           0 :           Int npola= sm_->ggS(model).shape()(2);
    1604           0 :           Int nchana= sm_->ggS(model).shape()(3);
    1605           0 :           IPosition blc(4,nXX, nYY, npola, nchana);
    1606           0 :           IPosition trc(4, nXX, nYY, npola, nchana);
    1607           0 :           blc(0)=0; blc(1)=0; trc(0)=nXX-1; trc(1)=nYY-1; 
    1608             : 
    1609             : 
    1610             :           //Those damn weights per plane can be wildly different so 
    1611             :           //deal with it properly here
    1612           0 :           for (Int j=0; j < npola; ++j){
    1613           0 :             for (Int k=0; k < nchana ; ++k){
    1614             :               
    1615           0 :               blc(2)=j; trc(2)=j;
    1616           0 :               blc(3)=k; trc(3)=k;
    1617           0 :               Slicer sl(blc, trc, Slicer::endIsLast);
    1618           0 :               SubImage<Float> fscalesub(sm_->fluxScale(model), sl, true);
    1619           0 :               SubImage<Float> ggSSub(sm_->ggS(model), sl, true);
    1620             :               Float planeMax;
    1621           0 :               LatticeExprNode LEN = max( ggSSub );
    1622           0 :               planeMax =  LEN.getFloat();
    1623           0 :               if(planeMax !=0){
    1624           0 :                 fscalesub.copyData( (LatticeExpr<Float>) 
    1625           0 :                                     (iif(ggSSub < (ggSMin2), 
    1626           0 :                                          0.0, (ggSSub/planeMax))));
    1627           0 :                 ggSSub.copyData( (LatticeExpr<Float>) 
    1628           0 :                                  (iif(ggSSub < (ggSMin2), 0.0, 
    1629             :                                       planeMax) ));
    1630             :         
    1631             :         
    1632             : 
    1633             :               }
    1634           0 :             }
    1635             : 
    1636             :           }
    1637             :         
    1638             :           /*
    1639             :             ft_->getFluxImage(sm_->fluxScale(model));
    1640             :         
    1641             :             sm_->ggS(model).copyData( (LatticeExpr<Float>) 
    1642             :             (iif(sm_->ggS(model) < (ggSMin2), 0.0,
    1643             :                                                (sm_->ggS(model)) )) );
    1644             :           */
    1645             :           //}   
    1646           0 :       }
    1647             :     
    1648             :       //because for usual ft machines a applySJoneInv is done on the gS
    1649             :       //in the finalizeput stage...need to understand if its necessary
    1650             :       /*need to understand that square business
    1651             :       if( (ft_->name() != "MosaicFT") && (!isPSFWork_p)){
    1652             :         sm_->gS(model).copyData( (LatticeExpr<Float>) 
    1653             :                                  (iif(sm_->fluxScale(model) > 0.0, 
    1654             :                                       ((sm_->gS(model))/(sm_->fluxScale(model))), 0.0 )) );
    1655             : 
    1656             : 
    1657             :       }
    1658             :       */
    1659             :       ///
    1660           0 :       sm_->ggS(model).clearCache();
    1661           0 :       sm_->fluxScale(model).clearCache();
    1662             :     }
    1663             : 
    1664             :   }
    1665           0 : }
    1666             : 
    1667          43 : void SkyEquation::checkVisIterNumRows(ROVisibilityIterator& vi){
    1668             : 
    1669          43 :   VisBuffer * vb = vi.getVisBuffer();
    1670          43 :   VisBufferAutoPtr vbap;
    1671          43 :   if (vb == NULL){
    1672          36 :       VisBufferAutoPtr tmp (vi);
    1673          36 :       vbap = tmp;
    1674          36 :       vb = vbap.get();
    1675          36 :   }
    1676             : 
    1677          43 :   vi.originChunks();
    1678          43 :   vi.origin();
    1679          43 :   Int nAnt=vb->numberAnt();
    1680          43 :   if(nAnt >1){
    1681          35 :     if (vb->nRow() < (nAnt*(nAnt-1)/4)){
    1682           0 :       vi.setRowBlocking( nAnt*(nAnt-1)/2+nAnt);
    1683           0 :       vi.originChunks();
    1684           0 :       vi.origin();
    1685             :     }
    1686             :   }
    1687          43 : }
    1688             : 
    1689           0 : String SkyEquation::associatedMSName(){
    1690           0 :   return String("");
    1691             : };
    1692             : 
    1693           0 : void SkyEquation::lock(){
    1694             : 
    1695             :   //Do nothing for now
    1696             : 
    1697           0 : }
    1698             : 
    1699           0 : void SkyEquation::unlock(){
    1700             :   // Do nothing for now
    1701             : 
    1702           0 : }
    1703             : 
    1704             : } //# NAMESPACE CASA - END
    1705             : 

Generated by: LCOV version 1.16