LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - Deconvolver.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 0 1405 0.0 %
Date: 2023-11-02 14:27:30 Functions: 0 48 0.0 %

          Line data    Source code
       1             : //# DOdeconvolver.cc: this implements the deconvolver DO 
       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: aips2-request@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //#
      27             : //# $Id: DOdeconvolver.cc,v 19.16 2005/12/06 20:18:50 wyoung Exp $
      28             : 
      29             : #include <casacore/casa/Arrays/Matrix.h>
      30             : #include <casacore/casa/Arrays/ArrayMath.h>
      31             : 
      32             : #include <casacore/casa/Logging.h>
      33             : #include <casacore/casa/Logging/LogIO.h>
      34             : #include <casacore/casa/OS/File.h>
      35             : #include <casacore/casa/Containers/Record.h>
      36             : 
      37             : #include <casacore/tables/TaQL/TableParse.h>
      38             : #include <casacore/tables/Tables/TableRecord.h>
      39             : #include <casacore/tables/Tables/TableDesc.h>
      40             : #include <casacore/tables/Tables/TableLock.h>
      41             : #include <casacore/tables/TaQL/ExprNode.h>
      42             : 
      43             : #include <casacore/casa/BasicSL/String.h>
      44             : #include <casacore/casa/Utilities/Assert.h>
      45             : #include <casacore/casa/Utilities/Fallible.h>
      46             : 
      47             : #include <casacore/casa/BasicSL/Constants.h>
      48             : 
      49             : #include <casacore/casa/Logging/LogSink.h>
      50             : #include <casacore/casa/Logging/LogMessage.h>
      51             : 
      52             : #include <casacore/casa/Arrays/ArrayMath.h>
      53             : 
      54             : #include <casacore/measures/Measures/Stokes.h>
      55             : #include <casacore/casa/Quanta/UnitMap.h>
      56             : #include <casacore/casa/Quanta/UnitVal.h>
      57             : #include <casacore/casa/Quanta/MVAngle.h>
      58             : #include <components/ComponentModels/ComponentList.h>
      59             : #include <components/ComponentModels/GaussianShape.h>
      60             : #include <casacore/measures/Measures/MDirection.h>
      61             : #include <casacore/measures/Measures/MPosition.h>
      62             : #include <casacore/casa/Quanta/MVEpoch.h>
      63             : #include <casacore/measures/Measures/MEpoch.h>
      64             : 
      65             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      66             : #include <casacore/lattices/LEL/LatticeExpr.h> 
      67             : #include <casacore/lattices/LatticeMath/LatticeFFT.h> 
      68             : #include <casacore/lattices/LatticeMath/LatticeCleaner.h> 
      69             : #include <casacore/lattices/LatticeMath/LatticeCleanProgress.h> 
      70             : #include <casacore/lattices/LatticeMath/LatticeConvolver.h> 
      71             : #include <casacore/lattices/Lattices/TiledLineStepper.h> 
      72             : #include <casacore/lattices/Lattices/LatticeStepper.h> 
      73             : #include <casacore/lattices/Lattices/LatticeNavigator.h> 
      74             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      75             : #include <casacore/lattices/Lattices/SubLattice.h>
      76             : #include <casacore/lattices/LRegions/LCBox.h>
      77             : #include <casacore/lattices/LRegions/LCSlicer.h>
      78             : 
      79             : #include <imageanalysis/ImageAnalysis/ComponentImager.h>
      80             : #include <casacore/images/Images/TempImage.h>
      81             : #include <casacore/images/Images/PagedImage.h>
      82             : #include <casacore/images/Images/ImageSummary.h>
      83             : #include <casacore/images/Images/SubImage.h>
      84             : #include <casacore/images/Regions/ImageRegion.h>
      85             : #include <casacore/images/Images/ImageRegrid.h>
      86             : #include <casacore/images/Images/ImageInfo.h>
      87             : 
      88             : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
      89             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      90             : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
      91             : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
      92             : #include <casacore/coordinates/Coordinates/Projection.h>
      93             : 
      94             : #include <synthesis/MeasurementComponents/ClarkCleanImageSkyModel.h>
      95             : #include <synthesis/MeasurementEquations/CEMemProgress.h>
      96             : #include <synthesis/MeasurementEquations/CEMemModel.h>
      97             : #include <synthesis/MeasurementEquations/ClarkCleanLatModel.h>
      98             : #include <synthesis/MeasurementEquations/ClarkCleanProgress.h>
      99             : #include <synthesis/DataSampling/ImageDataSampling.h>
     100             : #include <synthesis/MeasurementEquations/LatConvEquation.h>
     101             : #include <synthesis/MeasurementEquations/IPLatConvEquation.h>
     102             : #include <synthesis/MeasurementEquations/Deconvolver.h>
     103             : #include <synthesis/MeasurementEquations/Imager.h>
     104             : #include <synthesis/MeasurementEquations/ImageMSCleaner.h>
     105             : #include <synthesis/MeasurementEquations/ImageNACleaner.h>
     106             : 
     107             : 
     108             : #include <sstream>
     109             : 
     110             : #include <casacore/casa/namespace.h>
     111             : // Implementation comment:
     112             : // There are two different philosophies active here:
     113             : // ClarkCleanLatModel and CEMemModel are evolutionarily related and
     114             : // "solve" a LinearEquation (in this case, a LatticeConvolutionEqaution).
     115             : // The LatticeCleaner, which performs Hogbom and MultiScale Cleans,
     116             : // has no knowledge of the LatticeConvolutionEqaution (LatConvEquation), 
     117             : // but carries the PSF and DIRTY around inside itself.
     118             : using namespace casacore;
     119             : namespace casa { //# NAMESPACE CASA - BEGIN
     120             : 
     121           0 : Deconvolver::Deconvolver() 
     122             :   : dirty_p(0),
     123             :     psf_p(0), 
     124             :     convolver_p(0), 
     125             :     cleaner_p( ), 
     126             :     mt_nterms_p(-1), 
     127             :     mt_cleaner_p(), 
     128           0 :     mt_valid_p(false)
     129             : {
     130             : 
     131           0 :   defaults();
     132           0 : };
     133             : 
     134           0 : void Deconvolver::defaults() 
     135             : {
     136           0 :   mode_p="none";
     137           0 :   beamValid_p=false;
     138           0 :   scalesValid_p=false;
     139           0 :   beam_p = GaussianBeam();
     140           0 :   residEqn_p = 0;
     141           0 :   latConvEqn_p = 0;
     142           0 :   cleaner_p = 0;
     143           0 :   dirtyName_p = "";
     144           0 :   psfName_p = "";
     145           0 :   nx_p=0; ny_p=0; npol_p=0; nchan_p=0;
     146           0 :   fullPlane_p=false;
     147           0 : }
     148             : 
     149           0 : Deconvolver::Deconvolver(const String& dirty, const String& psf)
     150             :   : dirty_p(0), psf_p(0), convolver_p(0), cleaner_p( ), naCleaner_p(nullptr),
     151           0 :      mt_nterms_p(-1), mt_cleaner_p(), mt_valid_p(false)
     152             : {
     153           0 :   LogIO os(LogOrigin("Deconvolver", "Deconvolver(String& dirty, Strong& psf)", WHERE));
     154           0 :   defaults();
     155           0 :   open(dirty, psf);
     156           0 : }
     157             : 
     158           0 : Deconvolver::Deconvolver(const Deconvolver &other)
     159             :   : dirty_p(0), psf_p(0), convolver_p(0), cleaner_p( ), naCleaner_p(nullptr),
     160           0 :     mt_nterms_p(-1), mt_cleaner_p(), mt_valid_p(false)
     161             : {
     162           0 :   defaults();
     163           0 :   open(other.dirty_p->table().tableName(), other.psf_p->table().tableName());
     164           0 : }
     165             : 
     166           0 : Deconvolver &Deconvolver::operator=(const Deconvolver &other)
     167             : {
     168           0 :   if(this != &other){
     169           0 :     if (dirty_p ) {
     170           0 :       *dirty_p = *(other.dirty_p);
     171             :     }
     172           0 :     if (psf_p ) {
     173           0 :       *psf_p = *(other.psf_p);
     174             :     }
     175           0 :     if (convolver_p && this != &other) {
     176           0 :       *convolver_p = *(other.convolver_p);
     177             :     }
     178           0 :     if ((!cleaner_p.null()) ) {
     179           0 :       *cleaner_p = *(other.cleaner_p);
     180             :     }
     181           0 :     if(naCleaner_p)
     182           0 :       *naCleaner_p=*(other.naCleaner_p);
     183             :   }
     184           0 :   return *this;
     185             : }
     186             : 
     187           0 : Deconvolver::~Deconvolver()
     188             : {
     189           0 :   if (psf_p) {
     190           0 :     delete psf_p;
     191             :   }
     192           0 :   psf_p = 0;
     193           0 :   if (convolver_p) {
     194           0 :     delete convolver_p;
     195             :   }
     196           0 :   convolver_p = 0;
     197             :   /*if (cleaner_p) {
     198             :     delete cleaner_p;
     199             :   }
     200             :   cleaner_p = 0;
     201             :   */
     202           0 :   if (dirty_p) {
     203           0 :     delete dirty_p;
     204             :   }
     205           0 :   dirty_p = 0;
     206           0 : }
     207             : 
     208           0 : Bool Deconvolver::open(const String& dirty, const String& psf, Bool warn)
     209             : {
     210           0 :   LogIO os(LogOrigin("Deconvolver", "open()", WHERE));
     211             :   
     212             : 
     213             :   try {
     214           0 :     if (dirty_p) delete dirty_p;  dirty_p = 0;
     215           0 :     dirty_p = new PagedImage<Float>(dirty);
     216           0 :     AlwaysAssert(dirty_p, AipsError);
     217           0 :     nx_p=dirty_p->shape()(0);
     218           0 :     ny_p=dirty_p->shape()(1);
     219           0 :     dirty_p->setMaximumCacheSize(2*nx_p*ny_p);
     220           0 :     dirty_p->setCacheSizeInTiles(10000);
     221             : 
     222           0 :     if(dirty_p->shape().nelements()==3){
     223           0 :       findAxes();
     224           0 :       if (chanAxis_p > 0)
     225           0 :         nchan_p=dirty_p->shape()(chanAxis_p);
     226             :       else
     227           0 :         nchan_p=0;
     228             :     }
     229           0 :     if(dirty_p->shape().nelements()==4){
     230           0 :       findAxes();
     231           0 :       npol_p=dirty_p->shape()(polAxis_p);
     232           0 :       nchan_p=dirty_p->shape()(chanAxis_p);
     233             :     }
     234           0 :     dirtyName_p =  dirty_p->table().tableName();
     235             :     
     236           0 :     if (psf_p) delete psf_p;  psf_p = 0;
     237           0 :     if (psf == ""){
     238           0 :         if(warn) {
     239             :                 os << LogIO::WARN
     240           0 :                         << "No psf given; please define one before deconvolving" << LogIO::POST;
     241             :                 os << LogIO::WARN
     242           0 :                         << "Use the function open with the psf" << LogIO::POST;
     243             :         }
     244           0 :         return true;
     245             :     }
     246             :     else{
     247           0 :       psf_p = new PagedImage<Float>(psf);
     248           0 :       AlwaysAssert(psf_p, AipsError);
     249           0 :       psfName_p   =  psf_p->table().tableName();    
     250           0 :       psf_p->setMaximumCacheSize(2*nx_p*ny_p);
     251           0 :       psf_p->setCacheSizeInTiles(10000);
     252             :       
     253             :       try{
     254           0 :         os << "Fitting PSF" << LogIO::POST;
     255           0 :         fitpsf(psf, beam_p);
     256           0 :         if(! beam_p.isNull()) {
     257           0 :           os << "  Fitted beam is valid"<< LogIO::POST;
     258             :         }
     259             :         else {
     260             :           os << LogIO::WARN << "Fitted beam is invalid: please set using setbeam"
     261           0 :              << LogIO::POST;
     262             :         }
     263           0 :         beamValid_p=true;
     264             :         
     265           0 :       } catch (AipsError x) {
     266             :         os << LogIO::WARN << "Fitted beam is invalid: please set using setbeam"
     267           0 :            << LogIO::POST;
     268             :       } 
     269             :       
     270           0 :       if((psf_p->shape()(0) != nx_p) || psf_p->shape()(1) != ny_p){
     271             :         
     272             :         os << LogIO::SEVERE 
     273           0 :            << "PSF and Image does not have the same XY shape" << LogIO::POST;
     274             :         os << LogIO::SEVERE
     275             :            << "You may wish to regrid the PSF to the same shape as the dirty image" 
     276           0 :            << LogIO::POST;
     277           0 :       return false;
     278             : 
     279             :       } 
     280             :       
     281             :       try {
     282           0 :         os << "Making Lattice convolver" << LogIO::POST;
     283           0 :         if (convolver_p) {
     284           0 :           delete convolver_p;
     285             :         }
     286             :         
     287             :         //      convolver_p = new LatticeConvolver<Float>(*psf_p);
     288             :         //      AlwaysAssert(convolver_p, AipsError);
     289             :         
     290           0 :         if (residEqn_p) {
     291           0 :           delete residEqn_p;
     292             :         }
     293           0 :         residEqn_p = 0;
     294             :         
     295           0 :         if (latConvEqn_p) {
     296           0 :           delete latConvEqn_p;
     297             :         }
     298           0 :         latConvEqn_p = 0;
     299             :         
     300           0 :         os << "Making Image cleaner" << LogIO::POST;
     301             :         //if (cleaner_p) delete cleaner_p;
     302           0 :         cleaner_p= new ImageMSCleaner(*psf_p, *dirty_p);
     303           0 :         naCleaner_p=make_shared<ImageNACleaner>(*psf_p, *dirty_p);
     304           0 :         if(nchan_p<=1){
     305           0 :           convolver_p = new LatticeConvolver<Float>(*psf_p);
     306             :         }
     307             :         else{
     308           0 :           if(npol_p > 0 ){
     309           0 :             IPosition blc(4, 0, 0, 0, 0);
     310           0 :             IPosition trc(4, nx_p-1, ny_p-1, 0, 0);
     311           0 :             trc(polAxis_p)=npol_p-1;
     312           0 :             Slicer sl(blc, trc, Slicer::endIsLast);
     313           0 :             SubImage<Float> psfSub(*psf_p, sl, true);  
     314           0 :             convolver_p = new LatticeConvolver<Float>(psfSub);
     315           0 :             AlwaysAssert(convolver_p, AipsError);
     316             :           }
     317             :           else{
     318           0 :             IPosition blc(3, 0, 0, 0);
     319           0 :             IPosition trc(3, nx_p-1, ny_p-1, 0);
     320           0 :             Slicer sl(blc, trc, Slicer::endIsLast);
     321             :             //SubImage<Float> dirtySub(*dirty_p, sl, true);
     322           0 :             SubImage<Float> psfSub(*psf_p, sl, true);
     323           0 :             convolver_p = new LatticeConvolver<Float>(psfSub);
     324           0 :             AlwaysAssert(convolver_p, AipsError);
     325             :           }
     326             :           
     327             :         }
     328           0 :         AlwaysAssert(!cleaner_p.null(), AipsError);
     329             :         
     330           0 :         return true;
     331             : 
     332           0 :       } catch (AipsError x) {
     333           0 :         os << LogIO::SEVERE << "Caught Exception: "<< x.getMesg() << LogIO::POST;
     334           0 :         return false;
     335             :       } 
     336             :     }
     337             :   }
     338           0 :   catch (AipsError y){
     339           0 :     throw(y);
     340             :   }
     341             : }
     342             : 
     343           0 : Bool Deconvolver::reopen()
     344             : {
     345           0 :   LogIO os(LogOrigin("Deconvolver", "reopen()", WHERE));
     346             :   try {
     347           0 :     if (dirtyName_p != "" && psfName_p != "") {
     348           0 :       return (open(dirtyName_p, psfName_p));
     349             :     } else {
     350           0 :       return false;
     351             :     }
     352           0 :   }  catch (AipsError x) {
     353           0 :     dirty_p->table().unlock();
     354           0 :     psf_p->table().unlock();
     355           0 :     os << LogIO::SEVERE << "Caught Exception: "<< x.getMesg() << LogIO::POST;
     356           0 :     return false;
     357             :   } 
     358             :   return false;
     359             : }
     360             : 
     361             : // Fit the psf. If psf is blank then make the psf first.
     362           0 : Bool Deconvolver::fitpsf(const String& psf, GaussianBeam& beam)
     363             : {
     364           0 :   if(!valid()) return false;
     365             :   
     366           0 :   LogIO os(LogOrigin("Deconvolver", "fitpsf()", WHERE));
     367             :   
     368             :   try {
     369             :     
     370           0 :     os << "Fitting to psf" << LogIO::POST;
     371             : 
     372           0 :     if(psf=="") {
     373           0 :       os << LogIO::SEVERE << "Need a psf name" << LogIO::POST;
     374           0 :       return false;
     375             :     }
     376             :     
     377           0 :     PagedImage<Float> psfImage(psf);
     378           0 :     StokesImageUtil::FitGaussianPSF(psfImage, beam);
     379           0 :     beam_p = beam;
     380           0 :     beamValid_p=true;
     381             :     
     382             :     os << "  Beam fit: " << beam_p.getMajor("arcsec") << " by "
     383             :        << beam_p.getMinor("arcsec") << " (arcsec) at pa "
     384           0 :        << beam_p.getPA(Unit("deg")) << " (deg) " << endl;
     385           0 :     return true;
     386           0 :   } catch (AipsError x) {
     387           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
     388             :   } 
     389           0 :   return true;
     390             : }
     391             : 
     392           0 : Bool Deconvolver::close()
     393             : {
     394           0 :   if(!valid()) return false;
     395           0 :   if (detached()) return true;
     396           0 :   LogIO os(LogOrigin("Deconvolver", "close()", WHERE));
     397             :   
     398           0 :   os << "Closing images and detaching from Deconvolver" << LogIO::POST;
     399           0 :   if(psf_p) delete psf_p; psf_p = 0;
     400           0 :   if(dirty_p) delete dirty_p; dirty_p = 0;
     401           0 :   if (convolver_p) delete convolver_p; convolver_p = 0;
     402           0 :   if (residEqn_p) delete  residEqn_p;  residEqn_p = 0;
     403           0 :   if (latConvEqn_p) delete latConvEqn_p; latConvEqn_p = 0;
     404             : 
     405           0 :   return true;
     406             : }
     407             : 
     408           0 : String Deconvolver::dirtyname() const
     409             : {
     410           0 :   if (detached()) {
     411           0 :     return "none";
     412             :   }
     413           0 :   return dirty_p->table().tableName();
     414             : }
     415             : 
     416           0 : String Deconvolver::psfname() const
     417             : {
     418           0 :   if (detached()) {
     419           0 :     return "none";
     420             :   }
     421           0 :   return psf_p->table().tableName();
     422             : }
     423             : 
     424           0 : Bool Deconvolver::summary() const
     425             : {
     426           0 :   if(!valid()) return false;
     427           0 :   LogOrigin OR("Deconvolver", "Deconvolver::summary()",  WHERE);
     428             :   
     429           0 :   LogIO los(OR);
     430             :   
     431             :   try {
     432             :     
     433           0 :     los << "Summary of dirty image" << LogIO::POST;
     434           0 :     dirty_p->table().lock();
     435             :     {
     436           0 :        ImageSummary<Float> ims(*dirty_p);
     437           0 :        ims.list(los);
     438             :     }
     439             :     
     440           0 :     los << endl << state() << LogIO::POST;
     441           0 :     dirty_p->table().unlock();
     442             : 
     443           0 :     los << "Summary of PSF" << LogIO::POST;
     444           0 :     psf_p->table().lock();
     445             :     {
     446           0 :        ImageSummary<Float> psfs(*psf_p);
     447           0 :        psfs.list(los);
     448             :     }
     449             :     
     450           0 :     los << "Summary of scales" << LogIO::POST;
     451           0 :     if(scalesValid_p) {
     452           0 :       los << "Scales set" << LogIO::POST;
     453             :     }
     454             :     else {
     455           0 :       los << "Scales not set" << LogIO::POST;
     456             :     }
     457             : 
     458           0 :     los << endl << state() << LogIO::POST;
     459           0 :     psf_p->table().unlock();
     460           0 :     return true;
     461           0 :   } catch (AipsError x) {
     462             :     los << LogIO::SEVERE << "Caught Exception: " << x.getMesg()
     463           0 :         << LogIO::POST;
     464           0 :     dirty_p->table().unlock();
     465           0 :     psf_p->table().unlock();
     466           0 :     return false;
     467             :   } 
     468             :   
     469             :   return true;
     470             : }
     471             : 
     472           0 : String Deconvolver::state() const
     473             : {
     474           0 :   ostringstream os;
     475             :   
     476             :   try {
     477           0 :     os << "General: " << endl;
     478           0 :     if(dirty_p != 0){
     479           0 :       os << "  Dirty image is " << dirty_p->table().tableName() << endl; 
     480           0 :       dirty_p->table().unlock();
     481             :     }
     482           0 :     if(psf_p !=0){
     483           0 :       os << "  PSF         is " << psf_p->table().tableName() << endl;
     484           0 :       psf_p->table().unlock();
     485             :     }
     486           0 :     if(beamValid_p) {
     487           0 :       os << "  Beam fit: " << beam_p.getMajor("arcsec") << " by "
     488           0 :          << beam_p.getMinor("arcsec") << " (arcsec) at pa "
     489           0 :          << beam_p.getPA(Unit("deg")) << " (deg) " << endl;
     490             :     }
     491             :     else {
     492           0 :       os << "  Beam fit is not valid" << endl;
     493             :     }
     494             :     
     495           0 :   } catch (AipsError x) {
     496           0 :     LogOrigin OR("Deconvolver", "Deconvolver::state()", WHERE); 
     497           0 :     LogIO los(OR);
     498             :     los << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     499           0 :        << LogIO::POST;
     500           0 :     dirty_p->table().unlock();
     501           0 :     psf_p->table().unlock();
     502             :   } 
     503           0 :   return String(os);
     504             : }
     505             : 
     506             : // Restore: at least one model must be supplied
     507           0 : Bool Deconvolver::restore(const String& model, const String& image,
     508             :                           GaussianBeam& mbeam)
     509             : {
     510             :   
     511           0 :   if(!valid()) return false;
     512           0 :   LogIO os(LogOrigin("Deconvolver", "restore()", WHERE));
     513             :   
     514           0 :   dirty_p->table().lock();
     515           0 :   psf_p->table().lock();
     516             :   try {
     517             :     
     518             :     // Validate the names
     519           0 :     if(model=="") {
     520             :       os << LogIO::SEVERE << "Need a model"
     521           0 :          << LogIO::POST;
     522           0 :       return false;
     523             :     }
     524             :     
     525           0 :     String imagename(image);
     526           0 :     if(imagename=="") imagename=model+".restored";
     527           0 :     removeTable(imagename);
     528           0 :     if(!clone(model, imagename)) return false;
     529             :     
     530             :     // Smooth all the images and add residuals
     531           0 :     PagedImage<Float> modelImage0(model);
     532             : 
     533             : //
     534           0 :     TiledShape tShape(dirty_p->shape());
     535           0 :     ImageInterface<Float>* modelImage_p = new TempImage<Float>(tShape, dirty_p->coordinates());
     536             : //
     537           0 :     ImageRegrid<Float> regridder;
     538           0 :     Vector<Double> locate;
     539           0 :     Bool missedIt = regridder.insert(*modelImage_p, locate, modelImage0);
     540             :     //cerr << "missedIt " << missedIt << endl;
     541           0 :     if (!missedIt) {
     542           0 :       os << LogIO::SEVERE << "Problem in getting model Image on correct grid " << LogIO::POST;
     543             :     }
     544             : 
     545           0 :     PagedImage<Float> imageImage(modelImage_p->shape(),
     546             :                                  modelImage_p->coordinates(),
     547           0 :                                  image);
     548             : 
     549           0 :     TempImage<Float> dirtyModelImage(modelImage_p->shape(),modelImage_p->coordinates());
     550             :     //imageImage.copyData(*modelImage_p);
     551           0 :     if(! mbeam.isNull()) {
     552             :       os << "  Using specified beam: " << mbeam.getMajor("arcsec") << " by "
     553             :          << mbeam.getMinor("arcsec") << " (arcsec) at pa "
     554           0 :          << mbeam.getPA(Unit("deg")) << " (deg) " << LogIO::POST;
     555             :       //StokesImageUtil::Convolve(imageImage, mbeam, false);
     556             :     }
     557             :     else {
     558           0 :       if(! beam_p.isNull()) {
     559             :         os << "  Using fitted beam: " << beam_p.getMajor("arcsec") << " by "
     560             :            << beam_p.getMinor("arcsec") << " (arcsec) at pa "
     561           0 :            << beam_p.getPA(Unit("deg")) << " (deg) " << LogIO::POST;
     562             :         //StokesImageUtil::Convolve(imageImage, beam_p, false);
     563           0 :         mbeam = beam_p;
     564             :       }
     565             :       else {
     566           0 :         os << LogIO::SEVERE << "Restoring beam not specified" << LogIO::POST;
     567           0 :         return false;
     568             :       }
     569             :     }
     570             :     //Model * restoring beam 
     571             :     {
     572           0 :       IPosition convshp=modelImage_p->shape();
     573           0 :       convshp[0]=nx_p; convshp[1]=ny_p;
     574           0 :       for (uInt k=2; k< convshp.nelements(); ++k) convshp[k]=1;
     575           0 :       TempImage<Float> gaussim(convshp, modelImage_p->coordinates());
     576           0 :       gaussim.set(0.0);
     577           0 :       ImageInfo ii = gaussim.imageInfo();
     578           0 :       ii.setRestoringBeam(mbeam);
     579           0 :       gaussim.setImageInfo(ii);
     580           0 :       gaussim.setUnits(Unit("Jy/beam"));    
     581           0 :       putGaussian(gaussim, mbeam);
     582             :       //////////////////////
     583             :       //PagedImage<Float>xx(gaussim.shape(), gaussim.coordinates(), "tempGauss");
     584             :       //xx.copyData(gaussim);
     585             :       //////////////////
     586           0 :       LatticeConvolver<Float> lc(gaussim);
     587           0 :       lc.linear(imageImage, *modelImage_p);
     588             :     }
     589             :     // PSF * Model    
     590           0 :     convolver_p->circular(dirtyModelImage, *modelImage_p);
     591             : 
     592             :     // Smoothed + Dirty - PSF * Model
     593           0 :     imageImage.copyData(LatticeExpr<Float>(imageImage+*dirty_p - dirtyModelImage));
     594             :     {
     595           0 :       ImageInfo ii = imageImage.imageInfo();
     596           0 :       ii.setRestoringBeam(mbeam);
     597           0 :       imageImage.setImageInfo(ii);
     598           0 :       imageImage.setUnits(Unit("Jy/beam"));
     599             :     }
     600             : 
     601           0 :     dirty_p->table().unlock();
     602           0 :     psf_p->table().unlock();
     603           0 :     if (modelImage_p != & modelImage0) {
     604           0 :       delete modelImage_p;
     605             :     }
     606           0 :     return true;
     607           0 :   } catch (AipsError x) {
     608           0 :     dirty_p->table().unlock();
     609             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     610           0 :        << LogIO::POST;
     611             :   } 
     612           0 :   dirty_p->table().unlock();
     613           0 :   return true;
     614             : }
     615             : 
     616             : // Residual
     617           0 : Bool Deconvolver::residual(const String& model, const String& image)
     618             : {
     619             :   
     620           0 :   if(!valid()) return false;
     621           0 :   LogIO os(LogOrigin("Deconvolver", "residual()", WHERE));
     622             :   
     623           0 :   dirty_p->table().lock();
     624           0 :   psf_p->table().lock();
     625             :   try {
     626             :     
     627             :     // Validate the names
     628           0 :     if(model=="") {
     629             :       os << LogIO::SEVERE << "Need a model"
     630           0 :          << LogIO::POST;
     631             :     }
     632             :     
     633           0 :     String imagename(image);
     634           0 :     if(imagename=="") imagename=model+".residual";
     635           0 :     removeTable(imagename);
     636           0 :     if(!clone(dirty_p->table().tableName(), imagename)) return false;
     637             :     
     638             :     // Smooth all the images and add residuals
     639             :     
     640             :     // modelImage_p is a pointer to an image with the model data in it, but the
     641             :     // shape of the dirty image
     642           0 :     PagedImage<Float> modelImage0(model);
     643             : 
     644           0 :     TiledShape tShape(dirty_p->shape());
     645           0 :     ImageInterface<Float>* modelImage_p = new TempImage<Float>(tShape, dirty_p->coordinates());
     646             : //
     647           0 :     ImageRegrid<Float> regridder;
     648           0 :     Vector<Double> locate;
     649           0 :     Bool missedIt = regridder.insert(*modelImage_p, locate, modelImage0);
     650           0 :     if (!missedIt) {
     651           0 :       os << LogIO::SEVERE << "Problem in getting model Image on correct grid " << LogIO::POST;
     652             :     }
     653             : 
     654           0 :     PagedImage<Float> imageImage(modelImage_p->shape(),
     655             :                                  modelImage_p->coordinates(),
     656           0 :                                  image);
     657             :     // PSF * Model    
     658           0 :     convolver_p->circular(imageImage, *modelImage_p);
     659             : 
     660             :     // Dirty - PSF * Model
     661           0 :     imageImage.copyData(LatticeExpr<Float>(*dirty_p-imageImage));
     662           0 :     imageImage.setUnits(Unit("Jy/beam"));
     663             :     
     664           0 :     dirty_p->table().unlock();
     665           0 :     psf_p->table().unlock();
     666           0 :     if (modelImage_p != & modelImage0) {
     667           0 :       delete modelImage_p;
     668             :     }
     669           0 :     return true;
     670           0 :   } catch (AipsError x) {
     671           0 :     dirty_p->table().unlock();
     672           0 :     psf_p->table().unlock();
     673             :     os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
     674           0 :        << LogIO::POST;
     675             :   } 
     676           0 :   dirty_p->table().unlock();
     677           0 :   psf_p->table().unlock();
     678           0 :   return true;
     679             : }
     680             : 
     681             : // Make an empty image
     682           0 : Bool Deconvolver::make(const String& model)
     683             : {
     684             :   
     685           0 :   if(!valid()) return false;
     686           0 :   LogIO os(LogOrigin("Deconvolver", "make()", WHERE));
     687             :   
     688           0 :   dirty_p->table().lock();
     689             :   try {
     690             :     
     691             :     // Make an image with the required shape and coordinates
     692           0 :     String modelName(model);
     693           0 :     if(modelName=="") modelName=dirty_p->table().tableName()+".model";
     694           0 :     os << "Making empty image: " << model << LogIO::POST;
     695             :     
     696           0 :     removeTable(modelName);
     697           0 :     PagedImage<Float> modelImage(dirty_p->shape(),
     698           0 :                                  dirty_p->coordinates(), model);
     699           0 :     modelImage.set(0.0);
     700             :     
     701           0 :     modelImage.table().tableInfo().setSubType("GENERIC");
     702           0 :     modelImage.setUnits(Unit("Jy/pixel"));
     703           0 :     dirty_p->table().unlock();
     704           0 :     return true;
     705           0 :   } catch (AipsError x) {
     706           0 :     dirty_p->table().unlock();
     707           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
     708             :   } 
     709           0 :   dirty_p->table().unlock();
     710           0 :   return true;
     711             : };
     712             : 
     713             : 
     714             : // Make an empty image, but with only ONE STOKES pixel
     715           0 : Bool Deconvolver::make1(const String& model)
     716             : {
     717             :   
     718           0 :   if(!valid()) return false;
     719           0 :   LogIO os(LogOrigin("Deconvolver", "make1()", WHERE));
     720             :   
     721           0 :   dirty_p->table().lock();
     722             :   try {
     723             :     
     724             :     // Make an image with the required shape and coordinates
     725           0 :     String modelName(model);
     726           0 :     if(modelName=="") modelName=dirty_p->table().tableName()+".model";
     727           0 :     os << "Making empty image: " << model << LogIO::POST;
     728             :     
     729           0 :     removeTable(modelName);
     730           0 :     IPosition newshape = dirty_p->shape();
     731           0 :     newshape(2) = 1;
     732             :     PagedImage<Float> modelImage(newshape,
     733           0 :                                  dirty_p->coordinates(), model);
     734           0 :     modelImage.set(0.0);
     735             :     
     736           0 :     modelImage.table().tableInfo().setSubType("GENERIC");
     737           0 :     modelImage.setUnits(Unit("Jy/pixel"));
     738           0 :     dirty_p->table().unlock();
     739           0 :     return true;
     740           0 :   } catch (AipsError x) {
     741           0 :     dirty_p->table().unlock();
     742           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
     743             :   } 
     744           0 :   dirty_p->table().unlock();
     745           0 :   return true;
     746             : };
     747             : 
     748             : 
     749             : // Make an empty image, modeled in templateImage
     750           0 : Bool Deconvolver::make(const String& model, ImageInterface<Float>& templateImage)
     751             : {
     752             :   
     753           0 :   if(!valid()) return false;
     754           0 :   LogIO os(LogOrigin("Deconvolver", "make()", WHERE));
     755             :   
     756             :   try {
     757             :     
     758             :     // Make an image with the required shape and coordinates
     759           0 :     String modelName(model);
     760             : 
     761           0 :     os << "Making empty image: " << model << LogIO::POST;
     762           0 :         removeTable(modelName);
     763           0 :     PagedImage<Float> modelImage(templateImage.shape(),
     764           0 :                                  templateImage.coordinates(), model);
     765           0 :     modelImage.set(0.0);
     766             :     
     767           0 :     modelImage.table().tableInfo().setSubType("GENERIC");
     768           0 :     modelImage.setUnits(Unit("Jy/pixel"));
     769           0 :     return true;
     770           0 :   } catch (AipsError x) {
     771           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
     772             :   } 
     773           0 :   return true;
     774             : };
     775             : 
     776             : 
     777             : SubImage<Float>* 
     778           0 : Deconvolver::innerQuarter(PagedImage<Float>& in)
     779             : {
     780             : 
     781           0 :   IPosition blc(in.shape().nelements(), 0);
     782           0 :   IPosition trc(in.shape()-1);
     783           0 :   for (Int i=0;i<Int(in.shape().nelements());i++) {
     784           0 :     blc(i)=in.shape()(i)/4;
     785           0 :     trc(i)=blc(i)+in.shape()(i)/2-1;
     786           0 :     if(trc(i)<0) trc(i)=1;
     787             :   }
     788           0 :   LCSlicer quarter(blc, trc);
     789           0 :   SubImage<Float>* si = new SubImage<Float>(in, quarter, true);
     790           0 :   return si;
     791             : };
     792             : 
     793             : 
     794             : SubImage<Float>* 
     795           0 : Deconvolver::allQuarters(PagedImage<Float>& in)
     796             : {
     797           0 :   SubImage<Float>* si = new SubImage<Float>(in, true);
     798           0 :   return si;
     799             : };
     800             : 
     801           0 : Bool Deconvolver::smooth(const String& model, 
     802             :                          const String& image,
     803             :                          GaussianBeam& mbeam,
     804             :                          Bool normalizeVolume)
     805             : {
     806           0 :   if(!valid()) return false;
     807           0 :   LogIO os(LogOrigin("Deconvolver", "smooth()", WHERE));
     808             :   
     809           0 :   dirty_p->table().lock();
     810             :   try {
     811             :     
     812           0 :     os << "Smoothing image" << LogIO::POST;
     813             :     
     814           0 :     if(model=="") {
     815           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
     816           0 :       return false;
     817             :     }
     818             :     
     819           0 :     if(mbeam.getMajor().getValue()==0.0) {
     820           0 :       if(beamValid_p) {
     821           0 :         os << "Using previous beam fit" << LogIO::POST;
     822           0 :         mbeam = beam_p;
     823             : 
     824             :       }
     825             :       else {
     826           0 :         os << LogIO::SEVERE << "Specified beam is invalid" << LogIO::POST;
     827             :       }
     828             :     }
     829             :     
     830             :     // Smooth all the images
     831           0 :     PagedImage<Float> modelImage(model);
     832           0 :     PagedImage<Float> imageImage(modelImage.shape(),
     833             :                                  modelImage.coordinates(),
     834           0 :                                  image);
     835             : //
     836           0 :     imageImage.copyData(modelImage);
     837           0 :     StokesImageUtil::Convolve(imageImage, mbeam, normalizeVolume);
     838             :     {
     839           0 :       ImageInfo ii = imageImage.imageInfo();
     840           0 :       ii.setRestoringBeam(mbeam);
     841           0 :       imageImage.setImageInfo(ii);
     842           0 :       imageImage.setUnits(Unit("Jy/beam"));
     843             :     }
     844             : 
     845           0 :     dirty_p->table().unlock();
     846           0 :     psf_p->table().unlock();
     847           0 :     return true;
     848           0 :   } catch (AipsError x) {
     849           0 :     dirty_p->table().unlock();
     850           0 :     psf_p->table().unlock();
     851           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
     852             :   } 
     853           0 :   dirty_p->table().unlock();
     854           0 :   psf_p->table().unlock();
     855           0 :   return true;
     856             : }
     857             : //will clean casa axes order images 
     858           0 : Bool Deconvolver::clarkclean(const Int niter, 
     859             :                              const Float gain, const Quantity& threshold, 
     860             :                              const String& model, const String& maskName,
     861             :                              Float& maxresidual, Int& iterused,
     862             :                              Float cycleFactor){
     863             : 
     864           0 :   Bool retval=false;
     865           0 :   Double thresh=threshold.get("Jy").getValue();
     866           0 :   String imagename(model);
     867             :   // Make first image with the required shape and coordinates only if
     868             :   // it doesn't exist yet. Otherwise we'll throw an exception later
     869           0 :   if(imagename=="") imagename=dirty_p->table().tableName()+".clarkclean";
     870           0 :   if(!Table::isWritable(imagename)) {
     871           0 :     make(imagename);
     872             :   }
     873           0 :   PagedImage<Float> modelImage(imagename);
     874           0 :   Bool hasMask=false;
     875           0 :   if(maskName !="")
     876           0 :     hasMask=Table::isReadable(maskName);
     877           0 :   if(hasMask){
     878           0 :     PagedImage<Float> mask(maskName);
     879           0 :     retval=ClarkCleanImageSkyModel::clean(modelImage, *dirty_p, *psf_p, mask, maxresidual, iterused, gain, niter, thresh, cycleFactor, true, true); 
     880             :   }
     881             :   else{
     882           0 :     ImageInterface<Float> *tmpMask=0;
     883           0 :     retval=ClarkCleanImageSkyModel::clean(modelImage, *dirty_p, *psf_p, *tmpMask, maxresidual, iterused, gain, niter, thresh, cycleFactor, false, true); 
     884             :   }
     885             :     
     886           0 :   return retval;
     887             : }
     888             : // Clean algorithm
     889           0 : Bool Deconvolver::clarkclean(const Int niter, 
     890             :                              const Float gain, const Quantity& threshold, 
     891             :                              const Bool displayProgress, 
     892             :                              const String& model, const String& maskName,
     893             :                              const Int histBins, 
     894             :                              const Vector<Int>& vi_psfPatchSize, const Float maxExtPsf,
     895             :                              const Float speedUp, Int maxNumPix,
     896             :                              const Int maxNumMajorCycles,
     897             :                              const Int maxNumMinorIterations)
     898             : {
     899           0 :   if(!valid()) return false;
     900           0 :   LogIO os(LogOrigin("Deconvolver", "clarkclean()", WHERE));
     901             :   
     902           0 :   IPosition psfPatchSize(vi_psfPatchSize);
     903             : 
     904             : 
     905           0 :   dirty_p->table().lock();
     906           0 :   psf_p->table().lock();
     907             : 
     908           0 :   String imagename(model);
     909             :   // Make first image with the required shape and coordinates only if
     910             :   // it doesn't exist yet. Otherwise we'll throw an exception later
     911           0 :   if(imagename=="") imagename=dirty_p->table().tableName()+".clarkclean";
     912           0 :   if(!Table::isWritable(imagename)) {
     913           0 :     make(imagename);
     914             :   }
     915           0 :   PagedImage<Float> modelImage(imagename);
     916           0 :   ClarkCleanProgress *ccpp = 0;
     917             : 
     918             :   {
     919           0 :     ostringstream oos;
     920           0 :     oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
     921           0 :         <<threshold;                              ;
     922           0 :     os << String(oos) << LogIO::POST;
     923             :   }
     924             :   {
     925           0 :     ostringstream oos;
     926           0 :     oos << "nHhistBins = "
     927           0 :         <<histBins << ", maxExtPsf = "<<maxExtPsf<<", psfPatchSize = "
     928           0 :         <<psfPatchSize<<", maxNumPix = "<<maxNumPix;
     929           0 :     os << String(oos) << LogIO::POST;
     930             :   }
     931             :   {
     932           0 :     ostringstream oos;
     933           0 :     oos << "Speedup Factor = "<<speedUp<<", maxMajorCycles = "
     934           0 :         << maxNumMajorCycles<<", maxMinorIterations = "<<maxNumMinorIterations;
     935           0 :     os << String(oos) << LogIO::POST;
     936             :   }
     937             :   
     938           0 :   os << "Cleaning image using Clark Clean algorithm" << LogIO::POST;
     939             :   
     940             : 
     941             :   
     942             : 
     943             :   
     944             :   try {    
     945           0 :     if(model=="") {
     946           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
     947           0 :       return false;
     948             :     }
     949           0 :     PagedImage<Float> *mask = 0;
     950           0 :     Bool isCubeMask=false;
     951             :  
     952             :     Int xbeg, xend, ybeg, yend;
     953             :     //default clean box
     954           0 :     xbeg=nx_p/4; 
     955           0 :     xend=3*nx_p/4-1;
     956           0 :     ybeg=ny_p/4; 
     957           0 :     yend=3*ny_p/4-1;
     958             : 
     959             :    // Deal with mask
     960           0 :     if (maskName != "") {
     961           0 :       if( Table::isReadable(maskName)) {
     962           0 :         mask= new PagedImage<Float>(maskName);
     963           0 :         if (chanAxis_p < Int(mask->shape().nelements())){
     964           0 :           if (mask->shape()(chanAxis_p) > 1) 
     965           0 :             isCubeMask=true;
     966             :         }
     967           0 :         checkMask(*mask, xbeg, xend, ybeg, yend);
     968           0 :         AlwaysAssert(mask, AipsError);
     969             : 
     970             :       } else {
     971           0 :         os << LogIO::SEVERE << "Mask "<< mask<<" is not readable" << LogIO::POST;
     972             :       }
     973             :     }
     974           0 :     SubImage<Float> *maskSub=0;
     975           0 :     IPosition blc(2,xbeg,ybeg);
     976           0 :     IPosition trc(2,xend,yend);
     977           0 :     Bool result=false;
     978           0 :     if(nchan_p >=1){
     979           0 :       for (Int k=0; k<nchan_p; ++k){
     980           0 :         os<< "Cleaning channel " << k+1 << LogIO::POST;
     981           0 :         if(npol_p > 0 ){
     982           0 :           blc.resize(4);
     983           0 :           blc(chanAxis_p)=k;
     984           0 :           blc(polAxis_p)=0;
     985           0 :           trc.resize(4);
     986           0 :           trc(polAxis_p)=npol_p-1;
     987           0 :           trc(chanAxis_p)=k;
     988             :           
     989             :         }
     990             :         else{
     991           0 :           blc.resize(3);
     992           0 :           trc.resize(3);  
     993           0 :           blc(chanAxis_p)=k;
     994           0 :           trc(chanAxis_p)=k;
     995             :           
     996             :         }
     997             :       
     998             :         
     999             :         
    1000           0 :         Slicer sl(blc, trc, Slicer::endIsLast);
    1001           0 :         SubImage<Float> psfSub;
    1002             : 
    1003           0 :         if(mask != 0){
    1004           0 :           if( (isCubeMask) || (!isCubeMask && maskSub == 0 )){
    1005           0 :             if(maskSub !=0 ) delete maskSub;
    1006           0 :             blc(0)=0; blc(1)=0;
    1007           0 :             trc(0)=nx_p-1; trc(1)=ny_p-1;
    1008           0 :             sl=Slicer(blc, trc, Slicer::endIsLast);
    1009           0 :             maskSub=new SubImage<Float> (*mask,sl,false);
    1010           0 :             checkMask(*maskSub, xbeg, xend, ybeg, yend);
    1011           0 :             blc(0)=xbeg; blc(1)=ybeg;
    1012           0 :             trc(0)=xend; trc(1)=yend;
    1013           0 :             sl =Slicer(blc, trc, Slicer::endIsLast);
    1014           0 :             delete maskSub;
    1015           0 :             maskSub=new SubImage<Float> (*mask,sl,false);
    1016             :           }
    1017             :         }
    1018             : 
    1019             :    
    1020           0 :         SubImage<Float> dirtySub(*dirty_p, sl, true);
    1021           0 :         SubImage<Float> modelSub(modelImage,sl,true);
    1022           0 :         IPosition blc_psf=blc; IPosition trc_psf=trc;
    1023           0 :         if(psf_p->shape().nelements() != dirty_p->shape().nelements()){
    1024           0 :           blc_psf.resize(psf_p->shape().nelements());
    1025           0 :           trc_psf.resize(psf_p->shape().nelements());
    1026             :         }
    1027           0 :         blc_psf(0)=0; blc_psf(1)=0;
    1028           0 :         trc_psf(0)=nx_p-1; trc_psf(1)=ny_p-1;
    1029           0 :         sl=Slicer(blc_psf, trc_psf, Slicer::endIsLast);
    1030           0 :         psfSub=SubImage<Float>(*psf_p, sl, true);
    1031             :         
    1032           0 :         ClarkCleanLatModel myClarkCleaner(modelSub);
    1033           0 :         if(mask !=0 )
    1034           0 :           myClarkCleaner.setMask(*maskSub);
    1035             :         
    1036           0 :         myClarkCleaner.setNumberIterations(niter);
    1037           0 :         if (maxNumMajorCycles > 0 ) 
    1038           0 :           myClarkCleaner.setMaxNumberMajorCycles((uInt)maxNumMajorCycles);
    1039           0 :         if (maxNumMinorIterations > 0 ) 
    1040           0 :           myClarkCleaner.setMaxNumberMinorIterations((uInt)maxNumMinorIterations); 
    1041             :         
    1042           0 :         myClarkCleaner.setGain(gain);
    1043           0 :         Double d_thresh = threshold.getValue("Jy");
    1044           0 :         myClarkCleaner.setThreshold((Float)d_thresh);
    1045             :         
    1046           0 :         myClarkCleaner.setPsfPatchSize(psfPatchSize);
    1047           0 :         myClarkCleaner.setHistLength((uInt)histBins); 
    1048           0 :         myClarkCleaner.setMaxExtPsf(maxExtPsf); 
    1049           0 :         myClarkCleaner.setSpeedup(speedUp); 
    1050             :         
    1051           0 :         if (maxNumPix == 0) 
    1052           0 :           maxNumPix = (Int)(modelImage.shape().product()*0.04);
    1053           0 :         myClarkCleaner.setMaxNumPix((uInt)maxNumPix);
    1054             :         
    1055             :         //Now actually do the clean
    1056           0 :         if (displayProgress) {
    1057           0 :           ccpp = new ClarkCleanProgress ();
    1058           0 :           myClarkCleaner.setProgress(*ccpp);
    1059             :         }
    1060           0 :         if(latConvEqn_p !=0) delete latConvEqn_p;
    1061           0 :         latConvEqn_p=0;
    1062           0 :         latConvEqn_p = new LatConvEquation (psfSub, dirtySub);
    1063           0 :         result=myClarkCleaner.solve(*latConvEqn_p);
    1064             :       }
    1065             :     }
    1066             :     else{
    1067           0 :       IPosition blc(modelImage.shape().nelements(),0);
    1068           0 :       Int elem= npol_p >0 ? npol_p:0;
    1069           0 :       IPosition trc(modelImage.shape().nelements(),elem);
    1070           0 :       blc(0)=xbeg; blc(1)=ybeg;
    1071           0 :       trc(0)=xend; trc(1)=yend;
    1072           0 :       Slicer sl(blc, trc, Slicer::endIsLast);
    1073           0 :       SubImage<Float> maskSub;
    1074           0 :       SubImage<Float> dirtySub(*dirty_p, sl, true);
    1075           0 :       SubImage<Float> modelSub(modelImage,sl,true);
    1076           0 :       if(psf_p->shape().nelements() != dirty_p->shape().nelements()){
    1077           0 :         blc.resize(psf_p->shape().nelements());
    1078           0 :         trc.resize(psf_p->shape().nelements());
    1079             :       }
    1080           0 :       blc(0)=0; blc(1)=0;
    1081           0 :       trc(0)=nx_p-1; trc(1)=ny_p-1;
    1082           0 :       sl=Slicer(blc, trc, Slicer::endIsLast);
    1083           0 :       SubImage<Float> psfSub(*psf_p, sl, true);
    1084             :       
    1085           0 :       ClarkCleanLatModel myClarkCleaner(modelSub);
    1086           0 :       if(mask !=0 ){
    1087           0 :         maskSub= SubImage<Float>(*mask, sl, false);
    1088           0 :         myClarkCleaner.setMask(maskSub);
    1089             :       }
    1090             : 
    1091           0 :       myClarkCleaner.setNumberIterations(niter);
    1092           0 :       if (maxNumMajorCycles > 0 ) 
    1093           0 :         myClarkCleaner.setMaxNumberMajorCycles((uInt)maxNumMajorCycles);
    1094           0 :       if (maxNumMinorIterations > 0 ) 
    1095           0 :         myClarkCleaner.setMaxNumberMinorIterations((uInt)maxNumMinorIterations); 
    1096             :     
    1097           0 :       myClarkCleaner.setGain(gain);
    1098           0 :       Double d_thresh = threshold.getValue("Jy");
    1099           0 :       myClarkCleaner.setThreshold((Float)d_thresh);
    1100             :   
    1101           0 :       myClarkCleaner.setPsfPatchSize(psfPatchSize);
    1102           0 :       myClarkCleaner.setHistLength((uInt)histBins); 
    1103           0 :       myClarkCleaner.setMaxExtPsf(maxExtPsf); 
    1104           0 :       myClarkCleaner.setSpeedup(speedUp); 
    1105             :   
    1106           0 :       if (maxNumPix == 0) 
    1107           0 :         maxNumPix = (Int)(modelImage.shape().product()*0.04);
    1108           0 :       myClarkCleaner.setMaxNumPix((uInt)maxNumPix);
    1109             : 
    1110             :       //Now actually do the clean
    1111           0 :       if (displayProgress) {
    1112           0 :         ccpp = new ClarkCleanProgress ();
    1113           0 :         myClarkCleaner.setProgress(*ccpp);
    1114             :       }
    1115           0 :       latConvEqn_p = new LatConvEquation (psfSub, dirtySub);
    1116           0 :       result=myClarkCleaner.solve(*latConvEqn_p);
    1117             :     }
    1118           0 :     dirty_p->table().unlock();
    1119           0 :     psf_p->table().unlock();
    1120           0 :     if (ccpp != 0) { delete ccpp; ccpp = 0;}
    1121           0 :     delete latConvEqn_p;  latConvEqn_p = 0;
    1122           0 :     if (mask) { delete  mask;}
    1123             : 
    1124           0 :     return result;
    1125           0 :   } catch (AipsError x) {
    1126           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1127             :   } 
    1128           0 :   dirty_p->table().unlock();
    1129           0 :   psf_p->table().unlock();
    1130           0 :   if (ccpp != 0) {delete ccpp;  ccpp = 0; }
    1131           0 :   delete latConvEqn_p;  latConvEqn_p = 0;
    1132             : 
    1133             :   
    1134           0 :   return true;
    1135             : };
    1136             : 
    1137             : 
    1138             : 
    1139           0 : Bool Deconvolver::setupLatCleaner(const String& /*algorithm*/, const Int /*niter*/,
    1140             :                                   const Float /*gain*/, const Quantity& /*threshold*/, 
    1141             :                                   const Bool /*displayProgress*/){
    1142             : 
    1143           0 :   LogIO os(LogOrigin("Deconvolver", "clean()", WHERE));
    1144             :   
    1145             :   /*
    1146             :   if((algorithm=="msclean")||(algorithm=="fullmsclean" || algorithm=="multiscale" || algorithm=="fullmultiscale")) {
    1147             :     os << "Cleaning image using multi-scale algorithm" << LogIO::POST;
    1148             :     if(!scalesValid_p) {
    1149             :       os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
    1150             :       return false;
    1151             :     }
    1152             :     cleaner_p->setscales(scaleSizes_p);
    1153             :     cleaner_p->setcontrol(CleanEnums::MULTISCALE, niter, gain, threshold);
    1154             :   }
    1155             :   else if (algorithm=="hogbom") {
    1156             :     if(!scalesValid_p) {
    1157             :       Vector<Float> dummy;
    1158             :       setscales("nscales", 1, dummy);
    1159             :     }
    1160             :     cleaner_p->setscales(scaleSizes_p);
    1161             :     cleaner_p->setcontrol(CleanEnums::HOGBOM, niter, gain, threshold);
    1162             :   } else {
    1163             :     os << LogIO::SEVERE << "Unknown algorithm: " << algorithm << LogIO::POST;
    1164             :     return false;
    1165             :   }
    1166             : 
    1167             :   
    1168             : 
    1169             : 
    1170             :   if(algorithm=="fullmsclean" || algorithm=="fullmultiscale") {
    1171             :     os << "Cleaning full image using multi-scale algorithm" << LogIO::POST;
    1172             :     cleaner_p->ignoreCenterBox(true);
    1173             :   }
    1174             :   */
    1175           0 :   return true;
    1176             : 
    1177             : }
    1178             : // Clean algorithm
    1179           0 : Bool Deconvolver::clean(const String& algorithm, const Int niter,
    1180             :                         const Float gain, const Quantity& threshold, 
    1181             :                         const Bool displayProgress,
    1182             :                         const String& model, const String& mask, Float& maxResidual, Int& iterationsDone)
    1183             : {
    1184             :   
    1185           0 :   if(!valid()) return false;
    1186           0 :   LogIO os(LogOrigin("Deconvolver", "clean()", WHERE));
    1187             :   
    1188           0 :   dirty_p->table().lock();
    1189           0 :   psf_p->table().lock();
    1190             :   try {
    1191             :     
    1192           0 :     if(model=="") {
    1193           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    1194           0 :       return false;
    1195             :     }
    1196             :     //Int psfnchan=psf_p->shape()(chanAxis_p);
    1197             :     //Int masknchan=0;
    1198             :   
    1199           0 :     String imagename(model);
    1200             :     // Make first image with the required shape and coordinates only if
    1201             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    1202           0 :     if(imagename=="") imagename=dirty_p->table().tableName()+"."+algorithm;
    1203           0 :     if(!Table::isWritable(imagename)) {
    1204           0 :       make(imagename);
    1205             :     }
    1206             :     
    1207             :     {
    1208           0 :       ostringstream oos;
    1209           0 :       oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
    1210           0 :           <<threshold << ", Algorithm " << algorithm ;
    1211           0 :       os << String(oos) << LogIO::POST;
    1212             :     }
    1213             : 
    1214           0 :     PagedImage<Float> modelImage(imagename);
    1215             : 
    1216           0 :     AlwaysAssert(!cleaner_p.null(), AipsError);
    1217           0 :     PagedImage<Float> *maskim = 0;
    1218             :     // Deal with mask
    1219           0 :     if (mask != "") {
    1220           0 :       if( Table::isReadable(mask)) {
    1221           0 :         maskim = new PagedImage<Float>(mask);
    1222           0 :         AlwaysAssert(maskim, AipsError);
    1223           0 :         cleaner_p->setMask(*maskim);
    1224             :          } else {
    1225             : 
    1226           0 :         os << LogIO::SEVERE << "Mask "<< mask<<" is not readable" << LogIO::POST;
    1227             :       }
    1228             :     }
    1229             : 
    1230             :     
    1231           0 :     Bool result=false;
    1232             : 
    1233           0 :     result=cleaner_p->clean(modelImage, algorithm, niter, gain, threshold, displayProgress);
    1234           0 :     maxResidual=cleaner_p->maxResidual();
    1235           0 :     iterationsDone=cleaner_p->numberIterations();
    1236           0 :     dirty_p->table().relinquishAutoLocks(true);
    1237           0 :     dirty_p->table().unlock();
    1238           0 :     psf_p->table().relinquishAutoLocks(true);
    1239           0 :     psf_p->table().unlock();
    1240           0 :     if (maskim) delete maskim;    
    1241             : 
    1242           0 :     return result;
    1243           0 :   } catch (AipsError x) {
    1244           0 :     dirty_p->table().unlock();
    1245           0 :     psf_p->table().unlock();
    1246           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1247             :   } 
    1248             :   
    1249           0 :   return true;
    1250             : }
    1251             : 
    1252           0 : Bool Deconvolver::naclean(const Int niter,
    1253             :                         const Float gain, const Quantity& threshold, 
    1254             :                           const String& model, const String& maskname, const Int masksupp, const Int memType, const Float numSigma, Float& maxResidual, Int& iterationsDone)
    1255             : {
    1256             :   
    1257           0 :   if(!valid()) return false;
    1258           0 :   LogIO os(LogOrigin("Deconvolver", "clean()", WHERE));
    1259             :   
    1260           0 :   dirty_p->table().lock();
    1261           0 :   psf_p->table().lock();
    1262             :   try {
    1263             :     
    1264           0 :     if(model=="") {
    1265           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    1266           0 :       return false;
    1267             :     }
    1268             :     //Int psfnchan=psf_p->shape()(chanAxis_p);
    1269             :     //Int masknchan=0;
    1270             :   
    1271           0 :     String imagename(model);
    1272             :     // Make first image with the required shape and coordinates only if
    1273             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    1274           0 :     if(imagename=="") imagename=dirty_p->table().tableName()+".naclean";
    1275           0 :     if(!Table::isWritable(imagename)) {
    1276           0 :       make(imagename);
    1277             :     }
    1278             :     
    1279             :     {
    1280           0 :       ostringstream oos;
    1281           0 :       oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
    1282           0 :           <<threshold ;
    1283           0 :       os << String(oos) << LogIO::POST;
    1284             :     }
    1285             : 
    1286           0 :     PagedImage<Float> modelImage(imagename);
    1287             : 
    1288           0 :     AlwaysAssert(naCleaner_p != nullptr, AipsError);
    1289           0 :     PagedImage<Float> *maskim = 0;
    1290             :     // Deal with mask
    1291           0 :     String mask=maskname;
    1292           0 :     if (mask == "") {
    1293           0 :       mask=dirty_p->table().tableName()+".mask";
    1294             :     }
    1295           0 :     if(!Table::isWritable(mask))
    1296           0 :        make(mask);
    1297             :     
    1298           0 :     maskim = new PagedImage<Float>(mask);
    1299             :        
    1300             :     
    1301           0 :     AlwaysAssert(maskim, AipsError);
    1302           0 :     naCleaner_p->setMask(*maskim);
    1303             : 
    1304             :     
    1305             : 
    1306             :     
    1307           0 :     Bool result=false;
    1308             : 
    1309           0 :     result=naCleaner_p->clean(modelImage, niter, gain, threshold, masksupp, memType, numSigma);
    1310           0 :     maxResidual=cleaner_p->maxResidual();
    1311           0 :     iterationsDone=cleaner_p->iteration();
    1312           0 :     dirty_p->table().relinquishAutoLocks(true);
    1313           0 :     dirty_p->table().unlock();
    1314           0 :     psf_p->table().relinquishAutoLocks(true);
    1315           0 :     psf_p->table().unlock();
    1316           0 :     if (maskim) delete maskim;    
    1317             : 
    1318           0 :     return result;
    1319           0 :   } catch (AipsError x) {
    1320           0 :     dirty_p->table().unlock();
    1321           0 :     psf_p->table().unlock();
    1322           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1323             :   } 
    1324             :   
    1325           0 :   return true;
    1326             : }
    1327             : 
    1328             : 
    1329             : 
    1330             : // MEM algorithm
    1331           0 : Bool Deconvolver::mem(const String& entropy, const Int niter,
    1332             :                       const Quantity& sigma, const Quantity& targetFlux, 
    1333             :                       Bool constrainTargetFlux, Bool displayProgress,
    1334             :                       const String& model, const String& priorImage,
    1335             :                       const String& maskImage,
    1336             :                       const Bool imagePlane)
    1337             : {
    1338             :   
    1339           0 :   if(!valid()) return false;
    1340           0 :   LogIO os(LogOrigin("Deconvolver", "mem()", WHERE));
    1341             :   
    1342             :   //  SubImage<Float>* dirtyQ_p =0; 
    1343             :   //  SubImage<Float>* modelImageQ_p =0;
    1344             :   //  SubImage<Float>* priorImageQ_p =0;
    1345             :   //  SubImage<Float>* maskImageQ_p =0;
    1346             : 
    1347           0 :   Entropy* myEnt_p =0;
    1348           0 :   CEMemProgress * memProgress_p = 0;
    1349           0 :   residEqn_p=0;
    1350             : 
    1351             :   try {
    1352             : 
    1353             :     //    if(model=="") {
    1354             :     //     os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    1355             :     //      return false;
    1356             :     //   }
    1357             : 
    1358           0 :     Bool initializeModel = false;
    1359             :     Int xbeg, xend, ybeg, yend;
    1360           0 :     if (imagePlane) {
    1361           0 :       xbeg=0;
    1362           0 :       xend=nx_p-1;
    1363           0 :       ybeg=0;
    1364           0 :       yend=ny_p-1;
    1365           0 :       fullPlane_p=true;
    1366             :     } else {
    1367           0 :       xbeg=nx_p/4; 
    1368           0 :       xend=3*nx_p/4-1;
    1369           0 :       ybeg=ny_p/4; 
    1370           0 :       yend=3*ny_p/4-1;
    1371             :     }
    1372             : 
    1373           0 :     String imagename(model);
    1374             :     // Make first image with the required shape and coordinates only if
    1375             :     // it doesn't exist yet. Otherwise we'll throw an exception later
    1376           0 :     if(imagename=="") {
    1377           0 :       imagename=dirty_p->table().tableName()+"."+entropy;
    1378             :       os << LogIO::WARN << "No model name given, model will be " 
    1379           0 :          << imagename  << LogIO::POST;
    1380             :     }
    1381           0 :     if(!Table::isWritable(imagename)) {
    1382           0 :       initializeModel = true;
    1383           0 :       make(imagename);
    1384           0 :       dirty_p->table().lock();
    1385           0 :       psf_p->table().lock();
    1386             :     }
    1387             : 
    1388           0 :     PagedImage<Float> modelImage(imagename);
    1389             :     
    1390             :     //   if (imagePlane) {
    1391             :     //      modelImageQ_p = allQuarters(modelImage);
    1392             :     //   } else {
    1393             :     //     modelImageQ_p = innerQuarter(modelImage);
    1394             :     //  }
    1395             : 
    1396             :     {
    1397           0 :       ostringstream oos;
    1398           0 :       oos << "MEM Niter = "<<niter<<", Sigma = "<<sigma << 
    1399           0 :         ", TargetFlux = "  <<targetFlux << 
    1400           0 :         ", ConstrainTargetFlux = "  <<constrainTargetFlux << 
    1401           0 :         ", Entropy = " << entropy;
    1402           0 :       os << String(oos) << LogIO::POST;
    1403             :     }
    1404             : 
    1405           0 :     if(entropy=="entropy") {
    1406           0 :       os << "Deconvolving image using maximum entropy algorithm" << LogIO::POST;
    1407           0 :       myEnt_p = new EntropyI;
    1408             :     }
    1409           0 :     else if (entropy=="emptiness") {
    1410           0 :       myEnt_p = new EntropyEmptiness;
    1411             :     }
    1412             :     else {
    1413           0 :       os << " Known MEM entropies: entropy | emptiness " << LogIO::POST;
    1414           0 :       os << LogIO::SEVERE << "Unknown MEM entropy: " << entropy << LogIO::POST;
    1415           0 :       return false;
    1416             :     }
    1417             : 
    1418             : 
    1419           0 :     PagedImage<Float> *mask = 0;
    1420           0 :     Bool isCubeMask=false;
    1421           0 :     PagedImage<Float> *prior =0;
    1422             :     
    1423             :     // Deal with mask
    1424           0 :     if (maskImage != "") {
    1425           0 :       if( Table::isReadable(maskImage)) {
    1426           0 :         mask= new PagedImage<Float>(maskImage);
    1427           0 :         if (chanAxis_p < Int(mask->shape().nelements())){
    1428           0 :           if (mask->shape()(chanAxis_p) > 1) 
    1429           0 :             isCubeMask=true;
    1430             :         }
    1431           0 :         checkMask(*mask, xbeg, xend, ybeg, yend);
    1432           0 :         AlwaysAssert(mask, AipsError);
    1433             :         
    1434             :       } else {
    1435           0 :         os << LogIO::SEVERE << "Mask "<< mask<<" is not readable" << LogIO::POST;
    1436             :       }
    1437             :     }
    1438             : 
    1439           0 :     if (priorImage!="") {
    1440           0 :       if( Table::isReadable(priorImage)) {
    1441           0 :         prior= new PagedImage<Float>(priorImage);
    1442             :       } else {
    1443           0 :         os << LogIO::SEVERE << "Prior "<< prior<<" is not readable" << LogIO::POST;
    1444             :       }
    1445             :     }
    1446             : 
    1447           0 :     Bool result=false;
    1448           0 :     SubImage<Float> *maskSub=0;
    1449           0 :     IPosition blc(2,xbeg,ybeg);
    1450           0 :     IPosition trc(2,xend,yend);
    1451           0 :     if(nchan_p >= 1){
    1452           0 :       for (Int k=0; k< nchan_p; ++k){        
    1453           0 :         os<< "Processing channel " << k+1 << LogIO::POST;
    1454           0 :         if(npol_p > 0 ){
    1455           0 :           blc.resize(4);
    1456           0 :           blc(chanAxis_p)=k;
    1457           0 :           blc(polAxis_p)=0;
    1458           0 :           trc.resize(4);
    1459           0 :           trc(polAxis_p)=npol_p-1;
    1460           0 :           trc(chanAxis_p)=k;
    1461             :         
    1462             :         }
    1463             :         else{
    1464           0 :           blc.resize(3);
    1465           0 :           trc.resize(3);  
    1466           0 :           blc(chanAxis_p)=k;
    1467           0 :           trc(chanAxis_p)=k;
    1468             :         
    1469             :         }
    1470             : 
    1471           0 :         Slicer sl(blc, trc, Slicer::endIsLast);
    1472           0 :         SubImage<Float> psfSub;
    1473           0 :         SubImage<Float> priorSub;
    1474             : 
    1475           0 :         if(mask != 0){
    1476           0 :           if( (isCubeMask) || (!isCubeMask && maskSub == 0 )){
    1477           0 :             if(maskSub !=0 ) delete maskSub;
    1478           0 :             blc(0)=0; blc(1)=0;
    1479           0 :             trc(0)=nx_p-1; trc(1)=ny_p-1;
    1480           0 :             sl=Slicer(blc, trc, Slicer::endIsLast);
    1481           0 :             maskSub=new SubImage<Float> (*mask,sl,false);
    1482           0 :             checkMask(*maskSub, xbeg, xend, ybeg, yend);
    1483           0 :             blc(0)=xbeg; blc(1)=ybeg;
    1484           0 :             trc(0)=xend; trc(1)=yend;
    1485           0 :             sl =Slicer(blc, trc, Slicer::endIsLast);
    1486           0 :             delete maskSub;
    1487           0 :             maskSub=new SubImage<Float> (*mask,sl,false);
    1488             :           }
    1489             :         }
    1490             : 
    1491             : 
    1492           0 :         if(prior !=0 ){   
    1493           0 :           priorSub= SubImage<Float>(*prior, false);
    1494             :         }
    1495             : 
    1496           0 :         SubImage<Float> dirtySub(*dirty_p, sl, true);
    1497           0 :         SubImage<Float> modelSub(modelImage,sl,true);
    1498           0 :         IPosition blc_psf=blc; IPosition trc_psf=trc;
    1499           0 :         if(psf_p->shape().nelements() != dirty_p->shape().nelements()){
    1500           0 :           blc_psf.resize(psf_p->shape().nelements());
    1501           0 :           trc_psf.resize(psf_p->shape().nelements());
    1502             :         }
    1503           0 :         blc_psf(0)=0; blc_psf(1)=0;
    1504           0 :         trc_psf(0)=nx_p-1; trc_psf(1)=ny_p-1;
    1505           0 :         sl=Slicer(blc_psf, trc_psf, Slicer::endIsLast);
    1506           0 :         psfSub=SubImage<Float>(*psf_p, sl, true);
    1507             : 
    1508             : 
    1509             : 
    1510           0 :         CEMemModel myMemer( *myEnt_p, modelSub, niter, sigma.getValue("Jy"),
    1511           0 :                             targetFlux.getValue("Jy"),  constrainTargetFlux,
    1512           0 :                             initializeModel, imagePlane);
    1513             :     
    1514           0 :         if (!initializeModel) {
    1515           0 :           Record info=modelImage.miscInfo();
    1516             :           try {
    1517           0 :             Float alpha = 0.0;
    1518           0 :             Float beta = 0.0;
    1519           0 :             info.get("ALPHA", alpha);
    1520           0 :             myMemer.setAlpha(alpha);
    1521           0 :             info.get("BETA", beta);
    1522           0 :             myMemer.setBeta(beta); 
    1523           0 :           } catch  (AipsError x) {
    1524             :             // could not get Alpha and Beta for initialization
    1525             :             // continue
    1526             :             os << "Could not retrieve Alpha and Beta from previously initialized model" 
    1527           0 :                << LogIO::POST;
    1528             :           } 
    1529             :         } 
    1530             : 
    1531             : 
    1532             : 
    1533           0 :         if(prior != 0){
    1534           0 :           myMemer.setPrior(priorSub);
    1535             :         }
    1536           0 :         if (mask != 0) {
    1537           0 :           myMemer.setMask(*maskSub);
    1538             :         }
    1539             :       
    1540             :     
    1541             :         // Now actually do the MEM deconvolution
    1542           0 :         if (displayProgress) {
    1543           0 :           memProgress_p = new  CEMemProgress ();
    1544           0 :           myMemer.setProgress(*memProgress_p);
    1545             :         }
    1546             : 
    1547           0 :         if(residEqn_p !=0) delete residEqn_p;
    1548           0 :         residEqn_p=0;
    1549           0 :         if (imagePlane) {
    1550           0 :           residEqn_p = new IPLatConvEquation (psfSub, dirtySub);
    1551             :         } else {
    1552           0 :           residEqn_p = new LatConvEquation (psfSub, dirtySub);
    1553             :         }    
    1554             : 
    1555           0 :         result=myMemer.solve(*residEqn_p);
    1556             :     
    1557           0 :         Record info=modelImage.miscInfo();
    1558           0 :         info.define("ALPHA", myMemer.getBeta());
    1559           0 :         info.define("BETA",  myMemer.getAlpha());
    1560           0 :         modelImage.setMiscInfo(info);
    1561             :       }
    1562             :     }
    1563             : 
    1564             :     else{
    1565           0 :       SubImage<Float>* dirtyQ =0; 
    1566           0 :       SubImage<Float>* modelQ =0; 
    1567           0 :       Bool initializeModel = false;
    1568             : 
    1569           0 :       if (imagePlane) {
    1570           0 :         dirtyQ = allQuarters(*dirty_p);
    1571             :       } else {
    1572           0 :         dirtyQ = innerQuarter(*dirty_p);
    1573             :       }
    1574           0 :       if (imagePlane) {
    1575           0 :         modelQ = allQuarters(modelImage);
    1576             :       } else {
    1577           0 :         modelQ = innerQuarter(modelImage);
    1578             :       }
    1579             :       CEMemModel myMemer( *myEnt_p, *modelQ, niter, 
    1580           0 :                           sigma.getValue("Jy"),
    1581           0 :                           targetFlux.getValue("Jy"),  constrainTargetFlux,
    1582           0 :                           initializeModel, imagePlane);
    1583           0 :       if (!initializeModel) {
    1584           0 :         Record info=modelImage.miscInfo();
    1585             :         try {
    1586           0 :           Float alpha = 0.0;
    1587           0 :           Float beta = 0.0;
    1588           0 :           info.get("ALPHA", alpha);
    1589           0 :           myMemer.setAlpha(alpha);
    1590           0 :           info.get("BETA", beta);
    1591           0 :           myMemer.setBeta(beta); 
    1592           0 :         } catch  (AipsError x) {
    1593             :           // could not get Alpha and Beta for initialization
    1594             :           // continue
    1595             :           os << "Could not retrieve Alpha and Beta from previously initialized model" 
    1596           0 :              << LogIO::POST;
    1597             :         } 
    1598             :       } 
    1599           0 :       SubImage<Float> * priorQ=NULL;
    1600           0 :       if(prior !=0){    
    1601             : 
    1602           0 :         if (imagePlane) {
    1603           0 :           priorQ = allQuarters(*prior);
    1604             :         } else {
    1605           0 :           priorQ = innerQuarter(*prior);
    1606             :         
    1607             :         }
    1608           0 :          myMemer.setPrior(*priorQ);
    1609             :       }
    1610           0 :       SubImage<Float> *maskQ=NULL;
    1611           0 :       if(mask !=0){     
    1612             : 
    1613           0 :         if (imagePlane) {
    1614           0 :           maskQ = allQuarters(*mask);
    1615             :         } else {
    1616           0 :           maskQ = innerQuarter(*mask);
    1617             :         
    1618             :         }
    1619           0 :          myMemer.setMask(*maskQ);
    1620             :       }
    1621           0 :       if (displayProgress) {
    1622           0 :         memProgress_p = new  CEMemProgress ();
    1623           0 :         myMemer.setProgress(*memProgress_p);
    1624             :       }
    1625             : 
    1626           0 :       if (imagePlane) {
    1627           0 :         residEqn_p = new IPLatConvEquation (*psf_p, *dirtyQ);
    1628             :       } else {
    1629           0 :         residEqn_p = new LatConvEquation (*psf_p, *dirtyQ);
    1630             :       }    
    1631             :       
    1632           0 :       result=myMemer.solve(*residEqn_p);
    1633             :       
    1634           0 :       Record info=modelImage.miscInfo();
    1635           0 :       info.define("ALPHA", myMemer.getBeta());
    1636           0 :       info.define("BETA",  myMemer.getAlpha());
    1637           0 :       modelImage.setMiscInfo(info);
    1638             : 
    1639           0 :       if (dirtyQ != 0) {delete dirtyQ; dirtyQ = 0;}
    1640           0 :       if (modelQ != 0) {delete modelQ; modelQ = 0;}
    1641           0 :       if (residEqn_p != 0) {delete residEqn_p;    residEqn_p = 0;}
    1642           0 :       if (priorQ != 0) {delete priorQ; priorQ = 0;}
    1643           0 :       if (maskQ != 0) {delete maskQ; maskQ = 0;}
    1644             : 
    1645             :     }
    1646             : 
    1647           0 :     modelImage.setUnits(Unit("Jy/pixel"));
    1648             : 
    1649           0 :     dirty_p->table().unlock();
    1650           0 :     psf_p->table().unlock();
    1651           0 :     if (myEnt_p != 0) {delete myEnt_p;  myEnt_p = 0;}
    1652           0 :     if (memProgress_p!=0) {delete memProgress_p;  memProgress_p = 0; }    
    1653             : 
    1654           0 :     return result;
    1655             : 
    1656           0 :   } catch (AipsError x) {
    1657           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1658             :   } 
    1659             :   
    1660           0 :   dirty_p->table().unlock();
    1661           0 :   psf_p->table().unlock();
    1662           0 :   if (myEnt_p != 0) {delete myEnt_p;  myEnt_p = 0;}
    1663           0 :   if (residEqn_p != 0) {delete residEqn_p;    residEqn_p = 0;}
    1664           0 :   if (memProgress_p!=0) {delete memProgress_p;  memProgress_p = 0; }    
    1665             :   
    1666           0 :   return true;
    1667             : }
    1668             : 
    1669             : // makeprior, for MEM
    1670           0 : Bool Deconvolver::makeprior(const String& prior, const String& templatename, 
    1671             :                             const Quantity& lowClipFrom, const Quantity& lowClipTo, 
    1672             :                             const Quantity& highClipFrom, const Quantity& highClipTo, 
    1673             :                             const Vector<Int>& blc, const Vector<Int>& trc)
    1674             : {
    1675             :   
    1676           0 :   if(!valid()) return false;
    1677           0 :   LogIO os(LogOrigin("Deconvolver", "makeprior()", WHERE));
    1678             :   
    1679             :   try {
    1680           0 :     if(templatename=="") {
    1681             :       os << LogIO::SEVERE << "Need a name for template image " << endl
    1682             :          << "May I suggest you make a clean or mem image and " << endl
    1683           0 :          << "smooth it for the template?" << LogIO::POST;
    1684           0 :       return false;
    1685             :     }
    1686           0 :     if(prior=="") {
    1687           0 :       os << LogIO::SEVERE << "Need a name for output prior image " << LogIO::POST;
    1688           0 :       return false;
    1689             :     }
    1690             : 
    1691           0 :     PagedImage<Float> templateImage(templatename);
    1692           0 :     String priorname(prior);
    1693           0 :     if(priorname=="") priorname=templateImage.table().tableName()+".prior";
    1694           0 :     if(!Table::isWritable(priorname)) {
    1695           0 :       make(priorname);
    1696             :     }
    1697             : //
    1698           0 :     PagedImage<Float> priorImage(priorname);
    1699           0 :     ImageInterface<Float>* templateImage2_p = 0;
    1700             : //
    1701           0 :     if (priorImage.shape() != templateImage.shape()) {
    1702           0 :        TiledShape tShape(priorImage.shape());
    1703           0 :        templateImage2_p = new TempImage<Float>(tShape, priorImage.coordinates());
    1704             : //
    1705           0 :        ImageRegrid<Float> regridder;
    1706           0 :        Vector<Double> locate;
    1707           0 :        Bool missedIt = regridder.insert(*templateImage2_p, locate, templateImage);
    1708           0 :        if (!missedIt) {
    1709           0 :         os << LogIO::SEVERE << "Problem in getting template Image on correct grid " << LogIO::POST;
    1710             :        }
    1711             :     } else {
    1712           0 :       templateImage2_p = &templateImage;
    1713             :     }
    1714             : 
    1715             :     {
    1716           0 :       ostringstream oos;
    1717           0 :       oos << "Prior = "<<priorname<<", template = "<<templatename << endl;
    1718           0 :       oos <<"   Clip Below = "  << lowClipFrom.getValue("Jy") << 
    1719           0 :         ", Replace with = "  << lowClipTo.getValue("Jy") << endl;
    1720             :       
    1721           0 :       oos <<"   Clip Above = "  << highClipFrom.getValue("Jy") << 
    1722           0 :         ", Replace with = "  << highClipTo.getValue("Jy") << endl; 
    1723             :       // oos <<"   blc = " << blc <<", trc = " << trc << endl;
    1724           0 :       os << String(oos) << LogIO::POST;
    1725             :     }
    1726             : 
    1727           0 :     priorImage.set(lowClipTo.getValue("Jy"));
    1728             : 
    1729           0 :     IPosition iblc(blc);
    1730           0 :     IPosition itrc(trc);
    1731           0 :     IPosition imshape(priorImage.shape());  
    1732             :     //    Index::convertIPosition(iblc, blc);
    1733             :     //   Index::convertIPosition(itrc, trc);
    1734           0 :     IPosition iinc(imshape.nelements(),1);
    1735           0 :     LCBox::verify(iblc, itrc, iinc, imshape);
    1736           0 :     LCSlicer box(iblc, itrc);
    1737             : 
    1738           0 :     SubImage<Float> templateBox(*templateImage2_p, ImageRegion(box), false);
    1739           0 :     SubImage<Float> priorBox(priorImage, ImageRegion(box), true);
    1740             : 
    1741             :     // do Low clipping
    1742           0 :     priorBox.copyData( (LatticeExpr<Float>) 
    1743           0 :                        (iif(templateBox<lowClipFrom.getValue("Jy"), 
    1744             :                             lowClipTo.getValue("Jy"), templateBox)) );  
    1745             :     // do High clipping
    1746           0 :     priorBox.copyData( (LatticeExpr<Float>) 
    1747           0 :                        (iif(priorBox > highClipFrom.getValue("Jy"), 
    1748             :                             highClipTo.getValue("Jy"), priorBox)) );  
    1749             : 
    1750             : 
    1751           0 :     return true;
    1752           0 :   } catch (AipsError x) {
    1753           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1754             :   } 
    1755             :   
    1756           0 :   return true;
    1757             : }
    1758             : 
    1759             : // clipimage
    1760           0 : Bool Deconvolver::clipimage(const String& clippedImageName, const String& inputImageName, 
    1761             :                             const Quantity& threshold)
    1762             : {
    1763           0 :   if(!valid()) return false;
    1764           0 :   LogIO os(LogOrigin("Deconvolver", "clipimage()", WHERE));
    1765             :   
    1766             :   try {
    1767           0 :     if(inputImageName=="") {
    1768           0 :       os << LogIO::SEVERE << "Need a name for the image to clip" <<  LogIO::POST;
    1769           0 :       return false;
    1770             :     }
    1771           0 :     if(clippedImageName=="") {
    1772           0 :       os << LogIO::SEVERE << "Need a name for output clipped image " << LogIO::POST;
    1773           0 :       return false;
    1774             :     }
    1775             : 
    1776           0 :     PagedImage<Float> inputImage(inputImageName);
    1777           0 :     String clippedImageName2(clippedImageName);
    1778           0 :     if(clippedImageName2=="") clippedImageName2 = inputImage.table().tableName()+".clipped";
    1779           0 :     if(!Table::isWritable(clippedImageName2)) {
    1780           0 :       make (clippedImageName2);
    1781             :     }
    1782           0 :     PagedImage<Float> clippedImage(clippedImageName2);
    1783           0 :     if  (clippedImage.shape() != inputImage.shape() ) {
    1784           0 :       os << LogIO::SEVERE << "Input and clipped image sizes disagree " << LogIO::POST;
    1785           0 :       return false;
    1786             :     }
    1787             :     {
    1788           0 :       ostringstream oos;
    1789           0 :       oos << "Clipped Image = "<<clippedImageName2<<", Input Image = "<< inputImageName << endl;
    1790           0 :       oos << "Clip with Stokes I below = "  << threshold.getValue("Jy");
    1791           0 :       os << String(oos) << LogIO::POST;
    1792             :     }
    1793             : 
    1794           0 :     IPosition trc = inputImage.shape() - 1;
    1795           0 :     IPosition blc(4,0);
    1796             :     
    1797           0 :     trc(2) = 0;
    1798           0 :     blc(2) = 0;
    1799           0 :     LCSlicer boxI(blc, trc);
    1800           0 :     SubImage<Float> stokesISub(inputImage, ImageRegion(boxI), false);
    1801             :     Int iStokes;
    1802           0 :     for (iStokes=0; iStokes < inputImage.shape()(2); iStokes++) {
    1803           0 :       trc(2) = iStokes;
    1804           0 :       blc(2) = iStokes;
    1805           0 :       LCSlicer box(blc, trc);
    1806           0 :       SubImage<Float> stokesClippedSub(clippedImage, ImageRegion(box), true);
    1807           0 :       SubImage<Float>   stokesInputSub(inputImage, ImageRegion(box), false);
    1808           0 :       if (stokesISub.shape() != stokesClippedSub.shape() ) {
    1809           0 :         os << LogIO::SEVERE << "Input and clipped image sizes disagree " << LogIO::POST;
    1810           0 :         return false;
    1811             :       }
    1812           0 :       stokesClippedSub.copyData( (LatticeExpr<Float>) 
    1813           0 :                                  (iif(stokesISub < threshold.getValue("Jy"), 
    1814             :                                       0.0, stokesInputSub)) );  
    1815             :     }
    1816           0 :     return true;
    1817           0 :   } catch (AipsError x) {
    1818           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1819             :   } 
    1820             :   
    1821           0 :   return true;
    1822             : }
    1823             : 
    1824             : // boxmask
    1825           0 : Bool Deconvolver::boxmask(const String& boxmask, 
    1826             :                           const Vector<Int> blc, const Vector<Int> trc,
    1827             :                           const Quantity& fillValue, const Quantity& externalValue)
    1828             : {
    1829           0 :   if(!valid()) return false;
    1830           0 :   LogIO os(LogOrigin("Deconvolver", "boxmask()", WHERE));
    1831             :   
    1832             :   try {
    1833           0 :     if(boxmask=="") {
    1834           0 :       os << LogIO::SEVERE << "Need a name for output boxmask image " << LogIO::POST;
    1835           0 :       return false;
    1836             :     }
    1837           0 :     String boxname(boxmask);
    1838           0 :     if(boxname=="") boxname="boxmask";
    1839           0 :     if(!Table::isWritable(boxname)) {
    1840           0 :       make(boxname);
    1841             :     }
    1842           0 :     PagedImage<Float> boxImage(boxname);
    1843             : 
    1844             :     {
    1845           0 :       ostringstream oos;
    1846           0 :       oos << "BoxMask = "<<boxname<<
    1847           0 :         ", blc = " << blc(0) << " " << blc(1)<<
    1848           0 :         ", trc = " << trc(0) << " " << trc(1);
    1849           0 :       os << String(oos) << LogIO::POST;
    1850             :     }
    1851             : 
    1852           0 :     boxImage.set(externalValue.getValue("Jy"));
    1853             : 
    1854             :     // This only makes a 2-d box; will need to fix this for other
    1855             :     // image sorts
    1856           0 :     uInt dim = boxImage.ndim();
    1857           0 :     IPosition pshape = boxImage.shape();
    1858           0 :     IPosition blc0(dim, 0);
    1859           0 :     IPosition trc0(dim, 0);
    1860           0 :     blc0(0) = max(0, blc(0));
    1861           0 :     blc0(1) = max(0, blc(1));
    1862           0 :     if (trc0(0) == 0) trc0(0) = pshape(0)-1;
    1863           0 :     if (trc0(1) == 0) trc0(1) = pshape(1)-1;    
    1864           0 :     trc0(0) = min(trc(0), pshape(0)-1);
    1865           0 :     trc0(1) = min(trc(1), pshape(1)-1);
    1866           0 :     LCSlicer box(blc0, trc0);
    1867           0 :     SubImage<Float> innerSub(boxImage, ImageRegion(box), true);
    1868           0 :     innerSub.set(fillValue.getValue("Jy"));
    1869           0 :     return true;
    1870           0 :   } catch (AipsError x) {
    1871           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1872             :   }   
    1873           0 :   return true;
    1874             : }
    1875             : 
    1876             : //regionmask
    1877           0 : Bool Deconvolver::regionmask(const String& maskimage, Record* imageRegRec, Matrix<Quantity>& blctrcs, const Float& value){
    1878             :  
    1879           0 :   LogIO os(LogOrigin("deconvolver", "regionmask()", WHERE));
    1880           0 :   if(!dirty_p) {
    1881             :     os << LogIO::SEVERE << "Program logic error: Dirty image pointer dirty_p not yet set"
    1882           0 :        << LogIO::POST;
    1883           0 :     return false;
    1884             :   }
    1885           0 :   if(!Table::isWritable(maskimage)) {
    1886           0 :     if (!clone(dirty_p->name(),maskimage)) return false;
    1887           0 :     PagedImage<Float> mim(maskimage);
    1888           0 :     mim.set(0.0);
    1889           0 :     mim.table().relinquishAutoLocks();
    1890             :   }
    1891           0 :   Matrix<Float> circles;
    1892           0 :   return Imager::regionToImageMask(maskimage, imageRegRec, blctrcs, circles, value);
    1893             : 
    1894             : }
    1895             : 
    1896             : // Fourier transform the model
    1897           0 : Bool Deconvolver::ft(const String& model, const String& transform)
    1898             : {
    1899           0 :   if(!valid()) return false;
    1900             :   
    1901           0 :   LogIO os(LogOrigin("Deconvolver", "ft()", WHERE));
    1902             :   
    1903             :   try {
    1904             :     
    1905           0 :     if(model=="") {
    1906           0 :       os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
    1907           0 :       return false;
    1908             :     }
    1909             :     
    1910           0 :     os << "Fourier transforming model" << LogIO::POST;
    1911             : 
    1912           0 :     String transformname(transform);
    1913           0 :     if(transformname=="") transformname=model+".ft";
    1914           0 :     removeTable(transformname);
    1915             :     
    1916           0 :     PagedImage<Float> modelImage(model);
    1917           0 :     PagedImage<Complex> transformImage(modelImage.shape(),
    1918             :                                        modelImage.coordinates(),
    1919           0 :                                        transformname);
    1920           0 :     transformImage.copyData(LatticeExpr<Complex>(toComplex(modelImage)));
    1921             : 
    1922           0 :     LatticeFFT::cfft2d(transformImage);
    1923             : 
    1924           0 :     return true;
    1925           0 :   } catch (AipsError x) {
    1926           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    1927             :   } 
    1928           0 :   return true;
    1929             : }
    1930             : 
    1931           0 : Bool Deconvolver::setscales(const String& scaleMethod,
    1932             :                             const Int inscales,
    1933             :                             const Vector<Float>& userScaleSizes)
    1934             : {
    1935           0 :   LogIO os(LogOrigin("Deconvolver", "setscales()", WHERE));
    1936             : 
    1937           0 :   AlwaysAssert(!cleaner_p.null(), AipsError);
    1938             : 
    1939           0 :   Vector<Double> cells = psf_p->coordinates().increment();
    1940           0 :   os << "Cell size = " << abs(cells(0)/C::arcsec) << LogIO::POST;
    1941           0 :   AlwaysAssert (cells(0)!=0.0, AipsError);
    1942           0 :   scaleSizes_p.resize();
    1943           0 :   if (scaleMethod == "nscales") {
    1944           0 :     Int nscales=inscales;
    1945             : 
    1946           0 :     if(nscales<1) {
    1947           0 :       os << "Using default of 5 scales" << LogIO::POST;
    1948           0 :       nscales=5;
    1949             :     }
    1950             :   
    1951             :     // Validate scales
    1952           0 :     Float scaleInc=beam_p.getMinor().get("arcsec").getValue()/abs(cells(0)/C::arcsec);
    1953             : 
    1954           0 :     Vector<Float> scaleSizes(nscales);  
    1955             :     os << "Creating " << nscales << 
    1956           0 :       " scales from powerlaw nscales method" << LogIO::POST;
    1957           0 :     scaleSizes(0) = 0.0;
    1958           0 :     os << "scale 1 = 0.0 pixels " << LogIO::POST;
    1959           0 :     for (Int scale=1; scale<nscales;scale++) {
    1960           0 :       scaleSizes(scale) =
    1961           0 :         scaleInc * pow(10.0, (Float(scale)-2.0)/2.0);
    1962           0 :       os << "scale " << scale+1 << " = " << scaleSizes(scale)
    1963           0 :          << " pixels" << LogIO::POST;
    1964             :     }  
    1965           0 :     scaleSizes_p=scaleSizes;
    1966           0 :     cleaner_p->setscales(scaleSizes);   
    1967           0 :     scalesValid_p=true;
    1968             : 
    1969           0 :   } else if (scaleMethod == "uservector") {
    1970           0 :     if (userScaleSizes.nelements() <= 0) {
    1971             :        os << LogIO::SEVERE 
    1972             :           << "Need at least one scale for method uservector"
    1973           0 :           << LogIO::POST;
    1974             :     }
    1975           0 :     os << "Creating scales from uservector method: " << LogIO::POST;
    1976           0 :     for(uInt scale=0; scale < userScaleSizes.nelements(); scale++) {
    1977           0 :       os << "scale " << scale+1 << " = " << userScaleSizes(scale)
    1978           0 :          << " pixels" << LogIO::POST;
    1979             :     }
    1980           0 :     scaleSizes_p=userScaleSizes;
    1981           0 :     cleaner_p->setscales(userScaleSizes);   
    1982           0 :     scalesValid_p=true;
    1983             : 
    1984             :   } else {
    1985             :     os << LogIO::SEVERE << "Unknown scale setting algorithm: " 
    1986           0 :        << scaleMethod << LogIO::POST;
    1987           0 :     return false;
    1988             :   }
    1989             : 
    1990           0 :   return true;
    1991             : }
    1992             :   
    1993           0 : Bool Deconvolver::clone(const String& imageName, const String& newImageName)
    1994             : {
    1995           0 :   if(!valid()) return false;
    1996           0 :   LogIO os(LogOrigin("Deconvolver", "clone()", WHERE));
    1997             :   try {
    1998           0 :     PagedImage<Float> oldImage(imageName);
    1999           0 :     PagedImage<Float> newImage(oldImage.shape(), oldImage.coordinates(),
    2000           0 :                                newImageName);
    2001           0 :   } catch (AipsError x) {
    2002           0 :     os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
    2003           0 :     return false;
    2004             :   } 
    2005           0 :   return true;
    2006             : }
    2007             : 
    2008             : 
    2009             : 
    2010           0 : Bool Deconvolver::convolve(const String& convolvedName, 
    2011             :                            const String& modelName)
    2012             : {
    2013           0 :    PagedImage<Float> model(modelName);
    2014           0 :    PagedImage<Float> convolved(model.shape(),
    2015             :                              model.coordinates(),
    2016           0 :                              convolvedName);
    2017           0 :    convolver_p->linear( convolved, model );
    2018           0 :    return true;
    2019             : };
    2020             : 
    2021           0 : Bool Deconvolver::makegaussian(const String& gaussianName, GaussianBeam& mbeam, Bool normalizeVolume)
    2022             : {
    2023           0 :   LogIO os(LogOrigin("Deconvolver", "makegaussian()", WHERE));
    2024           0 :   if(!dirty_p) {
    2025             :     os << LogIO::SEVERE << "Program logic error: Dirty image pointer dirty_p not yet set"
    2026           0 :        << LogIO::POST;
    2027           0 :     return false;
    2028             :   }
    2029           0 :   PagedImage<Float> gaussian(dirty_p->shape(),
    2030           0 :                              dirty_p->coordinates(),
    2031           0 :                              gaussianName);
    2032           0 :   gaussian.set(0.0);
    2033           0 :   gaussian.setUnits(Unit("Jy/pixel"));
    2034           0 :   putGaussian(gaussian, mbeam);
    2035           0 :   if(!normalizeVolume){
    2036           0 :     Float maxpsf=max(gaussian).getFloat();
    2037           0 :     gaussian.copyData((LatticeExpr<Float>)(gaussian/maxpsf));
    2038             :   }
    2039             :   //uInt naxis=gaussian.shape().nelements();
    2040             :   // StokesImageUnil::Convolve requires an image with four axes
    2041             :   /* 
    2042             :   if(naxis==2){
    2043             :     IPosition center = gaussian.shape()/2;
    2044             :     gaussian.putAt(1.0, center);
    2045             :   }
    2046             :   else if(naxis==3){
    2047             :     IPosition center(3, Int((nx_p/4)*2), Int((ny_p/4)*2),0);
    2048             :     for (Int k=0; k < gaussian.shape()(2); ++k){
    2049             :       center(2) = k;
    2050             :       gaussian.putAt(1.0, center);
    2051             :     }
    2052             :   }
    2053             :   */
    2054             :   /*  if(naxis<4){
    2055             :     os << LogIO::SEVERE << "Input dirty image: naxis=" <<naxis
    2056             :        << ". Four axes are required."<< LogIO::POST;
    2057             :     return false;
    2058             : 
    2059             :   }
    2060             :   else if(naxis==4){
    2061             :     IPosition center(4, Int((nx_p/4)*2), Int((ny_p/4)*2),0,0);
    2062             :     for (Int k=0; k < gaussian.shape()(2); ++k){
    2063             :       
    2064             :       center(2) = k;
    2065             :       for(Int j=0; j < gaussian.shape()(3); ++j){
    2066             :         center(3)=j;
    2067             :         gaussian.putAt(1.0, center);
    2068             :       }
    2069             :     }
    2070             : 
    2071             : 
    2072             :   }
    2073             :   StokesImageUtil::Convolve(gaussian, mbeam, normalizeVolume);
    2074             :   */
    2075           0 :   return true;
    2076             : };
    2077             : 
    2078           0 : Bool Deconvolver::putGaussian(ImageInterface<Float>& im, const GaussianBeam& beam){
    2079           0 :   CoordinateSystem cs=im.coordinates();
    2080             :   
    2081           0 :   Vector<Int> dirAxes=CoordinateUtil::findDirectionAxes(cs);
    2082           0 :   DirectionCoordinate dirCoord=cs.directionCoordinate(cs.findCoordinate(Coordinate::DIRECTION));
    2083           0 :   Vector<Double> cenpix(2, Double(nx_p)/2.0);
    2084           0 :   cenpix(1)=Double(ny_p)/2.0;
    2085           0 :   MDirection centre;
    2086           0 :   dirCoord.toWorld(centre, cenpix);
    2087           0 :   MVAngle mvRA=centre.getAngle().getValue()(0);
    2088           0 :   MVAngle mvDEC=centre.getAngle().getValue()(1);
    2089             :   //cerr << "centre " << cenpix <<  "   " << centre.getRefString() << " " << mvRA(0.0).string(MVAngle::TIME,8)  << " " <<  mvDEC(0.0).string(MVAngle::ANGLE_CLEAN,8) << endl;
    2090             :   //cerr << "maj min pa " << beam.getMajor() << "   " <<  beam.getMinor() << "   " <<  beam.getPA() << endl;
    2091           0 :   GaussianShape gshp(centre, beam.getMajor(), beam.getMinor(), beam.getPA());
    2092           0 :   SkyComponent gcomp(Flux<Double>(1.0), gshp, ConstantSpectrum());
    2093           0 :   ComponentList cl;
    2094           0 :   cl.add(gcomp);
    2095           0 :   ComponentImager::project(im, cl);
    2096           0 :   return true;
    2097             :   
    2098             : 
    2099             : 
    2100             : }
    2101             : 
    2102             : 
    2103           0 : Bool Deconvolver::detached() const
    2104             : {
    2105           0 :   if (dirty_p == 0) {
    2106           0 :     LogIO os(LogOrigin("Deconvolver", "detached()", WHERE));
    2107             :     os << LogIO::SEVERE << 
    2108             :       "Deconvolver is detached - cannot perform operation." << endl <<
    2109           0 :       "Call Deconvolver.open('dirtyname', 'psfname') to reattach." << LogIO::POST;
    2110           0 :     return true;
    2111             :   }
    2112           0 :   return false;
    2113             : }
    2114             : 
    2115           0 : Bool Deconvolver::removeTable(const String& tablename) {
    2116             :   
    2117           0 :   LogIO os(LogOrigin("Deconvolver", "removeTable()", WHERE));
    2118             :   
    2119           0 :   if(Table::isReadable(tablename)) {
    2120           0 :     if (! Table::isWritable(tablename)) {
    2121             :       os << LogIO::SEVERE << "Table " << tablename
    2122           0 :          << " is not writable!: cannot alter it" << LogIO::POST;
    2123           0 :       return false;
    2124             :     }
    2125             :     else {
    2126           0 :       if (Table::isOpened(tablename)) {
    2127             :         os << LogIO::SEVERE << "Table " << tablename
    2128             :            << " is already open in the process. It needs to be closed first"
    2129           0 :            << LogIO::POST;
    2130           0 :           return false;
    2131             :       } else {
    2132           0 :         Table table(tablename, Table::Update);
    2133           0 :         if (table.isMultiUsed()) {
    2134             :           os << LogIO::SEVERE << "Table " << tablename
    2135             :              << " is already open in another process. It needs to be closed first"
    2136           0 :              << LogIO::POST;
    2137           0 :             return false;
    2138             :         } else {
    2139           0 :           Table table(tablename, Table::Delete);
    2140             :         }
    2141             :       }
    2142             :     }
    2143             :   }
    2144           0 :   return true;
    2145             : }
    2146             : 
    2147           0 : Bool Deconvolver::valid() const {
    2148           0 :   LogIO os(LogOrigin("Deconvolver", "if(!valid()) return false", WHERE));
    2149           0 :   if(!dirty_p) {
    2150             :     os << LogIO::SEVERE << "Program logic error: Dirty image pointer dirty_p not yet set"
    2151           0 :        << LogIO::POST;
    2152           0 :     return false;
    2153             :   }
    2154           0 :   if(!psf_p) {
    2155             :     os << LogIO::SEVERE << "Program logic error: PSF  pointer psf_p not yet set"
    2156           0 :        << LogIO::POST;
    2157           0 :     return false;
    2158             :   }
    2159           0 :   return true;
    2160             : }
    2161             : 
    2162           0 : void Deconvolver::findAxes(){
    2163             : 
    2164           0 :   CoordinateSystem coordsys= dirty_p->coordinates();
    2165           0 :   polAxis_p=coordsys.findCoordinate(Coordinate::STOKES);
    2166           0 :   if(polAxis_p > coordsys.findCoordinate(Coordinate::DIRECTION))
    2167           0 :     polAxis_p+=1;
    2168           0 :   chanAxis_p=coordsys.findCoordinate(Coordinate::SPECTRAL);
    2169           0 :   if(chanAxis_p > coordsys.findCoordinate(Coordinate::DIRECTION))
    2170           0 :     chanAxis_p+=1;
    2171             :   
    2172           0 : }
    2173             : 
    2174           0 : void Deconvolver::checkMask(ImageInterface<Float>& maskImage, Int& xbeg, Int& xend, 
    2175             :                             Int& ybeg, Int& yend){
    2176             :  
    2177             : 
    2178           0 :   LogIO os(LogOrigin("Deconvolver","checkMask",WHERE)); 
    2179             : 
    2180           0 :   xbeg=nx_p/4;
    2181           0 :   ybeg=ny_p/4;
    2182             :   
    2183           0 :   xend=xbeg+nx_p/2-1;
    2184           0 :   yend=ybeg+ny_p/2-1;  
    2185           0 :   Slicer sl;
    2186           0 :   if(nchan_p >= 1){
    2187             :     
    2188           0 :     if(npol_p > 0 ){
    2189           0 :       IPosition blc(4,0,0,0,0);
    2190           0 :       blc(chanAxis_p)=0;
    2191           0 :       blc(polAxis_p)=0;
    2192           0 :       IPosition trc(4, nx_p-1, ny_p-1, 0, 0);
    2193           0 :       trc(chanAxis_p)=0;
    2194           0 :       trc(polAxis_p)=0;
    2195           0 :       sl=Slicer(blc, trc, Slicer::endIsLast);
    2196             :     }
    2197             :     else{
    2198           0 :       IPosition blc(3, 0, 0, 0);
    2199           0 :       IPosition trc(3, nx_p-1, ny_p-1, 0);
    2200           0 :       sl=Slicer(blc, trc, Slicer::endIsLast);
    2201             :     }
    2202             :   }
    2203             :   else{
    2204           0 :     if(npol_p > 0 ){
    2205           0 :       IPosition blc(3, 0, 0, 0);
    2206           0 :       IPosition trc(3, nx_p-1, ny_p-1, 0);
    2207           0 :       sl=Slicer(blc, trc, Slicer::endIsLast);
    2208             :     }
    2209             :     else{
    2210           0 :        IPosition blc(2, 0, 0);
    2211           0 :        IPosition trc(2, nx_p-1, ny_p-1);
    2212             :     }
    2213             :   }
    2214             : 
    2215             : 
    2216           0 :   Matrix<Float> mask= maskImage.getSlice(sl, true);
    2217             :   // ignore mask if none exists
    2218           0 :   if(max(mask) < 0.000001) {
    2219             :     os << "Mask seems to be empty; will CLEAN inner quarter" 
    2220           0 :        << LogIO::WARN;
    2221           0 :     return;
    2222             :   }
    2223             :   // Now read the mask and determine the bounding box
    2224             : 
    2225           0 :   xbeg=nx_p-1;
    2226           0 :   ybeg=ny_p-1;
    2227           0 :   xend=0;
    2228           0 :   yend=0;
    2229             : 
    2230             :   
    2231           0 :   for (Int iy=0;iy<ny_p;iy++) {
    2232           0 :     for (Int ix=0;ix<nx_p;ix++) {
    2233           0 :       if(mask(ix,iy)>0.000001) {
    2234           0 :         xbeg=min(xbeg,ix);
    2235           0 :         ybeg=min(ybeg,iy);
    2236           0 :         xend=max(xend,ix);
    2237           0 :         yend=max(yend,iy);
    2238             : 
    2239             :       }
    2240             :     }
    2241             :   }
    2242             :   // Now have possible BLC. Make sure that we don't go over the
    2243             :   // edge later
    2244           0 :   if(((xend - xbeg)>nx_p/2) && (!fullPlane_p)) {
    2245           0 :     xbeg=nx_p/4-1; //if larger than quarter take inner of mask
    2246           0 :     os << LogIO::WARN << "Mask span over more than half the x-axis: Considering inner half of the x-axis"  << LogIO::POST;
    2247             :   } 
    2248           0 :   if(((yend - ybeg)>ny_p/2) && (!fullPlane_p)) { 
    2249           0 :     ybeg=ny_p/4-1;
    2250           0 :     os << LogIO::WARN << "Mask span over more than half the y-axis: Considering inner half of the y-axis" << LogIO::POST;
    2251             :   }  
    2252             : 
    2253             :   // Just making sure we are within limits...
    2254           0 :   if(fullPlane_p){
    2255           0 :     xend=min(xend,nx_p-1);
    2256           0 :     yend=min(yend,ny_p-1);
    2257             :   }
    2258             :   else{
    2259           0 :     xend=min(xend,xbeg+nx_p/2-1);
    2260           0 :     yend=min(yend,ybeg+ny_p/2-1); 
    2261             :   }
    2262             : 
    2263             : 
    2264             : 
    2265             : }
    2266             : 
    2267             : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2268             : // Multi-Term Clean algorithm with Taylor-Polynomial basis functions
    2269             : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2270           0 : Bool Deconvolver::mtopen(const Int nTaylor,
    2271             :                          const Vector<Float>& userScaleSizes,
    2272             :                          const Vector<String>& psfs)
    2273             : {
    2274             :   
    2275             :   //  if(!valid()) return false; //make MT version
    2276           0 :   LogIO os(LogOrigin("Deconvolver", "mtopen()", WHERE));
    2277             : 
    2278             :   // Check for already-open mt-deconvolver
    2279             :   
    2280           0 :   if(mt_nterms_p != -1)
    2281             :     {
    2282           0 :       os << LogIO::WARN << "Multi-term Deconvolver is already open, and set-up for " << mt_nterms_p << " Taylor-terms. Please close the deconvolver and reopen, or continue with cleaning." << LogIO::POST;
    2283           0 :       return false;
    2284             :     }
    2285             : 
    2286             :   // Check for valid ntaylor
    2287           0 :   if( nTaylor <=0 ) 
    2288             :     {
    2289           0 :       os << LogIO::SEVERE << "nTaylor must be at-least 1" << LogIO::POST; 
    2290           0 :       return false;
    2291             :     }
    2292             : 
    2293           0 :   mt_nterms_p = nTaylor;
    2294           0 :   uInt mt_npsftaylor = 2*nTaylor-1;
    2295             : 
    2296             :   // Check if the correct number of PSFs exist.
    2297           0 :   if( psfs.nelements() != mt_npsftaylor )
    2298             :     {
    2299           0 :       os << LogIO::SEVERE << "For " << mt_nterms_p << " Taylor terms, " << mt_npsftaylor << " PSFs are needed to populate the Hessian matrix. " << LogIO::POST;
    2300           0 :       return false;
    2301             :     }
    2302             : 
    2303           0 :   os << "Initializing MT-Clean with " << mt_nterms_p << " Taylor terms, " << userScaleSizes.nelements() << " scales and " << psfs.nelements() << " unique Hessian elements (psfs)" << LogIO::POST;
    2304             : 
    2305             :   // Open all the PSFs...
    2306           0 :   Block<CountedPtr<PagedImage<Float> > > mt_psfs(mt_npsftaylor);
    2307             : 
    2308             :   // Open the first PSF and extract shape info.
    2309           0 :   mt_psfs[0] = new PagedImage<Float>(psfs[0]);
    2310           0 :   AlwaysAssert(&*mt_psfs[0], AipsError);
    2311           0 :   nx_p=mt_psfs[0]->shape()(0);
    2312           0 :   ny_p=mt_psfs[0]->shape()(1);
    2313             :   //mt_psfs_p[0].setMaximumCacheSize(2*nx_p*ny_p);
    2314             :   //mt_psfs_p[0].setCacheSizeInTiles(10000);
    2315             : 
    2316             :   // Open the other PSFs and verify shape consistency
    2317           0 :   for(uInt i=1; i<mt_npsftaylor;i++)
    2318             :     {
    2319           0 :       mt_psfs[i] = new PagedImage<Float>(psfs[i]);
    2320           0 :       AlwaysAssert(&*mt_psfs[i], AipsError);
    2321           0 :       if( mt_psfs[i]->shape()(0) != nx_p || mt_psfs[i]->shape()(1) != ny_p )
    2322             :         {
    2323           0 :           os << LogIO::SEVERE << "Supplied PSFs are of different shapes. Please try again." << LogIO::POST;
    2324           0 :           mt_psfs.resize(0); // Not sure if this is safe, with CountedPtrs. WARN.
    2325           0 :           return false;
    2326             :         }
    2327             :     }
    2328             : 
    2329             :   // Initialize the Multi-Term Cleaner
    2330             :   try
    2331             :     {
    2332           0 :       mt_cleaner_p.setntaylorterms(mt_nterms_p);
    2333           0 :       mt_cleaner_p.setscales(userScaleSizes);
    2334           0 :       mt_cleaner_p.initialise(nx_p,ny_p); // allocates memory once....
    2335             :     }
    2336           0 :   catch (AipsError x) 
    2337             :     {
    2338             :       os << LogIO::WARN << "Cannot allocate required memory for Multi-Term minor cycle" 
    2339           0 :        << LogIO::POST;
    2340           0 :       return false;
    2341             :     } 
    2342             : 
    2343             :   // Send the PSFs into the Multi-Term Matrix Cleaner
    2344           0 :   for (uInt order=0;order<mt_npsftaylor;order++)
    2345             :     {
    2346           0 :       Matrix<Float> tempMat;
    2347           0 :       Array<Float> tempArr;
    2348           0 :       (mt_psfs[order])->get(tempArr,true); // by reference.
    2349           0 :       tempMat.reference(tempArr);
    2350             : 
    2351           0 :       mt_cleaner_p.setpsf( order , tempMat ); 
    2352             :     }
    2353             : 
    2354             :   // Compute Hessian elements for Taylor terms and Scales ( convolutions ), take the Hessian block-diagonal approximation and inverse, Check for invertability.
    2355           0 :   Int ret = mt_cleaner_p.computeHessianPeak();
    2356           0 :   if (ret != 0)
    2357             :     {
    2358           0 :       os << LogIO::SEVERE << "Cannot Invert Hessian matrix. Please close the deconvolver and supply different PSFs." << LogIO::POST; 
    2359           0 :       return false;
    2360             :     }
    2361             : 
    2362             :   // mt_psfs goes out of scope and CountedPtrs delete themselves automatically.
    2363             : 
    2364           0 :   mt_valid_p=true;
    2365             :   
    2366           0 :   return true;
    2367             : }
    2368             : 
    2369           0 : Bool Deconvolver::mtclean(const Vector<String>& residuals,
    2370             :                           const Vector<String>& models,
    2371             :                           const Int niter,
    2372             :                           const Float gain, 
    2373             :                           const Quantity& threshold, 
    2374             :                           const Bool /*displayProgress*/,
    2375             :                           const String& mask, 
    2376             :                           Float& maxResidual, Int& iterationsDone)
    2377             : {
    2378             :   
    2379           0 :   LogIO os(LogOrigin("Deconvolver", "mtclean()", WHERE));
    2380             : 
    2381           0 :   if(mt_valid_p==false)
    2382             :     {
    2383           0 :       os << LogIO::WARN << "Multi-Term Deconvolver is not initialized yet. Please call 'mtopen()' first" << LogIO::POST;
    2384           0 :       return false;
    2385             :     }
    2386             : 
    2387           0 :   os << "Running MT-Clean with " << mt_nterms_p << " Taylor terms " << LogIO::POST;
    2388             : 
    2389             :   // Send in the mask.
    2390           0 :   if( mask != String("") )
    2391             :     {
    2392           0 :       PagedImage<Float> mt_mask(mask);
    2393           0 :       Matrix<Float> tempMat;
    2394           0 :       Array<Float> tempArr;
    2395           0 :       (mt_mask).get(tempArr,true);
    2396           0 :       tempMat.reference(tempArr);
    2397             :       
    2398           0 :       mt_cleaner_p.setmask( tempMat );
    2399             :     }
    2400             : 
    2401             :   // Send in the residuals and model images.
    2402           0 :   Block<CountedPtr<PagedImage<Float> > > mt_residuals(mt_nterms_p);
    2403           0 :   Block<CountedPtr<PagedImage<Float> > > mt_models(mt_nterms_p);
    2404           0 :   for (Int i=0;i<mt_nterms_p;i++)
    2405             :     {
    2406           0 :       mt_residuals[i] = new PagedImage<Float>(residuals[i]);
    2407           0 :       AlwaysAssert(&*mt_residuals[i], AipsError);
    2408           0 :       if( mt_residuals[i]->shape()(0) != nx_p || mt_residuals[i]->shape()(1) != ny_p )
    2409             :         {
    2410           0 :           os << LogIO::SEVERE << "Supplied Residual images don't match PSF shapes." << LogIO::POST;
    2411           0 :           mt_residuals.resize(0); // Not sure if this is safe, with CountedPtrs. WARN.
    2412           0 :           return false;
    2413             :         }
    2414             : 
    2415           0 :       mt_models[i] = new PagedImage<Float>(models[i]);
    2416           0 :       AlwaysAssert(&*mt_models[i], AipsError);
    2417           0 :       if( mt_models[i]->shape()(0) != nx_p || mt_models[i]->shape()(1) != ny_p )
    2418             :         {
    2419           0 :           os << LogIO::SEVERE << "Supplied Model images don't match PSF shapes." << LogIO::POST;
    2420           0 :           mt_models.resize(0); // Not sure if this is safe, with CountedPtrs. WARN.
    2421           0 :           return false;
    2422             :         }
    2423             : 
    2424             : 
    2425           0 :       Matrix<Float> tempMat;
    2426           0 :       Array<Float> tempArr;
    2427             : 
    2428           0 :       (mt_residuals[i])->get(tempArr,true); // by reference.
    2429           0 :       tempMat.reference(tempArr);
    2430           0 :       mt_cleaner_p.setresidual( i , tempMat ); 
    2431             : 
    2432           0 :       (mt_models[i])->get(tempArr,true); // by reference.
    2433           0 :       tempMat.reference(tempArr);
    2434           0 :       mt_cleaner_p.setmodel( i , tempMat ); 
    2435             : 
    2436             :     } // end of for i 
    2437             : 
    2438             : 
    2439             :   // Fill in  maxResidual and iterationsDone
    2440             : 
    2441           0 :   Float fractionOfPsf=0.05;
    2442             :   
    2443             :   // Call the cleaner
    2444           0 :   iterationsDone = mt_cleaner_p.mtclean(niter, fractionOfPsf, gain, threshold.getValue(String("Jy")));
    2445             : 
    2446             :   // Get back the model (this is not held in MTMC by reference, because of 'incremental=T/F' logic....
    2447           0 :   for (Int order=0;order<mt_nterms_p;order++)
    2448             :     {
    2449           0 :       Matrix<Float> tempMod;
    2450           0 :       mt_cleaner_p.getmodel(order,tempMod);
    2451           0 :       mt_models[order]->put(tempMod);
    2452             : 
    2453             :       // Also get the updated residuals. Not really needed, but good to have.
    2454           0 :       mt_cleaner_p.getresidual(order,tempMod);
    2455           0 :       mt_residuals[order]->put(tempMod);
    2456             : 
    2457           0 :       if(order==0) maxResidual = max(fabs(tempMod));
    2458             : 
    2459             :     }           
    2460             : 
    2461           0 :   return maxResidual <= threshold.getValue(String("Jy"));
    2462             : }
    2463             : 
    2464             : 
    2465           0 : Bool Deconvolver::mtrestore(const Vector<String>& models,
    2466             :                           const Vector<String>& residuals,
    2467             :                           const Vector<String>& images,
    2468             :                           GaussianBeam& mbeam)
    2469             : {
    2470             : 
    2471           0 :   LogIO os(LogOrigin("Deconvolver", "mtrestore()", WHERE));
    2472             : 
    2473             :   // check that the mt_cleaner_p is alive..
    2474           0 :   if(mt_valid_p==false)
    2475             :     {
    2476           0 :       os << LogIO::WARN << "Multi-Term Deconvolver is not initialized yet. Please call 'mtopen()' first" << LogIO::POST;
    2477           0 :       return false;
    2478             :     }
    2479             :   
    2480           0 :   os << "Restoring Taylor-coefficient images" << LogIO::POST;
    2481             : 
    2482           0 :   Block<CountedPtr<PagedImage<Float> > > mt_residuals(mt_nterms_p);
    2483           0 :   for (Int i=0;i<mt_nterms_p;i++)
    2484             :     {
    2485           0 :       mt_residuals[i] = new PagedImage<Float>(residuals[i]);
    2486           0 :       AlwaysAssert(&*mt_residuals[i], AipsError);
    2487           0 :       if( mt_residuals[i]->shape()(0) != nx_p || mt_residuals[i]->shape()(1) != ny_p )
    2488             :         {
    2489           0 :           os << LogIO::SEVERE << "Supplied Residual images don't match PSF shapes." << LogIO::POST;
    2490           0 :           mt_residuals.resize(0); // Not sure if this is safe, with CountedPtrs. WARN.
    2491           0 :           return false;
    2492             :         }
    2493             :     }
    2494             : 
    2495             :   // Calculate principal solution on the residuals.
    2496             :   //// Send in new residuals
    2497           0 :   for (Int order=0;order<mt_nterms_p;order++)
    2498             :     {
    2499           0 :       Matrix<Float> tempMat;
    2500           0 :       Array<Float> tempArr;
    2501           0 :       (mt_residuals[order])->get(tempArr,true); // by reference.
    2502           0 :       tempMat.reference(tempArr);
    2503           0 :       mt_cleaner_p.setresidual( order , tempMat ); 
    2504             :     }           
    2505             : 
    2506             :   //// Compute p-soln
    2507           0 :   mt_cleaner_p.computeprincipalsolution();
    2508             : 
    2509             :   //// Get residuals out
    2510           0 :   for (Int order=0;order<mt_nterms_p;order++)
    2511             :     {
    2512           0 :       Matrix<Float> tempMat;
    2513           0 :       Matrix<Float> tempMod;
    2514           0 :       mt_cleaner_p.getresidual(order,tempMod);
    2515           0 :       mt_residuals[order]->put(tempMod);
    2516             :     }
    2517             : 
    2518             :   // Convolve models with the clean beam and add new residuals.... per term
    2519           0 :   for (Int order=0;order<mt_nterms_p;order++)
    2520             :     {
    2521           0 :       PagedImage<Float> thismodel(models[order]);
    2522           0 :       PagedImage<Float> thisimage( thismodel.shape(), thismodel.coordinates(), images[order]);
    2523             : 
    2524           0 :       LatticeExpr<Float> cop(thismodel);
    2525           0 :       thisimage.copyData(cop);
    2526             : 
    2527           0 :       StokesImageUtil::Convolve(thisimage, mbeam);
    2528             : 
    2529           0 :       LatticeExpr<Float> le(thisimage+( *mt_residuals[order] )); 
    2530           0 :       thisimage.copyData(le);
    2531             : 
    2532           0 :       ImageInfo ii = thisimage.imageInfo();
    2533           0 :       ii.setRestoringBeam(mbeam);
    2534           0 :       thisimage.setImageInfo(ii);
    2535           0 :       thisimage.setUnits(Unit("Jy/beam"));
    2536           0 :       thisimage.table().unmarkForDelete();
    2537             : 
    2538             :     }
    2539             : 
    2540           0 :   return true;
    2541             : }
    2542             : 
    2543             : // This code duplicates WBCleanImageSkyModel::calculateAlphaBeta
    2544             : // Eventually, This Deconvolver code will replace what's in WBCleanImageSkyModel.cc
    2545             : //  This function must be callable stand-alone, and must not use private vars.
    2546             : //      This is to allow easy recalculation of alpha with different thresholds
    2547           0 : Bool Deconvolver::mtcalcpowerlaw(const Vector<String>& images,
    2548             :                                  const Vector<String>& residuals,
    2549             :                                  const String& alphaname,
    2550             :                                  const String& betaname,
    2551             :                                  const Quantity& threshold,
    2552             :                                  const Bool calcerror)
    2553             : {
    2554           0 :   LogIO os(LogOrigin("Deconvolver", "mtcalcpowerlaw()", WHERE));
    2555             : 
    2556           0 :   uInt ntaylor = images.nelements();
    2557             : 
    2558           0 :   if(ntaylor<2)
    2559             :     {
    2560           0 :       os << LogIO::SEVERE << "Please enter at-least two Taylor-coefficient images" << LogIO::POST;
    2561           0 :       return false;
    2562             :     }
    2563             :   else
    2564             :     {
    2565             : 
    2566             :       // Check that the images exist on disk
    2567             : 
    2568           0 :       os << "Calculating spectral index";
    2569           0 :       if(ntaylor>3) os << " and spectral curvature";
    2570           0 :       os << " from " << ntaylor << " restored images, using a mask defined by a threshold of " << threshold.getValue(String("Jy")) << " Jy " << LogIO::POST;
    2571             :     }
    2572             :   
    2573             :   // Open restored images 
    2574           0 :   PagedImage<Float> imtaylor0(images[0]);
    2575           0 :   PagedImage<Float> imtaylor1(images[1]);
    2576             : 
    2577             :   // Check shapes
    2578           0 :   if( imtaylor0.shape() != imtaylor1.shape() )
    2579             :     {
    2580           0 :       os << LogIO::SEVERE << "Taylor-coefficient image shapes must match." << LogIO::POST;
    2581           0 :       return false;
    2582             :     }
    2583             : 
    2584             :   // Create empty alpha image
    2585           0 :   PagedImage<Float> imalpha(imtaylor0.shape(),imtaylor0.coordinates(),alphaname); 
    2586           0 :   imalpha.set(0.0);
    2587             : 
    2588           0 :   Float specthreshold = threshold.getValue(String("Jy"));
    2589             :   
    2590             :   // Create a mask - make this adapt to the signal-to-noise 
    2591           0 :   LatticeExpr<Float> mask1(iif((imtaylor0)>(specthreshold),1.0,0.0));
    2592           0 :   LatticeExpr<Float> mask0(iif((imtaylor0)>(specthreshold),0.0,1.0));
    2593             : 
    2594             :   /////// Calculate alpha
    2595           0 :   LatticeExpr<Float> alphacalc( ((imtaylor1)*mask1)/((imtaylor0)+(mask0)) );
    2596           0 :   imalpha.copyData(alphacalc);
    2597             : 
    2598             :   // Set the restoring beam for alpha
    2599           0 :   ImageInfo ii = imalpha.imageInfo();
    2600           0 :   ii.setRestoringBeam( (imtaylor0.imageInfo()).restoringBeam() );
    2601           0 :   imalpha.setImageInfo(ii);
    2602             :   //imalpha.setUnits(Unit("Spectral Index"));
    2603           0 :   imalpha.table().unmarkForDelete();
    2604             : 
    2605             :   // Make a mask for the alpha image
    2606           0 :   LatticeExpr<Bool> lemask(iif((imtaylor0 > specthreshold) , true, false));
    2607             : 
    2608           0 :   createMask(lemask, imalpha);
    2609           0 :   os << "Written Spectral Index Image : " << alphaname << LogIO::POST;
    2610             : 
    2611             : 
    2612             :   ////// Calculate error on alpha, if requested.
    2613           0 :   if(calcerror)
    2614             :     {
    2615           0 :       if( residuals.nelements() != ntaylor )
    2616             :         {
    2617           0 :           os << LogIO::WARN << "Number of residual images is different from number of restored images. Not calculating alpha-error map." << LogIO::POST;
    2618             :         }
    2619             :       else
    2620             :         {
    2621           0 :           PagedImage<Float> imalphaerror(imtaylor0.shape(),imtaylor0.coordinates(),alphaname+String(".error")); 
    2622           0 :           imalphaerror.set(0.0);
    2623             :           
    2624             :           /* Open residual images */
    2625           0 :           PagedImage<Float> residual0(residuals[0]);
    2626           0 :           PagedImage<Float> residual1(residuals[1]);
    2627             : 
    2628           0 :           if( residual0.shape() != residual1.shape() || residual0.shape() != imtaylor0.shape() )
    2629             :             {
    2630           0 :               os << LogIO::WARN << "Shapes of residual images (and/or restored images) do not match. Not calculating alpha-error map." << LogIO::POST;
    2631             :             }
    2632             :           else
    2633             :             {
    2634           0 :               LatticeExpr<Float> alphacalcerror( abs(alphacalc) * sqrt( ( (residual0*mask1)/(imtaylor0+mask0) )*( (residual0*mask1)/(imtaylor0+mask0) ) + ( (residual1*mask1)/(imtaylor1+mask0) )*( (residual1*mask1)/(imtaylor1+mask0) )  ) );
    2635           0 :               imalphaerror.copyData(alphacalcerror);
    2636           0 :               imalphaerror.setImageInfo(ii);
    2637           0 :               createMask(lemask, imalphaerror);
    2638           0 :               imalphaerror.table().unmarkForDelete();      
    2639           0 :               os << "Written Spectral Index Error Image : " << alphaname << ".error" << LogIO::POST;
    2640             :               
    2641             :               //          mergeDataError( imalpha, imalphaerror, alphaerrorname+".new" );
    2642             :             }
    2643             : 
    2644             :         }
    2645             : 
    2646             :     }// end if calcerror
    2647             : 
    2648             :   ////// Calculate beta, if enough images are given.
    2649           0 :   if(ntaylor>2)
    2650             :     {
    2651           0 :       PagedImage<Float> imbeta(imtaylor0.shape(),imtaylor0.coordinates(),betaname); 
    2652           0 :       imbeta.set(0.0);
    2653           0 :       PagedImage<Float> imtaylor2(images[2]);
    2654           0 :       if( imtaylor2.shape() != imtaylor0.shape() )
    2655             :         {
    2656           0 :           os << LogIO::WARN << "Restored image shapes do not match. Not calculating 'beta'" << LogIO::POST;
    2657             :         }
    2658             :       else
    2659             :         {
    2660           0 :           LatticeExpr<Float> betacalc( ((imtaylor2)*mask1)/((imtaylor0)+(mask0))-0.5*(imalpha)*(imalpha-1.0) );
    2661           0 :           imbeta.copyData(betacalc);
    2662           0 :           imbeta.setImageInfo(ii);
    2663             :           //imbeta.setUnits(Unit("Spectral Curvature"));
    2664           0 :           createMask(lemask, imbeta);
    2665           0 :           imbeta.table().unmarkForDelete();
    2666             :           
    2667           0 :           os << "Written Spectral Curvature Image : " << betaname << LogIO::POST;
    2668             :         }
    2669             :     }
    2670             :   
    2671           0 :   return true;
    2672             : }
    2673             : 
    2674             : // This is also a copy of WBCleanImageSkyModel::createMask
    2675             : // Eventually, WBCleanImageSkyModel must use this Deconvolver version.
    2676           0 : Bool Deconvolver::createMask(LatticeExpr<Bool> &lemask, ImageInterface<Float> &outimage)
    2677             : {
    2678           0 :       ImageRegion outreg = outimage.makeMask("mask0",false,true);
    2679           0 :       LCRegion& outmask=outreg.asMask();
    2680           0 :       outmask.copyData(lemask);
    2681           0 :       outimage.defineRegion("mask0",outreg, RegionHandler::Masks, true);
    2682           0 :       outimage.setDefaultMask("mask0");
    2683           0 :       return true;
    2684             : }
    2685             : 
    2686             : 
    2687             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16