LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SIImageStore.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 1209 1731 69.8 %
Date: 2025-12-19 19:56:21 Functions: 77 103 74.8 %

          Line data    Source code
       1             : //# SIImageStore.cc: Implementation of Imager.h
       2             : //# Copyright (C) 1997-2008
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This program is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU General Public License as published by the Free
       7             : //# Software Foundation; either version 2 of the License, or (at your option)
       8             : //# any later version.
       9             : //#
      10             : //# This program 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 General Public License for
      13             : //# more details.
      14             : //#
      15             : //# You should have received a copy of the GNU General Public License along
      16             : //# with this program; if not, write to the Free Software Foundation, Inc.,
      17             : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : 
      28             : #include <casacore/casa/Exceptions/Error.h>
      29             : #include <iostream>
      30             : #include <sstream>
      31             : 
      32             : #include <casacore/casa/Arrays/Matrix.h>
      33             : #include <casacore/casa/Arrays/ArrayMath.h>
      34             : #include <casacore/casa/Arrays/ArrayLogical.h>
      35             : 
      36             : #include <casacore/casa/Logging.h>
      37             : #include <casacore/casa/Logging/LogIO.h>
      38             : #include <casacore/casa/Logging/LogMessage.h>
      39             : #include <casacore/casa/Logging/LogSink.h>
      40             : #include <casacore/casa/Logging/LogMessage.h>
      41             : #include <casacore/casa/OS/DirectoryIterator.h>
      42             : #include <casacore/casa/OS/File.h>
      43             : #include <casacore/casa/OS/Path.h>
      44             : #include <casacore/lattices/Lattices/LatticeLocker.h>
      45             : #include <casacore/casa/OS/HostInfo.h>
      46             : #include <components/ComponentModels/GaussianDeconvolver.h>
      47             : #include <casacore/images/Images/TempImage.h>
      48             : #include <casacore/images/Images/PagedImage.h>
      49             : #include <imageanalysis/ImageAnalysis/CasaImageBeamSet.h>
      50             : #include <casacore/lattices/LatticeMath/LatticeMathUtil.h>
      51             : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
      52             : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
      53             : #include <casacore/tables/Tables/TableUtil.h>
      54             : 
      55             : #include <synthesis/ImagerObjects/SIImageStore.h>
      56             : #include <synthesis/ImagerObjects/SDMaskHandler.h>
      57             : #include <synthesis/TransformMachines/StokesImageUtil.h>
      58             : #include <synthesis/TransformMachines2/Utils.h>
      59             : #include <synthesis/ImagerObjects/SynthesisUtilMethods.h>
      60             : #include <casacore/images/Images/ImageRegrid.h>
      61             : #include <imageanalysis/ImageAnalysis/ImageStatsCalculator.h>
      62             : 
      63             : //#include <imageanalysis/ImageAnalysis/ImageMaskedPixelReplacer.h>
      64             : 
      65             : #include <sys/types.h>
      66             : #include <unistd.h>
      67             : #include "SIImageStore.h"
      68             : using namespace std;
      69             : 
      70             : using namespace casacore;
      71             : 
      72             : namespace casa { //# NAMESPACE CASA - BEGIN
      73             : 
      74             :   //
      75             :   //===========================================================================
      76             :   // Global method that I (SB) could make work in SynthesisUtilsMethods.
      77             :   //
      78             :   template <class T>
      79           0 :   void openImage(const String& imagenamefull,std::shared_ptr<ImageInterface<T> >& imPtr )
      80             :   {
      81           0 :     LogIO logIO ( LogOrigin("SynthesisImager","openImage(name)") );
      82             :     try
      83             :       {
      84           0 :         if (Table::isReadable(imagenamefull))
      85           0 :           imPtr.reset( new PagedImage<T>( imagenamefull ) );
      86             :       }
      87           0 :     catch (AipsError &x)
      88             :       {
      89           0 :         logIO << "Error in reading image \"" << imagenamefull << "\"" << LogIO::EXCEPTION;
      90             :       }
      91           0 :   }
      92             :   //
      93             :   //--------------------------------------------------------------
      94             :   //
      95             :   template 
      96             :   void openImage(const String& imagenamefull, std::shared_ptr<ImageInterface<Float> >& img );
      97             :   template 
      98             :   void openImage(const String& imagenamefull, std::shared_ptr<ImageInterface<Complex> >& img );
      99             :   //
     100             :   //===========================================================================
     101             : 
     102             : 
     103             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     104             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     105             :   /////       START of SIIMAGESTORE implementation
     106             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     107             : 
     108             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     109             :   
     110        4992 :   SIImageStore::SIImageStore()
     111             :   {
     112             :       
     113        4992 :     itsPsf.reset( );
     114        4992 :     itsModel.reset( );
     115        4992 :     itsResidual.reset( );
     116        4992 :     itsWeight.reset( );
     117        4992 :     itsImage.reset( );
     118        4992 :     itsMask.reset( );
     119        4992 :     itsGridWt.reset( );
     120        4992 :     itsPB.reset( );
     121        4992 :     itsImagePBcor.reset();
     122        4992 :     itsTempWorkIm.reset();
     123             : 
     124        4992 :     itsSumWt.reset( );
     125        4992 :     itsOverWrite = False;
     126        4992 :     itsUseWeight = False;
     127        4992 :     itsPBScaleFactor = 1.0;
     128             : 
     129        4992 :     itsNFacets = 1;
     130        4992 :     itsFacetId = 0;
     131        4992 :     itsNChanChunks = 1;
     132        4992 :     itsChanId = 0;
     133        4992 :     itsNPolChunks = 1;
     134        4992 :     itsPolId = 0;
     135             : 
     136        4992 :     itsImageShape = IPosition(4,0,0,0,0);
     137        4992 :     itsImageName = String("");
     138        4992 :     itsCoordSys = CoordinateSystem();
     139        4992 :     itsMiscInfo = Record();
     140             : 
     141        4992 :     itsIsSingleDishStore = False;
     142             : 
     143        4992 :     init();
     144             :     //    validate();
     145             : 
     146        4992 :   }
     147             : 
     148             :   // Used from SynthesisNormalizer::makeImageStore()
     149         824 :   SIImageStore::SIImageStore(
     150             :     const String &imagename,
     151             :     const CoordinateSystem &imcoordsys,
     152             :     const IPosition &imshape,
     153             :     const String &objectname,
     154             :     const Record &miscinfo,
     155             :     //  const Int nfacets,
     156             :     const Bool /*overwrite*/,
     157             :     const Bool useweightimage,
     158             :     const Bool issingledishstore
     159         824 :   )
     160             :   // TODO : Add parameter to indicate weight image shape. 
     161             :   {
     162        1648 :     LogIO os( LogOrigin("SIImageStore","Open new Images",WHERE) );
     163             :       
     164             : 
     165         824 :     itsPsf.reset( );
     166         824 :     itsModel.reset( );
     167         824 :     itsResidual.reset( );
     168         824 :     itsWeight.reset( );
     169         824 :     itsImage.reset( );
     170         824 :     itsMask.reset( );
     171         824 :     itsGridWt.reset( );
     172         824 :     itsPB.reset( );
     173         824 :     itsImagePBcor.reset( );
     174         824 :     itsTempWorkIm.reset();
     175             : 
     176         824 :     itsSumWt.reset( );
     177         824 :     itsOverWrite = False; // Hard Coding this. See CAS-6937. overwrite;
     178         824 :     itsUseWeight = useweightimage;
     179         824 :     itsPBScaleFactor = 1.0;
     180             : 
     181         824 :     itsNFacets = 1;
     182         824 :     itsFacetId = 0;
     183         824 :     itsNChanChunks = 1;
     184         824 :     itsChanId = 0;
     185         824 :     itsNPolChunks = 1;
     186         824 :     itsPolId = 0;
     187             : 
     188         824 :     itsImageName = imagename;
     189         824 :     itsCoordSys = imcoordsys;
     190         824 :     itsImageShape = imshape;
     191         824 :     itsObjectName = objectname;
     192         824 :     itsMiscInfo = miscinfo;
     193             : 
     194         824 :     itsIsSingleDishStore = issingledishstore;
     195             : 
     196         824 :     init();
     197             : 
     198         824 :     validate();
     199         824 :   }
     200             : 
     201             :   // Used from SynthesisNormalizer::makeImageStore()
     202             :   // This constructor creates an Image Store from images on disk
     203        3209 :   SIImageStore::SIImageStore(
     204             :     const String &imagename,
     205             :     const Bool ignorefacets,
     206             :     const Bool noRequireSumwt,
     207        3209 :     const Bool makeSingleDishStore)
     208             :   {
     209        6418 :     LogIO os( LogOrigin("SIImageStore","Open existing Images",WHERE) );
     210             : 
     211             :     { // Initialize some members
     212        3209 :       itsImageName = imagename;
     213             : 
     214        3209 :       itsPsf.reset( );
     215        3209 :       itsModel.reset( );
     216        3209 :       itsResidual.reset( );
     217        3209 :       itsWeight.reset( );   
     218        3209 :       itsImage.reset( );
     219        3209 :       itsMask.reset( );
     220        3209 :       itsGridWt.reset( );
     221        3209 :       itsPB.reset( );
     222        3209 :       itsImagePBcor.reset( );
     223        3209 :       itsTempWorkIm.reset();
     224        3209 :       itsMiscInfo = Record();
     225             : 
     226        3209 :       itsSumWt.reset( );
     227        3209 :       itsNFacets = 1;
     228        3209 :       itsFacetId = 0;
     229        3209 :       itsNChanChunks = 1;
     230        3209 :       itsChanId = 0;
     231        3209 :       itsNPolChunks = 1;
     232        3209 :       itsPolId = 0;
     233             :     
     234        3209 :       itsOverWrite = False;
     235             : 
     236        3209 :       itsIsSingleDishStore = makeSingleDishStore;
     237             :     }
     238             : 
     239             :     // Need to do this init now so that imageExts is initialized
     240        3209 :     init();
     241             : 
     242             :     // Since this constructor creates an ImStore from images on disk,
     243             :     // it needs at least one of the images to actually be present on disk,
     244             :     // from which it can retrieve shape and coordsys information.
     245             : 
     246             :     { // Do we have at least 1 usable image ?
     247        3209 :       constexpr SIImageStore::IMAGE_IDS imageIds[] = {
     248             :         SIImageStore::PSF,
     249             :         SIImageStore::RESIDUAL,
     250             :         SIImageStore::MODEL,
     251             :         SIImageStore::PB,
     252             :         SIImageStore::WEIGHT,
     253             :         SIImageStore::GRIDWT,
     254             :       };
     255             :   
     256        3209 :       std::shared_ptr<ImageInterface<Float> > imptr;
     257             : 
     258        3209 :       auto haveImage = False;
     259        3368 :       for (auto imageId : imageIds) {
     260        3368 :         const auto imageName = imageFullName(imageId);
     261        3368 :         if (doesImageExist(imageName)) {
     262        3209 :           if (imageId == SIImageStore::GRIDWT) {
     263           0 :             constexpr auto preserveOldComment = True;
     264             :             // How can this be right ?
     265             :           }
     266        3209 :           buildImage(imptr, imageName);
     267        3209 :           haveImage = True;
     268        3209 :           break;
     269             :         }
     270        3368 :       }
     271             : 
     272        3209 :       if (haveImage) {
     273        3209 :         itsObjectName = imptr->imageInfo().objectName();
     274        3209 :         itsImageShape = imptr->shape();
     275        3209 :         itsCoordSys = imptr->coordinates();
     276        3209 :         itsMiscInfo = imptr->miscInfo();
     277             :       } else {
     278           0 :         String errMsg;
     279           0 :         if (not itsIsSingleDishStore) {
     280             :           errMsg = "PSF, Residual, Model Image (or sumwt) do not exist."
     281           0 :                   " Please create one of them.";
     282             :         } else {
     283           0 :           errMsg = String("Single-dish image and single-dish weight image"
     284             :                    " do not exist. Please create one of:\n")
     285           0 :                    + imageFullName(SIImageStore::RESIDUAL) + "\nor\n"
     286           0 :                    + imageFullName(SIImageStore::WEIGHT);
     287             :         }
     288           0 :         throw AipsError(errMsg);
     289           0 :       }
     290        3209 :     }
     291             : 
     292             :     { // Handle special case: psf or residual exist
     293             :       // Should we update things here when itsIsSingleDishStore = True ?
     294        3209 :       if (    doesImageExist( imageFullName(RESIDUAL) )
     295        3209 :            or doesImageExist( imageFullName(PSF) ) ) {
     296        3207 :         if ( doesImageExist( imageFullName(SUMWT)) ) {
     297        3117 :           std::shared_ptr<ImageInterface<Float> > imptr;
     298        3117 :           buildImage(imptr, imageFullName(SUMWT) );
     299        3117 :           itsNFacets = imptr->shape()[0];
     300        3117 :           itsFacetId = 0;
     301        3117 :           itsUseWeight = getUseWeightImage( *imptr );
     302        3117 :           itsPBScaleFactor = 1.0; // No need to set properly here
     303             :                                   // as it will be calc'd in ()
     304             :           // Redo this here as psf may have different coordinates
     305        3117 :           itsCoordSys = imptr->coordinates();
     306        3117 :           itsMiscInfo =imptr->miscInfo();
     307        6234 :           if ( itsUseWeight 
     308        3117 :                and not doesImageExist( imageFullName(WEIGHT) ) ) {
     309           0 :             throw AipsError(
     310             :               "Internal error : Sumwt has a useweightimage=True"
     311             :               " but the weight image does not exist."
     312           0 :             );
     313             :           }
     314        3117 :         } else {
     315          90 :           if (not noRequireSumwt) { // .sumwt image required?
     316             :               // -> probably not for just the minor cycle (aka task deconvolve)
     317           0 :               throw AipsError(
     318             :                 "SumWt information does not exist."
     319             :                 " Please create either a PSF or Residual"
     320           0 :               );
     321             :           } else {
     322             :             os << "SumWt does not exist. Proceeding only with PSF"
     323          90 :               << LogIO::POST;
     324          90 :             std::shared_ptr<ImageInterface<Float> > imptr;
     325          90 :             if ( doesImageExist( imageFullName(RESIDUAL) ) ) {
     326          88 :               buildImage(imptr, imageFullName(RESIDUAL) );
     327             :             }
     328             :             else {
     329           2 :               buildImage(imptr, imageFullName(PSF) );
     330             :             }
     331             : 
     332          90 :             itsNFacets = 1;
     333          90 :             itsFacetId = 0;
     334          90 :             itsUseWeight = False;
     335          90 :             itsPBScaleFactor = 1.0;
     336          90 :             itsCoordSys = imptr->coordinates();
     337          90 :             itsMiscInfo = imptr->miscInfo();
     338          90 :           }
     339             :         }
     340             :       } // if psf or residual exist
     341             :     } // Handle special case
     342             : 
     343        3209 :     if (ignorefacets == True) itsNFacets = 1;
     344             : 
     345             :     // Why again ?
     346        3209 :     init();
     347             : 
     348        3209 :     validate();
     349        3209 :   }
     350             : 
     351             :   // used from getSubImageStore(), for example when creating the facets list
     352             :   // this would be safer if it was refactored as a copy constructor of the generic stuff +
     353             :   // initialization of the facet related parameters
     354         799 :   SIImageStore::SIImageStore(const std::shared_ptr<ImageInterface<Float> > &modelim,
     355             :                              const std::shared_ptr<ImageInterface<Float> > &residim,
     356             :                              const std::shared_ptr<ImageInterface<Float> > &psfim,
     357             :                              const std::shared_ptr<ImageInterface<Float> > &weightim,
     358             :                              const std::shared_ptr<ImageInterface<Float> > &restoredim,
     359             :                              const std::shared_ptr<ImageInterface<Float> > &maskim,
     360             :                              const std::shared_ptr<ImageInterface<Float> > &sumwtim,
     361             :                              const std::shared_ptr<ImageInterface<Float> > &gridwtim,
     362             :                              const std::shared_ptr<ImageInterface<Float> > &pbim,
     363             :                              const std::shared_ptr<ImageInterface<Float> > &restoredpbcorim,
     364             :                              const std::shared_ptr<ImageInterface<Float> > & tempworkimage,
     365             :                              const CoordinateSystem &csys,
     366             :                              const IPosition &imshape,
     367             :                              const String &imagename,
     368             :                              const String &objectname,
     369             :                              const Record &miscinfo,
     370             :                              const Int facet, const Int nfacets,
     371             :                              const Int chan, const Int nchanchunks,
     372             :                              const Int pol, const Int npolchunks,
     373         799 :                              const Bool useweightimage)
     374             :   {
     375             :       
     376             : 
     377         799 :     itsPsf=psfim;
     378         799 :     itsModel=modelim;
     379         799 :     itsResidual=residim;
     380             :     /* if(residim){
     381             :      LatticeLocker lock1(*itsResidual, FileLocker::Read);
     382             :      cerr << "RESIDMAX " << max(itsResidual->get()) <<  "   " << max(residim->get()) << endl;
     383             :      }*/
     384         799 :     itsWeight=weightim;
     385         799 :     itsImage=restoredim;
     386         799 :     itsMask=maskim;
     387             : 
     388         799 :     itsSumWt=sumwtim;
     389             : 
     390         799 :     itsGridWt=gridwtim;
     391         799 :     itsPB=pbim;
     392         799 :     itsImagePBcor=restoredpbcorim;
     393         799 :     itsTempWorkIm=tempworkimage;
     394             : 
     395         799 :     itsPBScaleFactor=1.0;// No need to set properly here as it will be computed in makePSF.
     396             : 
     397         799 :     itsObjectName = objectname;
     398         799 :     itsMiscInfo = miscinfo;
     399             : 
     400         799 :     itsNFacets = nfacets;
     401         799 :     itsFacetId = facet;
     402         799 :     itsNChanChunks = nchanchunks;
     403         799 :     itsChanId = chan;
     404         799 :     itsNPolChunks = npolchunks;
     405         799 :     itsPolId = pol;
     406             : 
     407         799 :     itsOverWrite=False;
     408         799 :     itsUseWeight=useweightimage;
     409             : 
     410         799 :     itsParentImageShape = imshape; 
     411         799 :     itsImageShape = imshape;
     412             : 
     413         799 :     itsParentCoordSys = csys;
     414         799 :     itsCoordSys = csys; // Hopefully this doesn't change for a reference image
     415         799 :     itsImageName = imagename;
     416             : 
     417         799 :     itsIsSingleDishStore = False;
     418             : 
     419             :     //-----------------------
     420         799 :     init(); // Connect parent pointers to the images.
     421             :     //-----------------------
     422             : 
     423             :     // Set these to null, to be set later upon first access.
     424         799 :     itsPsf.reset( );
     425         799 :     itsModel.reset( );
     426         799 :     itsResidual.reset( );
     427         799 :     itsWeight.reset( );
     428         799 :     itsImage.reset( );
     429         799 :     itsMask.reset( );
     430         799 :     itsSumWt.reset( );
     431         799 :     itsPB.reset( );
     432             : 
     433         799 :     validate();
     434         799 :   }
     435             :   
     436        9554 :    void SIImageStore::validate()
     437             :   {
     438             :     // There are two valid states. Check for at least one of them. 
     439        9554 :     Bool inValidState = False;
     440             :     
     441        9554 :     stringstream oss;
     442             :     { // Initialize error message
     443             :       oss
     444        9554 :         << "shape:" << itsImageShape
     445        9554 :           << " parentimageshape:" << itsParentImageShape
     446        9554 :         << " nfacets:" << itsNFacets << "x" << itsNFacets 
     447        9554 :           << " facetid:" << itsFacetId 
     448        9554 :         << " nchanchunks:" << itsNChanChunks << " chanid:" << itsChanId 
     449        9554 :         << " npolchunks:" << itsNPolChunks << " polid:" << itsPolId 
     450        9554 :         << " coord-dim:" << itsCoordSys.nPixelAxes() 
     451        9554 :         << " psf/res:" << (hasPsf() or hasResidual());
     452        9554 :       if ( hasSumWt() ) oss << " sumwtshape : " << sumwt()->shape();
     453        9554 :       oss << endl;
     454             :     }
     455             : 
     456             :     try {
     457             : 
     458        9554 :       if ( itsCoordSys.nPixelAxes() != 4 ) inValidState = False;
     459             : 
     460             :       // (1) Regular imagestore
     461        9554 :       if ( 
     462        9554 :               itsNFacets == 1     and itsFacetId == 0
     463        9362 :           and itsNChanChunks == 1 and itsChanId == 0
     464        9362 :           and itsNPolChunks == 1  and itsPolId == 0 ) {
     465        9240 :         Bool sumWtShapeOK = hasSumWt() and sumwt()->shape()[0] == 1;
     466        9240 :         if ( itsImageShape.isEqual(itsParentImageShape)
     467        9240 :              and ( sumWtShapeOK or not hasSumWt() )
     468       18480 :              and itsParentImageShape.product() > 0 ) inValidState = True;
     469        9240 :       }
     470             :       // (2) Reference Sub Imagestore
     471         314 :       else if ( 
     472         314 :              ( itsNFacets > 1     and itsFacetId >= 0 )
     473         122 :           or ( itsNChanChunks > 1 and itsChanId >= 0 )
     474         122 :           or ( itsNPolChunks > 1  and itsPolId >= 0 ) ) {
     475             :         // If shape is still unset, even when the first image has been made....
     476             :         Bool imgShapeOK1 =
     477         314 :           ( itsImageShape.product() > 0 and ( hasPsf() or hasResidual() ) );
     478             :         Bool imgShapeOK2 =
     479         942 :           ( itsImageShape.isEqual(IPosition(4,0,0,0,0)) and
     480         314 :             ( not hasPsf() and not hasResidual() )
     481         314 :           );
     482         314 :         Bool imgShapeOK = imgShapeOK1 or imgShapeOK2;
     483             :         Bool sumWtShapeOK =
     484         314 :           hasSumWt() and sumwt()->shape()[0] == 1; // One facet only.
     485             : 
     486         314 :         if (  imgShapeOK and ( itsParentImageShape.product() > 0 )
     487         314 :               and ( itsFacetId < itsNFacets*itsNFacets )
     488             :               // and (itsChanId<=itsNChanChunks) // chanchunks can be larger...
     489         314 :               and ( itsPolId < itsNPolChunks )
     490         628 :               and ( sumWtShapeOK or not hasSumWt() ) ) inValidState = True;
     491             :       }
     492             : 
     493             :     }
     494           0 :     catch ( AipsError &err ) {
     495           0 :       inValidState = False;
     496           0 :       oss << "  |||||  " << err.getMesg() << endl;
     497           0 :     }
     498             : 
     499        9554 :     if ( not inValidState ) {
     500           0 :       throw AipsError(
     501           0 :         "Internal Error : Invalid ImageStore state : " + oss.str()
     502           0 :       );
     503             :     }
     504             : 
     505        9554 :   }
     506             : 
     507             : 
     508             :   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     509             : 
     510         799 :   std::shared_ptr<SIImageStore> SIImageStore::getSubImageStore(const Int facet, const Int nfacets, 
     511             :                                                           const Int chan, const Int nchanchunks, 
     512             :                                                           const Int pol, const Int npolchunks)
     513             :   {
     514             :    
     515         799 :     return std::make_shared<SIImageStore>(itsModel, itsResidual, itsPsf, itsWeight, itsImage, itsMask, itsSumWt, itsGridWt, itsPB, itsImagePBcor, itsTempWorkIm, itsCoordSys, itsImageShape, itsImageName, itsObjectName, itsMiscInfo, facet, nfacets, chan, nchanchunks, pol, npolchunks, itsUseWeight);
     516             :   }
     517             : 
     518             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     519             :   //// Either read an image from disk, or construct one. 
     520             : 
     521       33903 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::openImage(const String imagenamefull, 
     522             :                                                              const Bool overwrite, 
     523             :                                                              const Bool dosumwt, const Int nfacetsperside, const Bool checkCoordSys)
     524             :   {
     525             : 
     526             : 
     527       33903 :     std::shared_ptr<ImageInterface<Float> > imPtr;
     528       33903 :     IPosition useShape( itsParentImageShape );
     529             : 
     530       33903 :     if( dosumwt ) // change shape to sumwt image shape.
     531             :       {
     532        4656 :         useShape[0] = nfacetsperside;
     533        4656 :         useShape[1] = nfacetsperside;
     534             :         //      cout << "openImage : Making sumwt grid : using shape : " << useShape << endl;
     535             :       }
     536             : 
     537             :     //    overwrite=False; /// HARD CODING THIS. See CAS-6937.
     538             : 
     539             :     //    cout << "Open image : " << imagenamefull << "    useShape : " << useShape << endl;
     540             : 
     541             :     // if image exists
     542             :     //      if overwrite=T
     543             :     //           try to make new image
     544             :     //           if not, try to open existing image
     545             :     //                     if cannot, complain.
     546             :     //       if overwrite=F
     547             :     //           try to open existing image
     548             :     //           if cannot, complain
     549             :     // if image does not exist
     550             :     //       try to make new image
     551             :     //       if cannot, complain
     552       33903 :     Bool dbg=False;
     553       33903 :     if( doesImageExist( imagenamefull ) )
     554             :       {
     555             :         ///// not used since itsOverWrite is hardcoded to FALSE (CAS-6937)
     556       27312 :         if (overwrite) //overwrite and make new image
     557             :           {
     558           0 :             if(dbg) cout << "Trying to overwrite and open new image named : " << imagenamefull << " ow:"<< overwrite << endl;
     559             :             try{
     560           0 :               buildImage(imPtr, useShape, itsParentCoordSys, imagenamefull) ;
     561           0 :               LatticeLocker lock1(*imPtr, FileLocker::Write);
     562             :               // initialize to zeros...
     563           0 :               imPtr->set(0.0);
     564           0 :             }
     565           0 :             catch (AipsError &x){
     566           0 :               if(dbg)cout << "Cannot overwrite : " << x.getMesg() << endl;
     567           0 :               if(dbg)cout << "Open already ? : " << Table::isOpened( imagenamefull ) << "  Writable ? : " << Table::isWritable( imagenamefull ) << endl;
     568           0 :             if(Table::isWritable( imagenamefull ))
     569             :               {
     570           0 :                 if(dbg) cout << "--- Trying to open existing image : "<< imagenamefull << endl;
     571             :                 try{
     572           0 :                   buildImage( imPtr, imagenamefull );
     573             :                 }
     574           0 :                 catch (AipsError &x){
     575           0 :                   throw( AipsError("Writable table exists, but cannot open : " + x.getMesg() ) );
     576           0 :                 }
     577             :               }// is table writable
     578             :             else
     579             :               {
     580           0 :                 throw( AipsError("Cannot overwrite existing image. : " + x.getMesg() ) );
     581             :               }
     582           0 :             }
     583             :           }// overwrite existing image
     584             :         else // open existing image ( Always tries this )
     585             :           {
     586             :             if(1) //Table::isWritable( imagenamefull ))
     587             :               {
     588       27312 :                 if(dbg) cout << "Trying to open existing image : "<< imagenamefull << endl;
     589             :                 try{
     590       27312 :                   buildImage( imPtr, imagenamefull ) ;
     591             : 
     592       27312 :                   if( !dosumwt)
     593             :                     {
     594             :                       //cout << useShape << "  and " << imPtr->shape() << " ---- " << useShape.product() << " : " << itsCoordSys.nCoordinates() << endl;
     595             :                       // Check if coordsys and shape of this image are consistent with current ones (if filled)
     596             : 
     597       23693 :                       if( useShape.product()>0 &&  ! useShape.isEqual( imPtr->shape() ) )
     598             :                         {
     599          15 :                           ostringstream oo1,oo2;
     600          15 :                           oo1 << useShape; oo2 << imPtr->shape();
     601          15 :                           throw( AipsError( "There is a shape mismatch between existing images ("+oo2.str()+") and current parameters ("+oo1.str()+"). If you are attempting to restart a run with a new image shape, please change imagename and supply the old model or mask as inputs (via the startmodel or mask parameters) so that they can be regridded to the new shape before continuing." ) );
     602          30 :                         }
     603             : 
     604             :                       
     605             :                      
     606       23678 :                       if( itsParentCoordSys.nCoordinates()>0 &&  checkCoordSys && ! itsParentCoordSys.near( imPtr->coordinates()) )
     607             :                         {
     608             :                           /// Implement an exception to get CAS-9977 to work. Modify the current coordsys to match the parent.
     609             :                           /// "The DirectionCoordinates have differing latpoles"
     610           2 :                           if( itsParentCoordSys.errorMessage().contains("differing latpoles") )
     611             :                             {
     612           0 :                               DirectionCoordinate dcord = itsParentCoordSys.directionCoordinate();
     613             :                               //cout << "Latpole from parent : " << dcord.longLatPoles() << endl;
     614             :                               
     615           0 :                               DirectionCoordinate dcord2 = imPtr->coordinates().directionCoordinate();
     616             :                               //cout << "Latpole from imPtr : " << dcord2.longLatPoles() << endl;
     617             :                       
     618           0 :                             LogIO os( LogOrigin("SIImageStore","Open existing Images",WHERE) );
     619           0 :                             os  << " Mismatch in Csys latpoles between existing image on disk (" << dcord2.longLatPoles() <<  ") and current imaging run (" << dcord.longLatPoles() << ") : " << itsParentCoordSys.errorMessage() << " -- Resetting to match image on disk" << LogIO::WARN << LogIO::POST;
     620             :                             //                       cout << "Set the coordinate from the Parent value" << endl;
     621             :                             //imPtr->setCoordinateInfo( itsParentCoordSys );
     622           0 :                             itsParentCoordSys = imPtr->coordinates();
     623           0 :                             }
     624             :                           
     625             :                           // Check again. 
     626           2 :                           if ( ! itsParentCoordSys.near( imPtr->coordinates() ) )
     627             :                             {
     628             :                               //cout << " Still different..." << endl;
     629           2 :                               throw( AipsError( "There is a coordinate system mismatch between existing images on disk and current parameters ("+itsParentCoordSys.errorMessage()+"). If you are attempting to restart a run, please change imagename and supply the old model or mask as inputs (via the startmodel or mask parameters) so that they can be regridded to the new coordinate system before continuing. " ) );
     630             :                             }
     631             :                               //}
     632             :                         }
     633             :                     }// not dosumwt
     634             :                 }
     635          17 :                 catch (AipsError &x){
     636          17 :                   throw( AipsError("Cannot open existing image : "+imagenamefull+" : " + x.getMesg() ) );
     637          17 :                 }
     638             :               }// is table writable
     639             :             else // table exists but not writeable
     640             :               {
     641             :                 if(dbg)cout << "Table exists but not writeable : " << imagenamefull << "  --- Open : " << Table::isOpened( imagenamefull ) << endl;
     642             :                 throw( AipsError("Image exists but not able to open for writes :"+imagenamefull+ ". Opened elsewhere : " + String::toString(Table::isOpened(imagenamefull))) );
     643             :               }
     644             :           }// open existing image
     645             :       }// if image exists
     646             :       else // image doesn't exist. make new one
     647             :         {
     648        6591 :           if(dbg) cout << "Trying to open new image named : " << imagenamefull <<  endl;
     649             :           try{
     650        6591 :             buildImage(imPtr, useShape, itsParentCoordSys, imagenamefull) ;
     651             :             // initialize to zeros...
     652             :             {
     653        6591 :             LatticeLocker lock1(*imPtr, FileLocker::Write);
     654        6591 :             imPtr->set(0.0);
     655        6591 :             imPtr->flush();
     656        6591 :             imPtr->unlock();
     657        6591 :             }
     658             :           }
     659           0 :           catch (AipsError &x){
     660           0 :             throw( AipsError("Cannot make new image. : " + x.getMesg() ) );
     661           0 :           }
     662             :         }
     663             : 
     664             : 
     665             :       //////////////////////////////////////
     666             :     /*      
     667             :     if( overwrite || !Table::isWritable( imagenamefull ) )
     668             :       {
     669             :         cout << "Trying to open new image named : " << imagenamefull << " ow:"<< overwrite << endl;
     670             :         imPtr.reset( new PagedImage<Float> (useShape, itsCoordSys, imagenamefull) );
     671             :         // initialize to zeros...
     672             :         imPtr->set(0.0);
     673             :       }
     674             :     else
     675             :       {
     676             :         if(Table::isWritable( imagenamefull ))
     677             :           {
     678             :             cout << "Trying to open existing image : "<< imagenamefull << endl;
     679             :             try{
     680             :               imPtr.reset( new PagedImage<Float>( imagenamefull ) );
     681             :             }
     682             :             catch (AipsError &x){
     683             :               cerr << "Writable table exists, but cannot open. Creating temp image. : " << x.getMesg() << endl;
     684             :               imPtr.reset( new TempImage<Float> (useShape, itsCoordSys) );
     685             :               //  imPtr=new PagedImage<Float> (useShape, itsCoordSys, imagenamefull);
     686             :               imPtr->set(0.0);
     687             :             }
     688             :           }
     689             :         else
     690             :           {
     691             :             cerr << "Table " << imagenamefull << " is not writeable. Creating temp image." << endl;
     692             :             imPtr.reset( new TempImage<Float> (useShape, itsCoordSys) );
     693             :             imPtr->set(0.0);
     694             :           }
     695             :       }
     696             :     */
     697       67772 :     return imPtr;
     698       33920 :   }
     699             : 
     700        6591 :   void SIImageStore::buildImage(std::shared_ptr<ImageInterface<Float> > &imptr, IPosition shape,
     701             :                                 CoordinateSystem csys, const String name)
     702             :   {
     703       13182 :     LogIO os( LogOrigin("SIImageStore", "Open non-existing image", WHERE) );
     704        6591 :     os  <<"Opening image, name: " << name << LogIO::DEBUG1;
     705             : 
     706        6591 :     itsOpened++;
     707             :     //For some reason cannot open a new paged image with UserNoread directly
     708             :     {
     709        6591 :       PagedImage<Float> godot(shape, csys, name);
     710        6591 :       godot.unlock();
     711        6591 :     }
     712        6591 :     TableLock::LockOption locktype=TableLock::AutoNoReadLocking;
     713             :     //TableLock::LockOption locktype=TableLock::UserLocking;
     714             :     /*if((name.contains(imageExts(PSF)) && !name.contains(imageExts(PSF)+".tt"))|| (name.contains(imageExts(RESIDUAL))&& !name.contains(imageExts(RESIDUAL)+".tt")) || (name.contains(imageExts(SUMWT)) && !name.contains(imageExts(SUMWT)+".tt"))){
     715             :       locktype=TableLock::UserNoReadLocking;
     716             :       }*/
     717        6591 :     imptr.reset( new PagedImage<Float> (name, locktype) );
     718             :     {
     719        6591 :       LatticeLocker lock1(*imptr, FileLocker::Write);
     720        6591 :       initMetaInfo(imptr, name);
     721        6591 :       imptr->unlock();
     722        6591 :     }
     723             :     /*
     724             :     Int MEMFACTOR = 18;
     725             :     Double memoryMB=HostInfo::memoryTotal(True)/1024/(MEMFACTOR*itsOpened);
     726             : 
     727             : 
     728             :     TempImage<Float> *tptr = new TempImage( TiledShape(shape, tileShape()), csys, memoryBeforeLattice() ) ;
     729             : 
     730             :     tptr->setMaximumCacheSize(shape.product());
     731             :     tptr->cleanCache();
     732             : 
     733             :     imptr.reset( tptr );
     734             :     
     735             :     */
     736        6591 :   }
     737             : 
     738       35285 :   void SIImageStore::buildImage(std::shared_ptr<ImageInterface<Float> > &imptr, const String name)
     739             :   {
     740       70570 :     LogIO os(LogOrigin("SIImageStore", "Open existing Images", WHERE));
     741       35285 :     os  <<"Opening image, name: " << name << LogIO::DEBUG1;
     742             : 
     743       35285 :     itsOpened++;
     744       35285 :     if ( Table::isReadable(name) ) {
     745       35285 :       TableLock::LockOption locktype=TableLock::AutoNoReadLocking;
     746             :       /*  if (
     747             :             (  name.contains(imageExts(PSF)) and
     748             :                not name.contains(imageExts(PSF) + ".tt")
     749             :             ) or
     750             :             (  name.contains(imageExts(RESIDUAL)) and
     751             :                not name.contains(imageExts(RESIDUAL)+".tt")
     752             :             ) or
     753             :             (  name.contains(imageExts(SUMWT)) and 
     754             :                not name.contains(imageExts(SUMWT)+".tt")
     755             :             )
     756             :           ) {
     757             :             locktype=TableLock::UserNoReadLocking;
     758             :           }
     759             :       */
     760       35285 :       Table table(name, locktype);
     761       35285 :       String type = table.tableInfo().type();
     762       35285 :       if ( type != TableInfo::type(TableInfo::PAGEDIMAGE) ) {
     763             : 
     764           0 :         imptr.reset( new PagedImage<Float>( table ) );
     765           0 :         imptr->unlock();
     766           0 :         return;
     767             :       }
     768       35285 :     }
     769             : 
     770       35285 :     LatticeBase* latt =ImageOpener::openImage(name);
     771       35285 :     if (not latt) {
     772           0 :       throw AipsError("Error in opening Image : "+name);
     773             :     }
     774       35285 :     DataType dtype = latt->dataType();
     775       35285 :     if (dtype == TpFloat) {
     776       35285 :       imptr.reset(dynamic_cast<ImageInterface<Float>* >(latt));
     777             :     } else {
     778           0 :       throw AipsError( "Need image to have float values :  "+name);
     779             :     }
     780             : 
     781             :     /*
     782             :     std::shared_ptr<casacore::ImageInterface<Float> > fim;
     783             :     std::shared_ptr<casacore::ImageInterface<Complex> > cim;
     784             : 
     785             :     std::tie(fim , cim)=ImageFactory::fromFile(name);
     786             :     if (fim) {
     787             :       imptr.reset(
     788             :         dynamic_cast<std::shared_ptr<casacore::ImageInterface<Float> > >(*fim)
     789             :       );
     790             :     } else {
     791             :       throw AipsError("Cannot open with ImageFactory : "+name);
     792             :     }
     793             :     */
     794             : 
     795             :     /*
     796             :     IPosition cimageShape;
     797             :     CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord(
     798             :       itsCoordSys,
     799             :       whichStokes,
     800             :       itsDataPolRep
     801             :     );
     802             :     */
     803             : 
     804       35285 :   }
     805             : 
     806             :   /**
     807             :    * Sets ImageInfo and MiscInfo on an image
     808             :    *
     809             :    * @param imptr image to initialize
     810             :    */
     811        6606 :   void SIImageStore::initMetaInfo(std::shared_ptr<ImageInterface<Float> > &imptr,
     812             :                                   const String name)
     813             :   {
     814             :       // Check objectname, as one of the mandatory fields. What this is meant to check is -
     815             :       // has the metainfo been initialized? If not, grab info from associated PSF
     816        6606 :     LatticeLocker lock1(*imptr, FileLocker::Write);
     817        6606 :       if (not itsObjectName.empty()) {
     818        6606 :           ImageInfo info = imptr->imageInfo();
     819        6606 :           info.setObjectName(itsObjectName);
     820        6606 :           imptr->setImageInfo(info);
     821        6606 :           imptr->setMiscInfo(itsMiscInfo);
     822        6606 :       } else if (std::string::npos == name.find(imageExts(PSF))) {
     823           0 :           auto srcImg = psf(0);
     824           0 :           if (nullptr != srcImg) {
     825           0 :               imptr->setImageInfo(srcImg->imageInfo());
     826           0 :               imptr->setMiscInfo(srcImg->miscInfo());
     827             :           }
     828           0 :       }
     829        6606 :       imptr->unlock();
     830        6606 :   }
     831             : 
     832             : 
     833             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     834           0 :   void SIImageStore::setMiscInfo(const Record miscinfo)
     835             :   {
     836           0 :     itsMiscInfo = miscinfo;
     837           0 :   }
     838             : 
     839           0 :   void SIImageStore::setObjectName(const String name)
     840             :   {
     841           0 :     itsObjectName = name;
     842           0 :   }
     843             : 
     844             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     845             : 
     846       37853 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::makeSubImage(const Int facet, const Int nfacets,
     847             :                                                                 const Int chan, const Int nchanchunks,
     848             :                                                                 const Int pol, const Int npolchunks,
     849             :                                                                 ImageInterface<Float>& image)
     850             :   {
     851             :     //assuming n x n facets
     852       37853 :     Int nx_facets=Int(sqrt(Double(nfacets)));
     853       75706 :     LogIO os( LogOrigin("SynthesisImager","makeFacet") );
     854             :      // Make the output image
     855       37853 :     Slicer imageSlicer;
     856             : 
     857             :     // Add checks for all dimensions..
     858       37853 :     if((facet>(nfacets-1))||(facet<0)) {
     859           0 :       os << LogIO::SEVERE << "Illegal facet " << facet << LogIO::POST;
     860           0 :       return std::shared_ptr<ImageInterface<Float> >();
     861             :     }
     862       37853 :     IPosition imshp=image.shape();
     863       37853 :     IPosition blc(imshp.nelements(), 0);
     864       37853 :     IPosition trc=imshp-1;
     865       37853 :     IPosition inc(imshp.nelements(), 1);
     866             : 
     867             :     /// Facets
     868       37853 :     Int facetx = facet % nx_facets; 
     869       37853 :     Int facety = (facet - facetx) / nx_facets;
     870       37853 :     Int sizex = imshp(0) / nx_facets;
     871       37853 :     Int sizey = imshp(1) / nx_facets;
     872       37853 :     blc(1) = facety * sizey; 
     873       37853 :     trc(1) = blc(1) + sizey - 1;
     874       37853 :     blc(0) = facetx * sizex; 
     875       37853 :     trc(0) = blc(0) + sizex - 1;
     876             : 
     877             :     /// Pol Chunks
     878       37853 :     Int sizepol = imshp(2) / npolchunks;
     879       37853 :     blc(2) = pol * sizepol;
     880       37853 :     trc(2) = blc(2) + sizepol - 1;
     881             : 
     882             :     /// Chan Chunks
     883       37853 :     Int sizechan = imshp(3) / nchanchunks;
     884       37853 :     blc(3) = chan * sizechan;
     885       37853 :     trc(3) = blc(3) + sizechan - 1;
     886             : 
     887       37853 :     LCBox::verify(blc, trc, inc, imshp);
     888       37853 :     Slicer imslice(blc, trc, inc, Slicer::endIsLast);
     889             : 
     890             :     // Now create the sub image
     891       37853 :     std::shared_ptr<ImageInterface<Float> >  referenceImage( new SubImage<Float>(image, imslice, True) );
     892             :     {
     893       37853 :       LatticeLocker lock1(*referenceImage, FileLocker::Write);
     894       37853 :       referenceImage->setMiscInfo(image.miscInfo());
     895       37853 :       referenceImage->setUnits(image.units());
     896             : 
     897       37853 :     }
     898             : 
     899             :     // cout << "Made Ref subimage of shape : " << referenceImage->shape() << endl;
     900             : 
     901       37853 :     return referenceImage;
     902             :     
     903       37853 :   }
     904             : 
     905             : 
     906             : 
     907             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     908             : 
     909       13033 :   SIImageStore::~SIImageStore() 
     910             :   {
     911       13033 :   }
     912             : 
     913             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     914             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     915             : 
     916       13080 :   Bool SIImageStore::releaseLocks() 
     917             :   {
     918             :     //LogIO os( LogOrigin("SIImageStore","releaseLocks",WHERE) );
     919             : 
     920             :     //    String fname( itsImageName+String(".info") );
     921             :     //    makePersistent( fname );
     922             : 
     923       13080 :     if( itsPsf ) releaseImage( itsPsf );
     924       13080 :     if( itsModel ) { releaseImage( itsModel ); }
     925       13080 :     if( itsResidual ) releaseImage( itsResidual );
     926       13080 :     if( itsImage ) releaseImage( itsImage );
     927       13080 :     if( itsWeight ) releaseImage( itsWeight );
     928       13080 :     if( itsMask ) releaseImage( itsMask );
     929       13080 :     if( itsSumWt ) releaseImage( itsSumWt );
     930       13080 :     if( itsGridWt ) releaseImage( itsGridWt );
     931       13080 :     if( itsPB ) releaseImage( itsPB );
     932       13080 :     if( itsImagePBcor ) releaseImage( itsImagePBcor );
     933             : 
     934       13080 :     return True; // do something more intelligent here.
     935             :   }
     936             : 
     937           0 :   Bool SIImageStore::releaseComplexGrids() 
     938             :   {
     939             :     //LogIO os( LogOrigin("SIImageStore","releaseComplexGrids",WHERE) );
     940             : 
     941           0 :     if( itsForwardGrid ) releaseImage( itsForwardGrid );
     942           0 :     if( itsBackwardGrid ) releaseImage( itsBackwardGrid );
     943             : 
     944           0 :     return True; // do something more intelligent here.
     945             :   }
     946             : 
     947       27297 :   void SIImageStore::releaseImage( std::shared_ptr<ImageInterface<Float> > &im )
     948             :   {
     949             :     //cerr << this << " releaseimage " << im.get() << endl;
     950             :     //LogIO os( LogOrigin("SIImageStore","releaseLocks",WHERE) );
     951       27297 :     im->flush();
     952             :     //os << LogIO::WARN << "clear cache" << LogIO::POST;
     953       27297 :     im->clearCache();
     954             :     //os << LogIO::WARN << "unlock" << LogIO::POST;
     955       27297 :     im->unlock();
     956             :     //os << LogIO::WARN << "tempClose" << LogIO::POST;
     957             :     //im->tempClose();
     958             :     //os << LogIO::WARN << "NULL" << LogIO::POST;
     959       27297 :     im.reset();  // This was added to allow modification by modules independently
     960       27297 :   }
     961             :   
     962           0 :   void SIImageStore::releaseImage( std::shared_ptr<ImageInterface<Complex> > &im )
     963             :   {
     964           0 :     im->tempClose();
     965           0 :   }
     966             : 
     967             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     968             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
     969           0 :   Vector<String> SIImageStore::getModelImageName()
     970             :   {
     971           0 :     Vector<String> mods(1);
     972           0 :     mods[0]=itsImageName + imageExts(MODEL);
     973           0 :     return mods;
     974           0 :   }
     975             : 
     976         788 :   Long SIImageStore::estimateRAM(){
     977             :     //right now this is estimated at 2MB for the 2 complex lattices;
     978         788 :     return Long(2000);
     979             :   }
     980          25 :   void SIImageStore::setModelImage( const Vector<String> &modelnames)
     981             :   {
     982          50 :     LogIO os( LogOrigin("SIImageStore","setModelImage",WHERE) );
     983             : 
     984          25 :     if( modelnames.nelements() > 1 )
     985           0 :       {throw( AipsError("Multiple starting model images are currently not supported. Please merge them before supplying as input to startmodel"));
     986             :         /// If needed, THIS is the place to add code to support lists of model images... perhaps regrid separately and add them up or some such thing.
     987             :       }
     988             : 
     989          25 :     if( modelnames.nelements()==1 ) { setModelImageOne( modelnames[0] ); }
     990          25 :   }
     991             : 
     992             : 
     993             : 
     994          45 :   void SIImageStore::setModelImageOne( const String &modelname , Int nterm)
     995             :   {
     996          90 :     LogIO os( LogOrigin("SIImageStore","setModelImageOne",WHERE) );
     997             : 
     998          45 :     if(modelname==String("")) return;
     999             : 
    1000          43 :     Bool multiterm=False;
    1001          43 :     if(nterm>-1)multiterm=True;
    1002          43 :     if(nterm==-1)nterm=0;
    1003             : 
    1004          43 :     Directory immodel( modelname ); //  +String(".model") );
    1005          43 :     if( !immodel.exists() ) 
    1006             :       {
    1007           0 :         os << "Starting model image " << modelname <<  " does not exist. No initial prediction will be done" << ((multiterm)?String(" for term")+String::toString(nterm) :"") << LogIO::POST;
    1008           0 :         return;
    1009             :       }
    1010             : 
    1011             :     // master merge 2019.01.08 - leaving in the commnets for now but clean up after it is verified 
    1012             :     //SHARED_PTR<PagedImage<Float> > newmodel( new PagedImage<Float>( modelname ) ); //+String(".model") ) );
    1013             :     //SHARED_PTR<ImageInterface<Float> > newmodel;
    1014          43 :     std::shared_ptr<ImageInterface<Float> > newmodel;
    1015          43 :     buildImage(newmodel, modelname);
    1016             :     // in master
    1017             :     //std::shared_ptr<PagedImage<Float> > newmodel( new PagedImage<Float>( modelname ) ); //+String(".model") ) );
    1018             : 
    1019          43 :     Bool hasMask = newmodel->isMasked(); /// || newmodel->hasPixelMask() ;
    1020             :     
    1021          43 :     if( hasMask )
    1022             :       {
    1023             :         
    1024           3 :         os << "Input startmodel has an internal mask. Setting masked pixels to zero" << LogIO::POST;
    1025             :         
    1026             :         try {
    1027             : 
    1028             :           ////// Neat function to replace masked pixels, but it will do it in-place.
    1029             :           ////// We need to not modify the input model on disk, but apply the mask only OTF before
    1030             :           //////  regridding to the target image,.
    1031             :           //      ImageMaskedPixelReplacer<Float> impr( newmodel, 0, "" );
    1032             :           //      impr.replace("0", False, False );
    1033             : 
    1034             :           
    1035           6 :           TempImage<Float> maskmodel( newmodel->shape(), newmodel->coordinates() );
    1036           3 :           IPosition inshape = newmodel->shape();
    1037           6 :           for(Int pol=0; pol<inshape[2]; pol++)
    1038             :             {
    1039           6 :               for(Int chan=0; chan<inshape[3]; chan++)
    1040             :                 {
    1041           3 :                   IPosition pos(4,0,0,pol,chan);
    1042             :                   std::shared_ptr<ImageInterface<Float> > subim=makeSubImage(0,1, 
    1043           6 :                                                                         chan, inshape[3],
    1044           3 :                                                                         pol, inshape[2], 
    1045           6 :                                                                         (*newmodel) );
    1046             :                   
    1047             :                   std::shared_ptr<ImageInterface<Float> > submaskmodel=makeSubImage(0,1, 
    1048           6 :                                                                                chan, inshape[3],
    1049           3 :                                                                                pol, inshape[2], 
    1050           3 :                                                                                maskmodel );
    1051             :                   
    1052           3 :                   ArrayLattice<Bool> pixmask( subim->getMask() );
    1053           6 :                   LatticeExpr<Float> masked( (*subim) * iif(pixmask,1.0,0.0) );
    1054           3 :                   submaskmodel->copyData( masked );
    1055           3 :                 }
    1056             :             }
    1057             :           
    1058             :           
    1059             : 
    1060             :           // Check shapes, coordsys with those of other images.  If different, try to re-grid here.
    1061           3 :           if( (newmodel->shape() != model(nterm)->shape()) ||  (! itsCoordSys.near(newmodel->coordinates() )) )
    1062             :             {
    1063           0 :               os << "Regridding input model " << modelname << " to target coordinate system for " << itsImageName << ".model" << ((multiterm)?".tt"+String::toString(nterm) :"") << LogIO::POST;
    1064           0 :               regridToModelImage( maskmodel, nterm );
    1065             :             }
    1066             :           else
    1067             :             {
    1068           3 :               os << "Copying input model " << modelname << " to " << itsImageName << ".model" << ((multiterm)?".tt"+String::toString(nterm) :"")  << LogIO::POST;
    1069           3 :               model(nterm)->copyData( LatticeExpr<Float> (maskmodel) );
    1070             :             }
    1071             :           
    1072             :           
    1073           3 :         } catch (AipsError &x) {
    1074           0 :           throw(AipsError("Setting masked pixels to zero for input startmodel : "+ x.getMesg()));
    1075           0 :         }
    1076             :         
    1077             :       }// hasMask
    1078             :     else // nomask
    1079             :       {
    1080             :         
    1081             :         // Check shapes, coordsys with those of other images.  If different, try to re-grid here.
    1082          40 :         if( (newmodel->shape() != model(nterm)->shape()) ||  (! itsCoordSys.near(newmodel->coordinates() )) )
    1083             :           {
    1084          15 :             os << "Regridding input model " << modelname << " to target coordinate system for " << itsImageName << ".model" << ((multiterm)?".tt"+String::toString(nterm) :"") << LogIO::POST;
    1085          15 :             regridToModelImage( *newmodel, nterm );
    1086             :           }
    1087             :         else
    1088             :           {
    1089          25 :             os << "Copying input model " << modelname << " to " << itsImageName << ".model" << ((multiterm)?".tt"+String::toString(nterm) :"")  << LogIO::POST;
    1090          25 :             model(nterm)->copyData( LatticeExpr<Float> (*newmodel) );
    1091             :           }
    1092             :       }//nomask
    1093          45 :   }
    1094             : 
    1095             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
    1096             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
    1097             : 
    1098       15346 :   IPosition SIImageStore::getShape()
    1099             :   {
    1100       15346 :     return itsImageShape;
    1101             :   }
    1102             : 
    1103        6969 :   String SIImageStore::getName()
    1104             :   {
    1105        6969 :     return itsImageName;
    1106             :   }
    1107             : 
    1108       14996 :   String SIImageStore::imageFullName(IMAGE_IDS imageId)
    1109             :   {
    1110       14996 :     return itsImageName + imageExts(imageId);
    1111             :   }
    1112             : 
    1113        8910 :   uInt SIImageStore::getNTaylorTerms(Bool /*dopsf*/)
    1114             :   {
    1115        8910 :     return 1;
    1116             :   }
    1117             : 
    1118             :   /*
    1119             :   void SIImageStore::checkRef( std::shared_ptr<ImageInterface<Float> > ptr, const String label )
    1120             :   {
    1121             :     if( ! ptr && itsImageName==String("reference") ) 
    1122             :       {throw(AipsError("Internal Error : Attempt to access null subImageStore "+label + " by reference."));}
    1123             :   }
    1124             :   */
    1125             : 
    1126      139796 :   void SIImageStore::accessImage( std::shared_ptr<ImageInterface<Float> > &ptr, 
    1127             :                     std::shared_ptr<ImageInterface<Float> > &parentptr, 
    1128             :                     const String label )
    1129             :   {
    1130             :     // if ptr is not null, assume it's OK. Perhaps add more checks.
    1131             : 
    1132             :     //cerr << "ACCIM itsptr" << ptr.get() << " parent " << parentptr.get() << " label " << label << endl;
    1133             :     
    1134      139796 :     Bool sw=False;
    1135      139796 :     if( label.contains(imageExts(SUMWT)) ) sw=True;
    1136             :     
    1137      139796 :     if( !ptr )
    1138             :       {
    1139             :         //cout << itsNFacets << " " << itsNChanChunks << " " << itsNPolChunks << endl;
    1140       34560 :         if( itsNFacets>1 || itsNChanChunks>1 || itsNPolChunks>1 )
    1141             :           {
    1142         975 :             if( ! parentptr ) 
    1143             :               {
    1144             :                 //cout << "Making parent : " << itsImageName+label << "    sw : " << sw << endl; 
    1145         757 :                 parentptr = openImage(itsImageName+label , itsOverWrite, sw, itsNFacets );  
    1146         757 :                 if( sw) {setUseWeightImage( *parentptr, itsUseWeight ); }
    1147             :               }
    1148             :             //      cout << "Making facet " << itsFacetId << " out of " << itsNFacets << endl;
    1149             :             //cout << "Making chunk " << itsChanId << " out of " << itsNChanChunks << endl;
    1150             :             //ptr = makeFacet( itsFacetId, itsNFacets*itsNFacets, *parentptr );
    1151        1950 :             ptr = makeSubImage( itsFacetId, itsNFacets*itsNFacets, 
    1152             :                                 itsChanId, itsNChanChunks, 
    1153             :                                 itsPolId, itsNPolChunks, 
    1154        1950 :                                 *parentptr );
    1155         975 :             if( ! sw )
    1156             :               {
    1157         803 :                 itsImageShape = ptr->shape(); // over and over again.... FIX.
    1158         803 :                 itsCoordSys = ptr->coordinates();
    1159         803 :                 itsMiscInfo = ptr->miscInfo();
    1160             :               }
    1161             : 
    1162             :             //cout << "accessImage : " << label << " : sumwt : " << sw << " : shape : " << itsImageShape << endl;
    1163             :     
    1164             :           }
    1165             :         else
    1166             :           { //no facets of chanchunks
    1167       33585 :             if(!parentptr){
    1168             :             ///coordsys for psf can be different ...shape should be the same.
    1169       32892 :               ptr = openImage(itsImageName+label , itsOverWrite, sw, 1, !(label.contains(imageExts(PSF)))); }
    1170             :             else{
    1171         693 :               ptr=parentptr;
    1172             :             }
    1173             :             //cout << "Opening image : " << itsImageName+label << " of shape " << ptr->shape() << endl;
    1174             :           }
    1175             :       }
    1176             : 
    1177             :     //cerr << "ACCIM2 ptr " << ptr.get() << " lock " << itsReadLock.get() << endl;
    1178             :     //itsReadLock.reset(new LatticeLocker(*ptr, FileLocker::Read));
    1179             :     
    1180             :     //    DirectionCoordinate dcord = ptr->coordinates().directionCoordinate();
    1181             :     //    cout << "Latpole from " << label << " : " << dcord.longLatPoles() << endl;
    1182             : 
    1183      139779 :   }
    1184             : 
    1185             : 
    1186       15198 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::psf(uInt /*nterm*/)
    1187             :   {
    1188       15198 :     accessImage( itsPsf, itsParentPsf, imageExts(PSF) );
    1189             :     
    1190       15197 :     return itsPsf;
    1191             :   }
    1192       32645 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::residual(uInt /*nterm*/)
    1193             :   {
    1194       32645 :     accessImage( itsResidual, itsParentResidual, imageExts(RESIDUAL) );
    1195             :     //    Record mi = itsResidual->miscInfo(); ostringstream oss;mi.print(oss);cout<<"MiscInfo(res) : " << oss.str() << endl;
    1196       32645 :     return itsResidual;
    1197             :   }
    1198        2589 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::weight(uInt /*nterm*/)
    1199             :   {
    1200        2589 :     accessImage( itsWeight, itsParentWeight, imageExts(WEIGHT) );
    1201        2589 :     return itsWeight;
    1202             :   }
    1203             : 
    1204       10820 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::sumwt(uInt /*nterm*/)
    1205             :   {
    1206             : 
    1207       10820 :     accessImage( itsSumWt, itsParentSumWt, imageExts(SUMWT) );
    1208             :     
    1209       10820 :     if( itsNFacets>1 || itsNChanChunks>1 || itsNPolChunks>1 ) 
    1210         536 :       { itsUseWeight = getUseWeightImage( *itsParentSumWt );}
    1211       10820 :     setUseWeightImage( *itsSumWt , itsUseWeight); // Sets a flag in the SumWt image. 
    1212             :     
    1213       10820 :     return itsSumWt;
    1214             :   }
    1215             : 
    1216       11763 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::model(uInt /*nterm*/)
    1217             :   {
    1218       11765 :     accessImage( itsModel, itsParentModel, imageExts(MODEL) );
    1219       11761 :     LatticeLocker lock1(*itsModel, FileLocker::Write);
    1220             :     // Set up header info the first time. 
    1221       11761 :     itsModel->setUnits("Jy/pixel");
    1222             : 
    1223       23522 :     return itsModel;
    1224       11761 :   }
    1225        6357 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::image(uInt /*nterm*/)
    1226             :   {
    1227        6357 :     accessImage( itsImage, itsParentImage, imageExts(IMAGE) );
    1228        6357 :     LatticeLocker lock1(*itsImage, FileLocker::Write);
    1229        6357 :     itsImage->setUnits(Unit("Jy/beam"));
    1230       12714 :     return itsImage;
    1231        6357 :   }
    1232             : 
    1233       15927 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::mask(uInt /*nterm*/)
    1234             :   {
    1235       15927 :     accessImage( itsMask, itsParentMask, imageExts(MASK) );
    1236       15923 :     return itsMask;
    1237             :   }
    1238          45 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::gridwt(IPosition newshape)
    1239             : 
    1240             :   {
    1241          45 :     if(newshape.empty()){
    1242          15 :       accessImage( itsGridWt, itsParentGridWt, imageExts(GRIDWT) );
    1243             :     }
    1244             :     else{
    1245          30 :       if(!itsGridWt  || (itsGridWt && (itsGridWt->shape() != newshape))){
    1246          15 :         itsGridWt.reset();  // deassign previous one hopefully it'll close it
    1247          15 :         CoordinateSystem newcoordsys=itsCoordSys;
    1248          15 :         if(newshape.nelements() > 4){
    1249          13 :           Matrix<Double> pc(1,1);      pc = 1.0;
    1250          26 :           LinearCoordinate zc(Vector<String>(1, "FIELD_ORDER"), Vector<String>(1, ""), Vector<Double>(1, 0.0), Vector<Double>(1,1.0), pc, Vector<Double>(1,0.0));
    1251          13 :           newcoordsys.addCoordinate(zc);
    1252          13 :         }
    1253          15 :           itsGridWt.reset(new PagedImage<Float>(newshape, newcoordsys, itsImageName+ imageExts(GRIDWT)));
    1254          15 :           initMetaInfo(itsGridWt, itsImageName+ imageExts(GRIDWT));
    1255             : 
    1256          15 :       }
    1257             :     }
    1258             :     /// change the coordinate system here, to uv.
    1259          45 :     return itsGridWt;
    1260             :   }
    1261             : 
    1262          31 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::tempworkimage(uInt /*term*/){
    1263          31 :     if(itsTempWorkIm) return itsTempWorkIm;
    1264          31 :     itsTempWorkIm.reset(new PagedImage<Float>(itsImageShape, itsCoordSys, itsImageName+ ".work.temp"));
    1265          31 :     static_cast<PagedImage<Float>* > (itsTempWorkIm.get())->set(0.0);
    1266          31 :     itsTempWorkIm->flush();
    1267          31 :     static_cast<PagedImage<Float>* > (itsTempWorkIm.get())->table().markForDelete();
    1268          31 :     return itsTempWorkIm;
    1269             :   }
    1270             :   
    1271       14273 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::pb(uInt /*nterm*/)
    1272             :   {
    1273       14273 :     accessImage( itsPB, itsParentPB, imageExts(PB) );
    1274       14271 :     return itsPB;
    1275             :   }
    1276         272 :   std::shared_ptr<ImageInterface<Float> > SIImageStore::imagepbcor(uInt /*nterm*/)
    1277             :   {
    1278         272 :     accessImage( itsImagePBcor, itsParentImagePBcor, imageExts(IMAGEPBCOR) );
    1279         272 :     LatticeLocker lock1(*itsImagePBcor, FileLocker::Write);
    1280         272 :     itsImagePBcor->setUnits(Unit("Jy/beam"));
    1281         544 :     return itsImagePBcor;
    1282         272 :   }
    1283             : 
    1284        1984 :   std::shared_ptr<ImageInterface<Complex> > SIImageStore::forwardGrid(uInt /*nterm*/){
    1285        1984 :     if( itsForwardGrid ) // && (itsForwardGrid->shape() == itsImageShape))
    1286             :       {
    1287             :         //      cout << "Forward grid has shape : " << itsForwardGrid->shape() << endl;
    1288        1736 :         return itsForwardGrid;
    1289             :       }
    1290         248 :     Vector<Int> whichStokes(0);
    1291         248 :     IPosition cimageShape;
    1292         248 :     cimageShape=itsImageShape;
    1293         248 :     MFrequency::Types freqframe = itsCoordSys.spectralCoordinate(itsCoordSys.findCoordinate(Coordinate::SPECTRAL)).frequencySystem(True);
    1294             :     // No need to set a conversion layer if image is in LSRK already or it is 'Undefined'
    1295         248 :     if(freqframe != MFrequency::LSRK && freqframe!=MFrequency::Undefined && freqframe!=MFrequency::REST) 
    1296           0 :       { itsCoordSys.setSpectralConversion("LSRK"); }
    1297         248 :     CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord( itsCoordSys,
    1298         248 :                                                                   whichStokes, itsDataPolRep);
    1299         248 :     cimageCoord.setObsInfo(itsCoordSys.obsInfo());
    1300         248 :     cimageShape(2)=whichStokes.nelements();      
    1301             :     //cout << "Making forward grid of shape : " << cimageShape << " for imshape : " << itsImageShape << endl;
    1302         248 :     itsForwardGrid.reset( new TempImage<Complex>(TiledShape(cimageShape, tileShape()), cimageCoord, memoryBeforeLattice()) );
    1303             :     //if(image())
    1304         248 :     if(hasRestored()){
    1305          16 :       LatticeLocker lock1(*itsForwardGrid, FileLocker::Write);
    1306          16 :       itsForwardGrid->setImageInfo((image())->imageInfo());
    1307             : 
    1308          16 :     }
    1309         248 :     return itsForwardGrid;
    1310         248 :   }
    1311             : 
    1312        2680 :   std::shared_ptr<ImageInterface<Complex> > SIImageStore::backwardGrid(uInt /*nterm*/){
    1313        2680 :     if( itsBackwardGrid ) //&& (itsBackwardGrid->shape() == itsImageShape))
    1314             :       {
    1315             :         //      cout << "Backward grid has shape : " << itsBackwardGrid->shape() << endl;
    1316        2151 :         return itsBackwardGrid;
    1317             :       }
    1318         529 :     Vector<Int> whichStokes(0);
    1319         529 :     IPosition cimageShape;
    1320         529 :     cimageShape=itsImageShape;
    1321         529 :     MFrequency::Types freqframe = itsCoordSys.spectralCoordinate(itsCoordSys.findCoordinate(Coordinate::SPECTRAL)).frequencySystem(True);
    1322             :     // No need to set a conversion layer if image is in LSRK already or it is 'Undefined'
    1323         529 :     if(freqframe != MFrequency::LSRK && freqframe!=MFrequency::Undefined && freqframe!=MFrequency::REST ) 
    1324           0 :       { itsCoordSys.setSpectralConversion("LSRK"); }
    1325         529 :     CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord( itsCoordSys,
    1326         529 :                                                                   whichStokes, itsDataPolRep);
    1327         529 :     cimageCoord.setObsInfo(itsCoordSys.obsInfo());
    1328         529 :     cimageShape(2)=whichStokes.nelements();
    1329             :     //cout << "Making backward grid of shape : " << cimageShape << " for imshape : " << itsImageShape << endl;
    1330         529 :     itsBackwardGrid.reset( new TempImage<Complex>(TiledShape(cimageShape, tileShape()), cimageCoord, memoryBeforeLattice()) );
    1331             :     //if(image())
    1332         529 :     if(hasRestored()){
    1333           8 :       LatticeLocker lock1(*itsBackwardGrid, FileLocker::Write);
    1334           8 :       itsBackwardGrid->setImageInfo((image())->imageInfo());
    1335           8 :     }
    1336         529 :     return itsBackwardGrid;
    1337         529 :     }
    1338        2433 :   Double SIImageStore::memoryBeforeLattice(){
    1339             :           //Calculate how much memory to use per temporary images before disking
    1340        2433 :     return 1.0;  /// in MB
    1341             :   }
    1342        2433 :   IPosition SIImageStore::tileShape(){
    1343             :           //Need to have settable stuff here or algorith to determine this
    1344        2433 :           return IPosition(4, min(itsImageShape[0],1000), min(itsImageShape[1],1000), 1, 1);
    1345             :   }
    1346             : 
    1347             :   // TODO : Move to an image-wrapper class ? Same function exists in SynthesisDeconvolver.
    1348       46225 :   Bool SIImageStore::doesImageExist(String imagename)
    1349             :   {
    1350       92450 :     LogIO os( LogOrigin("SIImageStore","doesImageExist",WHERE) );
    1351       46225 :     Directory image( imagename );
    1352       92450 :     return image.exists();
    1353       46225 :   }
    1354             : 
    1355             : 
    1356           0 :   void SIImageStore::resetImages( Bool resetpsf, Bool resetresidual, Bool resetweight )
    1357             :   {
    1358           0 :     if( resetpsf ){
    1359           0 :       LatticeLocker lock1(*(psf()), FileLocker::Write);
    1360           0 :       psf()->set(0.0);
    1361             : 
    1362           0 :     }
    1363           0 :     if( resetresidual ) {
    1364             :       //      removeMask( residual() );
    1365           0 :       LatticeLocker lock1(*(residual()), FileLocker::Write);
    1366           0 :       residual()->set(0.0);
    1367           0 :     }
    1368           0 :     if( resetweight && itsWeight ){
    1369           0 :       LatticeLocker lock1(*(weight()), FileLocker::Write);
    1370           0 :       weight()->set(0.0);
    1371           0 :     }
    1372           0 :     if( resetweight ){
    1373           0 :       LatticeLocker lock1(*(sumwt()), FileLocker::Write);
    1374           0 :       sumwt()->set(0.0);
    1375           0 :     }
    1376           0 :   }
    1377             : 
    1378           0 :   void SIImageStore::addImages( std::shared_ptr<SIImageStore> imagestoadd,
    1379             :                                 Bool addpsf, Bool addresidual, Bool addweight, Bool adddensity)
    1380             :   {
    1381             : 
    1382           0 :     if(addpsf)
    1383             :       {
    1384           0 :         LatticeExpr<Float> adderPsf( *(psf()) + *(imagestoadd->psf()) ); 
    1385           0 :         psf()->copyData(adderPsf);
    1386           0 :       }
    1387           0 :     if(addresidual)
    1388             :       {
    1389           0 :         LatticeExpr<Float> adderRes( *(residual()) + *(imagestoadd->residual()) ); 
    1390           0 :         residual()->copyData(adderRes);
    1391           0 :       }
    1392           0 :     if(addweight)
    1393             :       {
    1394           0 :         if( getUseWeightImage( *(imagestoadd->sumwt()) ) ) // Access and add weight only if it is needed.
    1395             :           {
    1396           0 :             LatticeExpr<Float> adderWeight( *(weight()) + *(imagestoadd->weight()) ); 
    1397           0 :             weight()->copyData(adderWeight);
    1398           0 :           }
    1399             : 
    1400             :         /*
    1401             :         Array<Float> qqq, www;
    1402             :         imagestoadd->sumwt()->get(qqq,True);
    1403             :         sumwt()->get(www,True);
    1404             :         cout << "SUMWT : Adding : " << qqq << " to " << www << endl;
    1405             :         */
    1406             : 
    1407           0 :         LatticeExpr<Float> adderSumWt( *(sumwt()) + *(imagestoadd->sumwt()) ); 
    1408           0 :         sumwt()->copyData(adderSumWt);
    1409           0 :         setUseWeightImage( *sumwt(),  getUseWeightImage(*(imagestoadd->sumwt()) ) );
    1410             : 
    1411           0 :       }
    1412           0 :     if(adddensity)
    1413             :       {
    1414           0 :         LatticeExpr<Float> adderDensity( *(gridwt()) + *(imagestoadd->gridwt()) ); 
    1415           0 :         gridwt()->copyData(adderDensity);
    1416           0 :       }
    1417             : 
    1418           0 :   }
    1419             : 
    1420           0 : void SIImageStore::setWeightDensity( std::shared_ptr<SIImageStore> imagetoset )
    1421             :   {
    1422           0 :     LogIO os( LogOrigin("SIImageStore","setWeightDensity",WHERE) );
    1423             :     //gridwt()->copyData( LatticeExpr<Float> ( *(imagetoset->gridwt()) ) );
    1424             :     //looks like you have to call them before hand or it crashes in parallel sometimes
    1425           0 :     IPosition shape=(imagetoset->gridwt())->shape();
    1426           0 :     os << LogIO::DEBUG2 << "SHAPES " << imagetoset->gridwt()->shape() << "   " << gridwt()->shape() << endl;
    1427           0 :     (gridwt(shape))->copyData( LatticeExpr<Float> ( *(imagetoset->gridwt()) ) );
    1428             : 
    1429           0 :   }
    1430             : 
    1431             :   // TODO
    1432             :   //    cout << "WARN :   get getPbMax right for cube.... weight is indexed on chan and pol." << endl;
    1433         201 :   Double SIImageStore::getPbMax()
    1434             :   {
    1435             : 
    1436             :     //// Don't do any extra norm. Minor cycle will operate with native PB.
    1437             :     //return 1.0;
    1438             : 
    1439             :     //// Normalize PB to 1 at the center of the image OF CHANNEL ZERO
    1440             :     
    1441             :     //        IPosition shp = weight(0)->shape();
    1442             :     //     IPosition center(4, shp[0]/2, shp[1]/2,0,0);
    1443             :     //    return sqrt(   weight(0)->getAt( center )   );
    1444             :     
    1445             : 
    1446             :     //// Normalize PB to 1 at the location of the maximum (across all chans..)
    1447             :     
    1448         402 :     LatticeExprNode le( sqrt(max( *(weight(0)) )) );
    1449         402 :     return le.getFloat();
    1450             :     
    1451         201 :   }
    1452             : 
    1453        1558 :   Double SIImageStore::getPbMax(Int pol,Int chan)
    1454             :   {
    1455             : 
    1456             :     //// Normalize PB to 1 at the location of the maximum (per pol,chan)
    1457             :     
    1458        1558 :     CountedPtr<ImageInterface<Float> > subim=makeSubImage(0, 1,
    1459        1558 :                                                           chan, itsImageShape[3],
    1460        1558 :                                                           pol, itsImageShape[2],
    1461        3116 :                                                           *weight(0));
    1462             : 
    1463        3116 :     return sqrt(max(subim->get()));
    1464        1558 :   }
    1465             : 
    1466         140 :   void  SIImageStore::makePBFromWeight(const Float pblimit)
    1467             :   {
    1468         280 :    LogIO os( LogOrigin("SIImageStore","makePBFromWeight",WHERE) );
    1469             : 
    1470         297 :         for(Int pol=0; pol<itsImageShape[2]; pol++)
    1471             :           {
    1472         484 :                for(Int chan=0; chan<itsImageShape[3]; chan++)
    1473             :               {
    1474             : 
    1475         327 :                 itsPBScaleFactor = getPbMax(pol,chan);
    1476             :                 
    1477         327 :                 if(itsPBScaleFactor<=0){os << LogIO::NORMAL1 << "Skipping normalization for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;}
    1478             :                 else {
    1479             : 
    1480         320 :                   CountedPtr<ImageInterface<Float> > wtsubim=makeSubImage(0,1, 
    1481         320 :                                                                           chan, itsImageShape[3],
    1482         320 :                                                                           pol, itsImageShape[2], 
    1483         640 :                                                                           *weight() );
    1484         320 :                   CountedPtr<ImageInterface<Float> > pbsubim=makeSubImage(0,1, 
    1485         320 :                                                                           chan, itsImageShape[3],
    1486         320 :                                                                           pol, itsImageShape[2], 
    1487         640 :                                                                           *pb() );
    1488             :                   
    1489             :                   
    1490         640 :                   LatticeExpr<Float> normed( sqrt(abs(*wtsubim)) / itsPBScaleFactor  );
    1491         640 :                   LatticeExpr<Float> limited( iif( normed > fabs(pblimit) , normed, 0.0 ) );
    1492         320 :                   pbsubim->copyData( limited );
    1493         320 :                 }// if not zero
    1494             :               }
    1495             :           }
    1496             : 
    1497         140 :         if((pb()->getDefaultMask()==""))
    1498             :           {
    1499             :             //Remove the old mask as it is no longer valid
    1500             :             //removeMask( pb() );
    1501             : 
    1502             :             //      if( pblimit >= 0.0 )
    1503             :               {
    1504             :                 //MSK// 
    1505         222 :                 LatticeExpr<Bool> pbmask( iif( *pb() > fabs(pblimit) , True , False ) );
    1506             :                 //MSK// 
    1507         111 :                 createMask( pbmask, pb() );
    1508         111 :                 pb()->pixelMask().unlock();
    1509         111 :               }
    1510             : 
    1511             :           }
    1512         140 :         weight()->unlock();
    1513         140 :         pb()->unlock();
    1514         140 :   }
    1515             : 
    1516         607 :   void  SIImageStore::makePBImage(const Float pblimit)
    1517             :   {
    1518        1214 :    LogIO os( LogOrigin("SIImageStore","makePBImage",WHERE) );
    1519             : 
    1520         607 :    if( hasPB() )
    1521             :      {
    1522             : 
    1523        1352 :         for(Int pol=0; pol<itsImageShape[2]; pol++)
    1524             :           {
    1525        3518 :                for(Int chan=0; chan<itsImageShape[3]; chan++)
    1526             :               {
    1527             : 
    1528        2771 :                   CountedPtr<ImageInterface<Float> > pbsubim=makeSubImage(0,1, 
    1529        2771 :                                                                           chan, itsImageShape[3],
    1530        2771 :                                                                           pol, itsImageShape[2], 
    1531        5542 :                                                                           *pb() );
    1532             : 
    1533             :                   // Norm by the max
    1534        2771 :                   LatticeExprNode elmax= max( *pbsubim );
    1535        2771 :                   Float fmax = abs(elmax.getFloat());
    1536             :                   //If there are multiple overlap of beam such that the peak is larger than 1 then normalize
    1537             :                   //otherwise leave as is
    1538        2771 :                   if(fmax>1.0)
    1539             :                     {
    1540         238 :                       LatticeExpr<Float> normed( (*pbsubim) / fmax  );
    1541         238 :                       LatticeExpr<Float> limited( iif( normed > fabs(pblimit) , normed, 0.0 ) );
    1542         119 :                       pbsubim->copyData( limited );
    1543         119 :                     }
    1544             :                   else
    1545             :                     {
    1546        5304 :                       LatticeExpr<Float> limited( iif((*pbsubim) > fabs(pblimit) , (*pbsubim), 0.0 ) );
    1547        2652 :                       pbsubim->copyData( limited );
    1548        2652 :                     }
    1549        2771 :               }
    1550             :           }
    1551             : 
    1552         605 :         if((pb()->getDefaultMask()==""))// && pblimit >= 0.0)
    1553             :           {
    1554             :             //      removeMask( pb() );
    1555             :             //MSK//             
    1556        1172 :             LatticeExpr<Bool> pbmask( iif( *pb() > fabs(pblimit) , True , False ) );
    1557             :             //MSK// 
    1558         586 :             createMask( pbmask, pb() );
    1559         586 :             pb()->pixelMask().unlock();
    1560         586 :           }
    1561             : 
    1562             :      }// if hasPB
    1563         607 :    pb()->unlock();
    1564             : 
    1565         607 :   }
    1566             : 
    1567         960 :   Bool SIImageStore::createMask(LatticeExpr<Bool> &lemask, 
    1568             :                                 CountedPtr<ImageInterface<Float> > outimage)
    1569             :   {
    1570             :     //cout << "Calling makeMask for mask0 for " << outimage->name() << endl;
    1571             :     try
    1572             :       {
    1573         960 :         LatticeLocker lock1(*outimage, FileLocker::Write);
    1574         960 :         ImageRegion outreg = outimage->makeMask("mask0",False,True);
    1575         960 :         LCRegion& outmask=outreg.asMask();
    1576         960 :         outmask.copyData(lemask);
    1577         960 :         outimage->defineRegion("mask0",outreg, RegionHandler::Masks, True);
    1578             :         
    1579         960 :         outimage->setDefaultMask("mask0");
    1580             :         
    1581         960 :         outimage->unlock();
    1582         960 :         outimage->tempClose();
    1583             :         
    1584             :         //    outimage->table().unmarkForDelete();      
    1585         960 :       }
    1586           0 :     catch (const AipsError& x) {
    1587           0 :       throw(AipsError("Error in creating internal T/F mask : " + x.getMesg() ));
    1588           0 :     }
    1589             : 
    1590         960 :     return True;
    1591             :   }
    1592             : 
    1593        1885 :   Bool SIImageStore::copyMask(CountedPtr<ImageInterface<Float> > inimage,
    1594             :                                 CountedPtr<ImageInterface<Float> > outimage)
    1595             :   {
    1596             :     //    cout << "In copyMask for " << outimage->name() << endl;
    1597             : 
    1598             :     try
    1599             :       {
    1600        1885 :         if( (inimage->getDefaultMask()).matches("mask0") ) // input mask exists.
    1601        1675 :           {LatticeLocker lock1(*outimage, FileLocker::Write);
    1602        1675 :             removeMask(outimage);
    1603             :             
    1604             :             // // clear output image mask
    1605             :             // if( (outimage->getDefaultMask()).matches("mask0") ) 
    1606             :             //   {outimage->setDefaultMask(""); 
    1607             :             //  outimage->removeRegion("mask0");}
    1608             :             // get mask from input image
    1609             :             
    1610        1678 :             ImageRegion outreg=outimage->makeMask("mask0", False, True);
    1611        1672 :             LCRegion& outmask=outreg.asMask();
    1612        1672 :             outmask.copyData(inimage->getRegion("mask0").asLCRegion());
    1613        1672 :             outimage->defineRegion("mask0",outreg, RegionHandler::Masks,True);
    1614        1672 :             outimage->setDefaultMask("mask0");
    1615        1675 :           }
    1616             :       }
    1617           3 :     catch (const AipsError& x) {
    1618           3 :       throw(AipsError("Error in copying internal T/F mask : " + x.getMesg() ));
    1619           3 :     }
    1620             : 
    1621        1882 :     return True;
    1622             :   }
    1623             :   
    1624        2026 :   void SIImageStore::removeMask(CountedPtr<ImageInterface<Float> > im)
    1625             :   {
    1626             :     try
    1627             :       {
    1628             :         // // clear output image mask
    1629             :         // if( (im->getDefaultMask()).matches("mask0") ) 
    1630             :         //   {im->setDefaultMask(""); 
    1631             :         //      im->removeRegion("mask0");}
    1632             :         ///Remove the old mask as it is no longer valid
    1633        2026 :         LatticeLocker lock1(*im, FileLocker::Write);
    1634        2026 :         if (im-> getDefaultMask() != String(""))
    1635             :           {
    1636         410 :             String strung=im->getDefaultMask();
    1637         410 :             im->setDefaultMask("");
    1638         410 :             im->removeRegion(strung);
    1639         410 :           } 
    1640        2026 :         if( im->hasRegion("mask0") )
    1641             :           {
    1642           0 :             im->removeRegion("mask0");
    1643             :           }
    1644        2026 :       }
    1645           0 :     catch (const AipsError& x)
    1646             :       {
    1647           0 :         throw(AipsError("Error in deleting internal T/F mask : " + x.getMesg() ));
    1648           0 :       }
    1649        2026 :   } 
    1650         226 :   void SIImageStore:: rescaleResolution(Int chan, 
    1651             :                                         ImageInterface<Float>& image, 
    1652             :                                         const GaussianBeam& newbeam, 
    1653             :                                         const GaussianBeam& oldbeam){
    1654             : 
    1655         452 :     LogIO os( LogOrigin("SIImageStore","rescaleResolution",WHERE) );
    1656         452 :     GaussianBeam toBeUsed(Quantity(0.0, "arcsec"),Quantity(0.0, "arcsec"), 
    1657         678 :                           Quantity(0.0, "deg")) ;
    1658             :     try {
    1659         226 :       Bool samesize = GaussianDeconvolver::deconvolve(toBeUsed, newbeam, oldbeam);
    1660             : 
    1661             :       /*
    1662             :       os << LogIO::NORMAL2 << "Chan : " << chan << " : Input beam : : " << oldbeam.getMajor(Unit("arcsec")) << " arcsec, " << oldbeam.getMinor(Unit("arcsec"))<< " arcsec, " << oldbeam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    1663             :       os << LogIO::NORMAL2 << "Target beam : " << newbeam.getMajor(Unit("arcsec")) << " arcsec, " << newbeam.getMinor(Unit("arcsec"))<< " arcsec, " << newbeam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    1664             :       os << LogIO::NORMAL2 << "Beam to be used : " << toBeUsed.getMajor(Unit("arcsec")) << " arcsec, " << toBeUsed.getMinor(Unit("arcsec"))<< " arcsec, " << toBeUsed.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    1665             :       os << LogIO::NORMAL2 << "SameSize ? " << samesize << endl;
    1666             :       */
    1667             :       
    1668         225 :       if( samesize )
    1669             :         {
    1670           8 :           os << LogIO::NORMAL2 << "Input and output beam sizes are the same for Channel : " << chan << ". Not convolving residuals." << LogIO::POST;
    1671             :         }
    1672             :         else 
    1673             :         {
    1674         217 :           Double pixwidth=sqrt(image.coordinates().increment()(0)*image.coordinates().increment()(0)+image.coordinates().increment()(1)*image.coordinates().increment()(1));
    1675             :           
    1676         217 :           if(toBeUsed.getMinor(image.coordinates().worldAxisUnits()[0]) > pixwidth)
    1677             :             {
    1678             :               //cerr << "old beam area " << oldbeam.getArea("rad2") << " new beam " << newbeam.getArea("rad2") << endl;
    1679         211 :               StokesImageUtil::Convolve(image, toBeUsed, True);
    1680         211 :               image.copyData(LatticeExpr<Float>(image*newbeam.getArea("rad2")/ oldbeam.getArea("rad2")));
    1681             :             }
    1682             :         }
    1683             :     }
    1684           1 :     catch (const AipsError& x) {
    1685             :       //throw(AipsError("Cannot convolve to new beam: may be smaller than old beam : " + x.getMesg() ));
    1686           1 :       os << LogIO::WARN << "Cannot convolve to new beam for Channel : " << chan <<  " : " << x.getMesg() << LogIO::POST;
    1687           1 :     }
    1688             :     
    1689             : 
    1690         226 :   }
    1691             : 
    1692         738 :   void SIImageStore::divideWeightBySumwt()
    1693             :   {
    1694        1476 :     LogIO os(LogOrigin("SIImageStore", "divideWeightBySumWt", WHERE));
    1695             : 
    1696             :    
    1697         738 :     if( itsUseWeight )
    1698             :     { 
    1699             : 
    1700         136 :       divideImageByWeightVal( *weight() ); 
    1701             :     }
    1702             : 
    1703         738 :   }
    1704             :   
    1705             : 
    1706         630 :   void SIImageStore::dividePSFByWeight(const Float /* pblimit*/)
    1707             :   {
    1708        1260 :     LogIO os( LogOrigin("SIImageStore","dividePSFByWeight",WHERE) );
    1709             : 
    1710         630 :     LatticeLocker lock1 (*(psf()), FileLocker::Write);
    1711         630 :     normPSF();
    1712             :     //This bit us twice now...hiding this sensitivity division in psf division has wasted a few FTE days
    1713             :     // Leaving it commented so as it is a lesson of not what to do...
    1714             :     // moving it to its own function
    1715             :       //  if( itsUseWeight )
    1716             :    // { 
    1717             :         
    1718             :         //divideImageByWeightVal( *weight() ); 
    1719             :   //  }
    1720         630 :     (psf())->unlock();
    1721             :     
    1722         630 :   }
    1723             : 
    1724         639 :   void SIImageStore::normalizePrimaryBeam(const Float pblimit)
    1725             :   {
    1726        1278 :     LogIO os( LogOrigin("SIImageStore","normalizePrimaryBeam",WHERE) );
    1727             : 
    1728             :     //    cout << "In dividePSFByWeight : itsUseWeight : " << itsUseWeight << endl;
    1729         639 :     if( itsUseWeight )
    1730             :     { 
    1731             :         
    1732         213 :         for(Int pol=0; pol<itsImageShape[2]; pol++)
    1733             :           {
    1734         400 :             for(Int chan=0; chan<itsImageShape[3]; chan++)
    1735             :               {
    1736         285 :                 os << LogIO::NORMAL1 << "Scale factor for [C" +String::toString(chan) + ":P" + String::toString(pol) + "] to keep the model image w.r.to a PB of max=1 is " << getPbMax(pol,chan) << LogIO::POST;
    1737             :               }//chan
    1738             :           }//pol
    1739             : 
    1740          98 :         makePBFromWeight(pblimit);
    1741             :         
    1742             :     }//if itsUseWeight
    1743         541 :     else { makePBImage(pblimit); } // OR... just check that it exists already.
    1744         639 :     pb()->unlock();
    1745             :     
    1746         639 :    }
    1747             : 
    1748             :   // Make another for the PSF too.
    1749        1409 :   void SIImageStore::divideResidualByWeight(Float pblimit, String normtype) {
    1750             : 
    1751        2818 :     LogIO os(LogOrigin("SIImageStore", "divideResidualByWeight", WHERE));
    1752        1409 :     LatticeLocker lock1(*(residual()), FileLocker::Write);
    1753             : 
    1754         525 :     auto logTemplate = [&](Int const &chan, Int const &pol, string const &normalizer, string const &result) {
    1755         525 :       os << LogIO::NORMAL1
    1756        1050 :          << "[C" + String::toString(chan) + ":P" + String::toString(pol) + "] "
    1757        1050 :          << "Dividing " << itsImageName + String(".residual") << " by "
    1758             :          << "[ " << normalizer << " ] "
    1759        1575 :          << "to get " << result << "." << LogIO::POST;
    1760         525 :     };
    1761             : 
    1762             :     // Normalize by the sumwt, per plane. 
    1763        1409 :     Bool didNorm = divideImageByWeightVal(*residual());
    1764             : 
    1765        1409 :     if (itsUseWeight) {
    1766         416 :       for (Int pol = 0; pol < itsImageShape[2]; pol++) {
    1767         760 :         for (Int chan = 0; chan < itsImageShape[3]; chan++) {
    1768         538 :           itsPBScaleFactor = getPbMax(pol, chan);
    1769             : 
    1770         538 :           if (itsPBScaleFactor <= 0) {
    1771             :             os << LogIO::NORMAL1 
    1772             :                << "Skipping normalization for C:" << chan << " P:" << pol 
    1773          13 :                << " because pb max is zero " << LogIO::POST;
    1774             : 
    1775             :           } else {
    1776         525 :             CountedPtr<ImageInterface<Float> > wtsubim = makeSubImage(0, 1,
    1777         525 :                                                                       chan, itsImageShape[3],
    1778         525 :                                                                       pol, itsImageShape[2], 
    1779        1050 :                                                                       *weight());
    1780         525 :             CountedPtr<ImageInterface<Float> > ressubim = makeSubImage(0, 1,
    1781         525 :                                                                        chan, itsImageShape[3],
    1782         525 :                                                                        pol, itsImageShape[2], 
    1783        1050 :                                                                        *residual());
    1784         525 :             LatticeExpr<Float> ratio;
    1785         525 :             Float scalepb = 1.0;
    1786             : 
    1787         525 :             if (normtype == "flatnoise") {
    1788        1575 :               logTemplate(chan, pol,
    1789        1050 :                           "sqrt(weightimage) * " + String::toString(itsPBScaleFactor),
    1790             :                           "flat noise with unit pb peak");
    1791             : 
    1792        1050 :               LatticeExpr<Float> deno =  itsPBScaleFactor * sqrt(abs(LatticeExpr<Float>(*(wtsubim))));
    1793         525 :               scalepb = fabs(pblimit) * itsPBScaleFactor * itsPBScaleFactor;
    1794         525 :               ratio = iif(deno > scalepb, (*(ressubim) / deno), 0.0);
    1795             : 
    1796         525 :             } else if (normtype == "pbsquare") {
    1797           0 :               logTemplate(chan, pol,
    1798           0 :                           String::toString(itsPBScaleFactor),
    1799             :                           "optimal noise with unit pb peak");
    1800             : 
    1801           0 :               Float deno = itsPBScaleFactor * itsPBScaleFactor;
    1802           0 :               ratio = (*(ressubim) / deno);
    1803             : 
    1804           0 :             } else if (normtype == "flatsky") {
    1805           0 :               logTemplate(chan, pol, "weight", "flat sky");
    1806             : 
    1807           0 :               LatticeExpr<Float> deno = LatticeExpr<Float>(*(wtsubim));
    1808           0 :               scalepb = fabs(pblimit * pblimit) * itsPBScaleFactor * itsPBScaleFactor;
    1809           0 :               ratio = iif(deno > scalepb, (*(ressubim) / deno), 0.0);
    1810             : 
    1811           0 :             }
    1812             : 
    1813             :             //IPosition ip(4, itsImageShape[0] / 2, itsImageShape[1]/2, 0, 0);
    1814             :             //Float resval = ressubim->getAt(ip);
    1815             :             //LatticeExpr<Float> mask(iif((deno) > scalepb, 1.0, 0.0));
    1816             :             //LatticeExpr<Float> maskinv(iif((deno) > scalepb, 0.0, 1.0));
    1817             :             //LatticeExpr<Float> ratio(((*(ressubim)) * mask) / (deno + maskinv));
    1818             : 
    1819             :             //above blocks all sources outside minpb but visible with weight coverage
    1820             :             //which could be cleaned out...one could use below for that
    1821             :             //LatticeExpr<Float> ratio(iif(deno > scalepb, (*(ressubim)) / deno, *ressubim));
    1822             : 
    1823         525 :             ressubim->copyData(ratio);
    1824             : 
    1825             :             //cout << "Val of residual before|after normalizing at center for pol " << pol << " chan " << chan << " : " << resval << "|" << ressubim->getAt(ip) << " weight : " << wtsubim->getAt(ip) << endl;
    1826         525 :           } // if not zero
    1827             :         } //chan
    1828             :       } //pol
    1829             :     }
    1830             :     
    1831             :     // If no normalization happened, print a warning. The user must check if it's right or not.
    1832             :     // Or... later if we get a gridder that does pre-norms, this warning can go. 
    1833        1409 :     if ((didNorm | itsUseWeight) != True) {
    1834           0 :       os << LogIO::WARN << "No normalization done to residual" << LogIO::POST;
    1835             :     }
    1836             :     
    1837             :     ///// A T/F mask in the residual will confuse users looking at the interactive clean
    1838             :     ///// window
    1839        1409 :     if ((residual()->getDefaultMask() == "") && hasPB() && pblimit >=0.0) {
    1840         250 :       copyMask(pb(), residual());
    1841             :     }
    1842             : 
    1843        1409 :     if ((pblimit < 0.0) && (residual()->getDefaultMask()).matches("mask0")) {
    1844           1 :       removeMask(residual());
    1845             :     }
    1846             : 
    1847        1409 :     residual()->unlock();
    1848        1409 :   }
    1849             : 
    1850         155 :   void SIImageStore::divideResidualByWeightSD(Float pblimit) {
    1851             : 
    1852         310 :     LogIO os(LogOrigin("SIImageStore", "divideResidualByWeightSD", WHERE));
    1853         155 :     LatticeLocker lock1(*(residual()), FileLocker::Write);
    1854             : 
    1855         155 :     if (itsUseWeight) {
    1856         310 :       LatticeExpr<Float> deno = LatticeExpr<Float>(*weight());
    1857         310 :       LatticeExpr<Float> ratio = iif(deno > 0.0, *(residual()) / deno, 0.0);
    1858         155 :       residual()->copyData(ratio);
    1859         155 :     }
    1860             :     else {
    1861             :       // If no normalization happened, print a warning. The user must check if it's right or not.
    1862             :       // Or... later if we get a gridder that does pre-norms, this warning can go.
    1863           0 :       os << LogIO::WARN << "No normalization done to residual" << LogIO::POST;
    1864             :     }
    1865             : 
    1866             :     ///// A T/F mask in the residual will confuse users looking at the interactive clean
    1867             :     ///// window
    1868         155 :     if ((residual()->getDefaultMask() == "") && hasPB() && pblimit >=0.0) {
    1869           0 :       copyMask(pb(), residual());
    1870             :     }
    1871             : 
    1872         155 :     if ((pblimit < 0.0) && (residual()->getDefaultMask()).matches("mask0")) {
    1873           0 :       removeMask(residual());
    1874             :     }
    1875             : 
    1876         155 :     residual()->unlock();
    1877         155 :   }
    1878             : 
    1879         930 :   void SIImageStore::divideModelByWeight(Float pblimit, const String normtype)
    1880             :   {
    1881        1860 :     LogIO os( LogOrigin("SIImageStore","divideModelByWeight",WHERE) );
    1882             : 
    1883             :     
    1884        1860 :         if(itsUseWeight // only when needed
    1885         930 :            && weight() )// i.e. only when possible. For an initial starting model, don't need wt anyway.
    1886             :       {
    1887             : 
    1888         135 :         if( normtype=="flatsky") {
    1889             :          
    1890           0 :           LatticeExprNode LEN = max( *model());
    1891           0 :           os << LogIO::NORMAL1 << "Model is already flat sky with peak flux : " << LEN.getFloat();
    1892           0 :           os << ". No need to divide before prediction" << LogIO::POST;
    1893             :           
    1894           0 :           return;
    1895           0 :           }
    1896         135 :         else if( normtype=="flatnoise"){
    1897             : 
    1898         290 :           for(Int pol=0; pol<itsImageShape[2]; pol++)
    1899             :             {
    1900         509 :               for(Int chan=0; chan<itsImageShape[3]; chan++)
    1901             :                 {
    1902             :                   
    1903         354 :                   itsPBScaleFactor = getPbMax(pol,chan);
    1904             :                   //    cout << " pbscale : " << itsPBScaleFactor << endl;
    1905         354 :                 if(itsPBScaleFactor<=0){os << LogIO::NORMAL1 << "Skipping normalization for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;}
    1906             :                 else {
    1907             :                   
    1908         324 :                   CountedPtr<ImageInterface<Float> > wtsubim=makeSubImage(0,1, 
    1909         324 :                                                                           chan, itsImageShape[3],
    1910         324 :                                                                           pol, itsImageShape[2], 
    1911         648 :                                                                           *weight() );
    1912         324 :                   CountedPtr<ImageInterface<Float> > modsubim=makeSubImage(0,1, 
    1913         324 :                                                                            chan, itsImageShape[3],
    1914         324 :                                                                            pol, itsImageShape[2], 
    1915         648 :                                                                            *model() );
    1916         324 :                   os << LogIO::NORMAL1 ;
    1917         324 :                   os <<  "[C" +String::toString(chan) + ":P" + String::toString(pol) + "] ";
    1918         324 :                   os << "Dividing " << itsImageName+String(".model") ;
    1919         324 :                   os << " by [ sqrt(weight) / " << itsPBScaleFactor ;
    1920         324 :                   os <<" ] to get to flat sky model before prediction" << LogIO::POST;
    1921             :                   
    1922             :                  
    1923         648 :                   LatticeExpr<Float> deno( sqrt( abs(*(wtsubim)) ) / itsPBScaleFactor );
    1924             :                   
    1925         648 :                   LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
    1926         648 :                   LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
    1927         648 :                   LatticeExpr<Float> ratio( ( (*(modsubim)) * mask ) / ( deno + maskinv ) );
    1928             :                   
    1929             :                   // 
    1930             :                   //The above has a problem...mask is cutting out clean components found 
    1931             :                   // outside pblimit ...use below if this is what is wanted
    1932             :         //LatticeExpr<Float> ratio(iif(sqrt(abs(*(wtsubim))) < (fabs(pblimit)*itsPBScaleFactor), 0.0,  (*(modsubim))/(sqrt( abs(*(wtsubim)))  / itsPBScaleFactor))); 
    1933             :                   // LatticeExpr<Float> ratio(iif((sqrt(abs(*(wtsubim))) ==0.0), 0.0,  ((*(modsubim))*itsPBScaleFactor)/sqrt( abs(*(wtsubim))) ));
    1934             :                   
    1935         324 :                   IPosition ip(4,itsImageShape[0]/2,itsImageShape[1]/2,0,0);
    1936             :                   ///             Float modval = modsubim->getAt(ip);
    1937             :                   //LatticeExprNode aminval( min(*modsubim) );
    1938             :                   //LatticeExprNode amaxval( max(*modsubim) );
    1939             :                   //cout << "Before ---- min : " << aminval.getFloat() << " max : " << amaxval.getFloat() << endl;
    1940             : 
    1941         324 :                   modsubim->copyData(ratio);
    1942             :                   //              cout << "Val of model before|after flattening at center for pol " << pol << " chan " << chan << " : " << modval << "|" << modsubim->getAt(ip) << " weight : " << wtsubim->getAt(ip) << endl;
    1943             :                   //LatticeExprNode minval( min(*modsubim) );
    1944             :                   //LatticeExprNode maxval( max(*modsubim) );
    1945             :                   //cout << "After ---- min : " << minval.getFloat() << " max : " << maxval.getFloat() << endl;
    1946         324 :                 }// if not zero
    1947             :                 }//chan
    1948             :             }//pol
    1949             : 
    1950             :         }
    1951           0 :         else if( normtype=="pbsquare"){
    1952             : 
    1953           0 :           for(Int pol=0; pol<itsImageShape[2]; pol++)
    1954             :             {
    1955           0 :               for(Int chan=0; chan<itsImageShape[3]; chan++)
    1956             :                 {
    1957             :                   
    1958           0 :                   itsPBScaleFactor = getPbMax(pol,chan);
    1959             :                   //    cout << " pbscale : " << itsPBScaleFactor << endl;
    1960           0 :                 if(itsPBScaleFactor<=0){os << LogIO::NORMAL1 << "Skipping normalization for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;}
    1961             :                 else {
    1962             :                   
    1963           0 :                   CountedPtr<ImageInterface<Float> > wtsubim=makeSubImage(0,1, 
    1964           0 :                                                                           chan, itsImageShape[3],
    1965           0 :                                                                           pol, itsImageShape[2], 
    1966           0 :                                                                           *weight() );
    1967           0 :                   CountedPtr<ImageInterface<Float> > modsubim=makeSubImage(0,1, 
    1968           0 :                                                                            chan, itsImageShape[3],
    1969           0 :                                                                            pol, itsImageShape[2], 
    1970           0 :                                                                            *model() );
    1971           0 :                   os << LogIO::NORMAL1 ;
    1972           0 :                   os <<  "[C" +String::toString(chan) + ":P" + String::toString(pol) + "] ";
    1973           0 :                   os << "Dividing " << itsImageName+String(".model") ;
    1974           0 :                   os << " by [ (weight) / " << itsPBScaleFactor ;
    1975           0 :                   os <<" ] to restore to optimal sky model before prediction" << LogIO::POST;
    1976             :                   
    1977             :                    
    1978           0 :                   LatticeExpr<Float> deno(  abs(*(wtsubim))  / (itsPBScaleFactor*itsPBScaleFactor) );
    1979             :                   
    1980           0 :                   LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
    1981           0 :                   LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
    1982           0 :                   LatticeExpr<Float> ratio( ( (*(modsubim)) * mask ) / ( deno + maskinv ) );
    1983             :                   
    1984             :                   // 
    1985             :                   //The above has a problem...mask is cutting out clean components found 
    1986             :                   // outside pblimit ...use below if this is what is wanted
    1987             :                   // LatticeExpr<Float> ratio(iif(abs(*(wtsubim)) == 0.0, *modsubim,  (*(modsubim))/( abs(*(wtsubim))  / (itsPBScaleFactor*itsPBScaleFactor)))); 
    1988             :                   
    1989           0 :                   IPosition ip(4,itsImageShape[0]/2,itsImageShape[1]/2,0,0);
    1990             :                   ///             Float modval = modsubim->getAt(ip);
    1991             :                   //LatticeExprNode aminval( min(*modsubim) );
    1992             :                   //LatticeExprNode amaxval( max(*modsubim) );
    1993             :                   //cout << "Before ---- min : " << aminval.getFloat() << " max : " << amaxval.getFloat() << endl;
    1994             : 
    1995           0 :                   modsubim->copyData(ratio);
    1996             :                   
    1997             :                   //              cout << "Val of model before|after flattening at center for pol " << pol << " chan " << chan << " : " << modval << "|" << modsubim->getAt(ip) << " weight : " << wtsubim->getAt(ip) << endl;
    1998             :                   //LatticeExprNode minval( min(*modsubim) );
    1999             :                   //LatticeExprNode maxval( max(*modsubim) );
    2000             :                   //cout << "After ---- min : " << minval.getFloat() << " max : " << maxval.getFloat() << endl;
    2001           0 :                 }// if not zero
    2002             :                 }//chan
    2003             :             }//pol
    2004             : 
    2005             :         }
    2006             : 
    2007             :         //      storeImg(String("flatmodel.im"), *model());
    2008             :         
    2009             :       }
    2010         930 :     }
    2011             :   
    2012         838 :   void SIImageStore::multiplyModelByWeight(Float pblimit, const String normtype)
    2013             :   {
    2014        1676 :    LogIO os( LogOrigin("SIImageStore","multiplyModelByWeight",WHERE) );
    2015             : 
    2016        1676 :         if(itsUseWeight // only when needed
    2017         838 :            && weight() )// i.e. only when possible. For an initial starting model, don't need wt anyway.
    2018             :       {
    2019          42 :         if( normtype=="flatsky") {
    2020           0 :           os << "Model is already flat sky. No need to multiply back after prediction" << LogIO::POST;
    2021           0 :           return;
    2022             :           }
    2023          42 :         else if( normtype=="flatnoise"){
    2024             : 
    2025          96 :           for(Int pol=0; pol<itsImageShape[2]; pol++)
    2026             :             {
    2027         108 :               for(Int chan=0; chan<itsImageShape[3]; chan++)
    2028             :                 {
    2029             :                   
    2030          54 :                   itsPBScaleFactor = getPbMax(pol,chan);
    2031             :                   //    cout << " pbscale : " << itsPBScaleFactor << endl;
    2032          54 :                 if(itsPBScaleFactor<=0){os << LogIO::NORMAL1 << "Skipping normalization for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;}
    2033             :                 else {
    2034             :                   
    2035          50 :                   CountedPtr<ImageInterface<Float> > wtsubim=makeSubImage(0,1, 
    2036          50 :                                                                           chan, itsImageShape[3],
    2037          50 :                                                                           pol, itsImageShape[2], 
    2038         100 :                                                                           *weight() );
    2039          50 :                   CountedPtr<ImageInterface<Float> > modsubim=makeSubImage(0,1, 
    2040          50 :                                                                            chan, itsImageShape[3],
    2041          50 :                                                                            pol, itsImageShape[2], 
    2042         100 :                                                                            *model() );
    2043             : 
    2044             :                  
    2045             : 
    2046          50 :                   os << LogIO::NORMAL1 ;
    2047          50 :                   os <<  "[C" +String::toString(chan) + ":P" + String::toString(pol) + "] ";
    2048          50 :                   os << "Multiplying " << itsImageName+String(".model") ;
    2049          50 :                   os << " by [ sqrt(weight) / " << itsPBScaleFactor;
    2050          50 :                   os <<  " ] to take model back to flat noise with unit pb peak." << LogIO::POST;
    2051             : 
    2052         100 :                   LatticeExpr<Float> deno( sqrt( abs(*(wtsubim)) ) / itsPBScaleFactor );
    2053             :                   
    2054         100 :                   LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
    2055         100 :                   LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
    2056         100 :                   LatticeExpr<Float> ratio( ( (*(modsubim)) * mask ) * ( deno + maskinv ) );
    2057             :                  
    2058             :                   /////See comment in divmodel and divresidual for below usage 
    2059             :                   //LatticeExpr<Float> ratio ( (*(modsubim)) * sqrt( abs(*(wtsubim)))  / itsPBScaleFactor );
    2060          50 :                   modsubim->copyData(ratio);
    2061             :       
    2062          50 :                 }// if not zero
    2063             :                 }//chan
    2064             :             }//pol
    2065             :         }
    2066           0 :         else if( normtype=="pbsquare"){
    2067             : 
    2068           0 :           for(Int pol=0; pol<itsImageShape[2]; pol++)
    2069             :             {
    2070           0 :               for(Int chan=0; chan<itsImageShape[3]; chan++)
    2071             :                 {
    2072             :                   
    2073           0 :                   itsPBScaleFactor = getPbMax(pol,chan);
    2074             :                   //    cout << " pbscale : " << itsPBScaleFactor << endl;
    2075           0 :                 if(itsPBScaleFactor<=0){os << LogIO::NORMAL1 << "Skipping normalization for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;}
    2076             :                 else {
    2077             :                   
    2078           0 :                   CountedPtr<ImageInterface<Float> > wtsubim=makeSubImage(0,1, 
    2079           0 :                                                                           chan, itsImageShape[3],
    2080           0 :                                                                           pol, itsImageShape[2], 
    2081           0 :                                                                           *weight() );
    2082           0 :                   CountedPtr<ImageInterface<Float> > modsubim=makeSubImage(0,1, 
    2083           0 :                                                                            chan, itsImageShape[3],
    2084           0 :                                                                            pol, itsImageShape[2], 
    2085           0 :                                                                            *model() );
    2086             : 
    2087             :                  
    2088             : 
    2089           0 :                   os << LogIO::NORMAL1 ;
    2090           0 :                   os <<  "[C" +String::toString(chan) + ":P" + String::toString(pol) + "] ";
    2091           0 :                   os << "Multiplying " << itsImageName+String(".model") ;
    2092           0 :                   os << " by [ weight / " << itsPBScaleFactor*itsPBScaleFactor;
    2093           0 :                   os <<  " ] to take model back to flat noise with unit pb peak." << LogIO::POST;
    2094             :                           
    2095           0 :                   LatticeExpr<Float> deno(  abs(*(wtsubim))  / (itsPBScaleFactor*itsPBScaleFactor) );
    2096             :                   
    2097           0 :                   LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
    2098           0 :                   LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
    2099           0 :                   LatticeExpr<Float> ratio( ( (*(modsubim)) * mask ) * ( deno + maskinv ) );
    2100             :                  
    2101             :                   /////See comment in divmodel and divresidual for below usage 
    2102             :                   //LatticeExpr<Float> ratio ( (*(modsubim)) * sqrt( abs(*(wtsubim))  / itsPBScaleFactor) );
    2103           0 :                   modsubim->copyData(ratio);
    2104           0 :                 }// if not zero
    2105             :                 }//chan
    2106             :             }//pol
    2107             :         }       
    2108             :       }
    2109         838 :   }
    2110             :   
    2111           0 :   GaussianBeam SIImageStore::getPSFGaussian(Float psfcutoff)
    2112             :   {
    2113           0 :     GaussianBeam beam;
    2114             :     try
    2115             :       {
    2116           0 :         if( psf()->ndim() > 0 )
    2117             :           {
    2118           0 :           LatticeLocker lock2 (*(psf()), FileLocker::Read);
    2119           0 :           StokesImageUtil::FitGaussianPSF( *(psf()), beam, psfcutoff);
    2120           0 :           }
    2121             :       }
    2122           0 :     catch(AipsError &x)
    2123             :       {
    2124             :         //      LogIO os( LogOrigin("SIImageStore","getPSFGaussian",WHERE) );
    2125             :         //      os << "Error in fitting a Gaussian to the PSF : " << x.getMesg() << LogIO::POST;
    2126           0 :         throw( AipsError("Error in fitting a Gaussian to the PSF : " + x.getMesg()) );
    2127           0 :       }
    2128             : 
    2129           0 :     return beam;
    2130           0 :   }
    2131             : 
    2132        1890 :   void SIImageStore::makeImageBeamSet(Float psfcutoff, const Bool forcefit)
    2133             :   {
    2134        1890 :     clock_t begin = clock();
    2135             :       
    2136        3780 :     LogIO os( LogOrigin("SIImageStore","getPSFGaussian",WHERE) );
    2137             :     // For all chans/pols, call getPSFGaussian() and put it into ImageBeamSet(chan,pol).
    2138        1890 :     AlwaysAssert( itsImageShape.nelements() == 4, AipsError );
    2139        1890 :     uInt nx = itsImageShape[0];
    2140        1890 :     uInt ny = itsImageShape[1];
    2141        1890 :     uInt npol = itsImageShape[2];
    2142        1890 :     uInt nchan = itsImageShape[3];
    2143        1890 :     ImageInfo ii = psf()->imageInfo();
    2144        1890 :     ImageBeamSet iibeamset=ii.getBeamSet();
    2145        1890 :     if(iibeamset.nchan()==nchan && iibeamset.nstokes()==npol && forcefit==False){
    2146        1122 :       itsPSFBeams=iibeamset;
    2147        1122 :       itsRestoredBeams=iibeamset;
    2148        1122 :       return;
    2149             :     }
    2150         768 :     itsPSFBeams.resize( nchan, npol );
    2151         768 :     itsRestoredBeams.resize(nchan, npol);
    2152             :     //    cout << "makeImBeamSet : imshape : " << itsImageShape << endl;
    2153             : 
    2154         768 :     String blankpsfs="";
    2155        3602 :     for( uInt chanid=0; chanid<nchan;chanid++) {
    2156        5964 :       for( uInt polid=0; polid<npol; polid++ ) {
    2157        3130 :     LatticeLocker lock2 (*(psf()), FileLocker::Read);
    2158             : 
    2159        3130 :         IPosition substart(4,0,0,polid,chanid);
    2160        3130 :         IPosition substop(4,nx-1,ny-1,polid,chanid);
    2161        3130 :         Slicer psfslice(substart, substop,Slicer::endIsLast);
    2162        6260 :         SubImage<Float> subPsf( *psf() , psfslice, True );
    2163        3130 :         GaussianBeam beam;
    2164             : 
    2165        3130 :         Bool tryfit=True;
    2166             :         
    2167        3130 :         LatticeExprNode le( max(subPsf) );
    2168        3130 :         tryfit = le.getFloat()>0.0;
    2169        3130 :         if(tryfit)
    2170             :           {
    2171             :             try
    2172             :               {
    2173        3016 :                 StokesImageUtil::FitGaussianPSF( subPsf, beam,psfcutoff );
    2174        3016 :                 itsPSFBeams.setBeam( chanid, polid, beam );
    2175        3016 :                 itsRestoredBeams.setBeam(chanid, polid, beam);
    2176             :               }
    2177           0 :             catch(AipsError &x)
    2178             :               {
    2179           0 :                 os << LogIO::WARN << "[Chan" << chanid << ":Pol" << polid << "] Error Gaussian fit to PSF : " << x.getMesg() ;
    2180             :                 //              os << LogIO::POST;
    2181           0 :                 os << " :  Setting restoring beam to largest valid beam." << LogIO::POST;
    2182           0 :               }
    2183             :           }
    2184             :         else
    2185             :           {
    2186             :             //      os << LogIO::WARN << "[Chan" << chanid << ":Pol" << polid << "] PSF is blank. Setting null restoring beam." << LogIO::POST ;
    2187         114 :             blankpsfs += "[C" +String::toString(chanid) + ":P" + String::toString(polid) + "] ";
    2188             :           }
    2189             : 
    2190        3130 :       }// end of pol loop
    2191             :     }// end of chan loop
    2192             : 
    2193         768 :     if( blankpsfs.length() >0 )
    2194          43 :       os << LogIO::WARN << "PSF is blank for" << blankpsfs << LogIO::POST;
    2195             : 
    2196             :     //// Replace null (and bad) beams with the good one. 
    2197             :     ////GaussianBeam maxbeam = findGoodBeam(True);
    2198             : 
    2199             :     //// Replace null beams by a tiny tiny beam, just to get past the ImageInfo restriction that
    2200             :     //// all planes must have non-null beams.
    2201             :     
    2202         768 :     GaussianBeam defaultbeam=itsPSFBeams.getMaxAreaBeam();
    2203             :     ///many of the unittests in tsdimaging seem to depend on having 0 area beams
    2204             :     ///which throws and exception when it is stored in the image
    2205             :     ///(so setting them to some small number)!
    2206         768 :     if(defaultbeam.getArea("rad2")==0.0){
    2207           7 :       Quantity majax(1e-06,"arcsec"),minax(1e-06,"arcsec"),pa(0.0,"deg");
    2208           7 :       defaultbeam.setMajorMinor(majax,minax);
    2209           7 :       defaultbeam.setPA(pa);
    2210           7 :     }
    2211        3602 :     for( uInt chanid=0; chanid<nchan;chanid++) {
    2212        5964 :       for( uInt polid=0; polid<npol; polid++ ) {
    2213        3130 :         if( (itsPSFBeams.getBeam(chanid, polid)).isNull() ) 
    2214         114 :           { itsPSFBeams.setBeam( chanid, polid, defaultbeam );
    2215         114 :             itsRestoredBeams.setBeam( chanid, polid, defaultbeam );
    2216             :           }
    2217             :       }// end of pol loop
    2218             :     }// end of chan loop
    2219             :     
    2220             :     /*        
    2221             :     //// Fill in gaps if there are any --- with the MAX Area beam. 
    2222             :     /////    GaussianBeam maxbeam = itsPSFBeams.getMaxAreaBeam();
    2223             :     if( maxbeam.isNull() ) {
    2224             :         os << LogIO::WARN << "No planes have non-zero restoring beams. Forcing artificial 1.0arcsec beam." << LogIO::POST;
    2225             :         Quantity majax(1.0,"arcsec"),minax(1.0,"arcsec"),pa(0.0,"deg");
    2226             :         maxbeam.setMajorMinor(majax,minax);
    2227             :         maxbeam.setPA(pa);
    2228             :       }
    2229             :     else  {
    2230             :         for( Int chanid=0; chanid<nchan;chanid++) {
    2231             :           for( Int polid=0; polid<npol; polid++ ) {
    2232             :             if( (itsPSFBeams.getBeam(chanid, polid)).isNull() ) 
    2233             :               { itsPSFBeams.setBeam( chanid, polid, maxbeam ); }
    2234             :           }// end of pol loop
    2235             :         }// end of chan loop
    2236             :       }
    2237             :     */
    2238             : 
    2239             : 
    2240             :     /// For lack of a better place, store this inside the PSF image. To be read later and used to restore
    2241             :    
    2242         768 :     ii.setBeams( itsPSFBeams );
    2243             :     {
    2244         768 :       LatticeLocker lock1(*(psf()), FileLocker::Write);
    2245         768 :       psf()->setImageInfo(ii);
    2246         768 :       psf()->unlock();
    2247         768 :     }
    2248         768 :     clock_t end = clock();
    2249         768 :     os << LogIO::NORMAL << "Time to fit Gaussian to PSF " << double(end - begin) / CLOCKS_PER_SEC << LogIO::POST;
    2250        4134 :   }// end of make beam set
    2251             : 
    2252             : 
    2253           0 :   ImageBeamSet SIImageStore::getChannelBeamSet(const Int channel){
    2254             : 
    2255           0 :     return getChannelSliceBeamSet(channel, channel);
    2256             :   }
    2257             : 
    2258             : 
    2259           0 :   ImageBeamSet SIImageStore::getChannelSliceBeamSet(const Int begChan, const Int endChan){
    2260           0 :      ImageBeamSet bs=getBeamSet();
    2261           0 :     if(bs.shape()[0]==1)
    2262           0 :       return bs;
    2263           0 :     if(begChan > endChan || begChan <0)
    2264           0 :       throw(AipsError("Inconsistent slice of beam in channel requested"));
    2265           0 :     if(bs.shape()[0] < (endChan-1))
    2266           0 :       throw(AipsError("beam of channel "+String::toString(endChan)+" does not exist"));
    2267           0 :     IPosition blc(2, begChan, 0);
    2268           0 :     IPosition trc(2, endChan, bs.shape()[1]-1);
    2269           0 :     Matrix<GaussianBeam> sliceBeam=bs.getBeams()(blc, trc);
    2270           0 :     ImageBeamSet subBeamSet(sliceBeam);
    2271           0 :     return subBeamSet;
    2272             : 
    2273           0 :   }
    2274         276 :   void SIImageStore::setBeamSet(const ImageBeamSet& bs){
    2275             : 
    2276         276 :     itsPSFBeams=bs;
    2277         276 :   }
    2278             :   
    2279        1123 :   ImageBeamSet SIImageStore::getBeamSet(Float psfcutoff)
    2280             :   {
    2281        1123 :     IPosition beamshp = itsPSFBeams.shape();
    2282        1123 :     AlwaysAssert( beamshp.nelements()==2 , AipsError );
    2283        1123 :     if( beamshp[0]==0 || beamshp[1]==0 ) {makeImageBeamSet(psfcutoff);}
    2284        2246 :     return itsPSFBeams; 
    2285        1123 :   }
    2286             : 
    2287         773 :   void SIImageStore::printBeamSet(Bool verbose)
    2288             :   {
    2289        1546 :     LogIO os( LogOrigin("SIImageStore","printBeamSet",WHERE) );
    2290         773 :     AlwaysAssert( itsImageShape.nelements() == 4, AipsError );
    2291         773 :     if( itsImageShape[3] == 1 && itsImageShape[2]==1 )
    2292             :       {
    2293         434 :         GaussianBeam beam = itsPSFBeams.getBeam();
    2294         434 :         os << "Beam : " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2295         434 :  }
    2296             :     else
    2297             :       {
    2298             :         // per CAS-11415, verbose=True when restoringbeam='common'
    2299         339 :         if( verbose ) 
    2300             :           {
    2301           9 :             ostringstream oss;
    2302           9 :             oss<<"Beam";
    2303           9 :             Int nchan = itsImageShape[3];
    2304         189 :             for( Int chanid=0; chanid<nchan;chanid++) {
    2305         180 :               Int polid=0;
    2306             :               //          for( Int polid=0; polid<npol; polid++ ) {
    2307         180 :               GaussianBeam beam = itsPSFBeams.getBeam( chanid, polid );
    2308         180 :               oss << " [C" << chanid << "]: " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg";
    2309         180 :             }//for chanid
    2310           9 :             os << oss.str() << LogIO::POST;
    2311           9 :           }
    2312             :         else 
    2313             :           { 
    2314             :         // TODO : Enable this, when this function doesn't complain about 0 rest freq.
    2315             :         //                                 or when rest freq is never zero !
    2316             :         try{
    2317         330 :                 itsPSFBeams.summarize( os, False, itsCoordSys );
    2318             :                 // per CAS-11415 request, not turn on this one (it prints out per-channel beam in each line in the logger)
    2319             :                 //itsPSFBeams.summarize( os, verbose, itsCoordSys );
    2320             :         }
    2321           0 :         catch(AipsError &x)
    2322             :           {
    2323           0 :             os << LogIO::WARN << "Error while printing (compact) restoring beam summary : " <<  x.getMesg() << LogIO::POST;
    2324           0 :             os << "Printing long summary" << LogIO::POST;
    2325             :             
    2326           0 :             AlwaysAssert( itsImageShape.nelements() == 4, AipsError );
    2327             :             //Int npol = itsImageShape[2];
    2328           0 :             Int nchan = itsImageShape[3];
    2329           0 :             for( Int chanid=0; chanid<nchan;chanid++) {
    2330           0 :               Int polid=0;
    2331             :               //          for( Int polid=0; polid<npol; polid++ ) {
    2332           0 :               GaussianBeam beam = itsPSFBeams.getBeam( chanid, polid );
    2333           0 :               os << "Beam [C" << chanid << "]: " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2334             :               //}//for polid
    2335           0 :             }//for chanid
    2336           0 :           }// catch
    2337             :         }
    2338             :       }
    2339         773 :   }
    2340             :   
    2341             :   /////////////////////////////// Restore all planes.
    2342             : 
    2343         927 :   void SIImageStore::restore(GaussianBeam& rbeam, String& usebeam, uInt term, Float psfcutoff)
    2344             :   {
    2345        1854 :     LogIO os( LogOrigin("SIImageStore","restore",WHERE) );
    2346             :     //     << ". Optionally, PB-correct too." << LogIO::POST;
    2347             : 
    2348         927 :     AlwaysAssert( itsImageShape.nelements() == 4, AipsError );
    2349         927 :     Int nx = itsImageShape[0];
    2350         927 :     Int ny = itsImageShape[1];
    2351         927 :     Int npol = itsImageShape[2];
    2352         927 :     Int nchan = itsImageShape[3];
    2353             : 
    2354             :     /*    if( !hasResidualImage() )
    2355             :       {
    2356             :         // Cannot restore without residual/dirty image.
    2357             :         os << "Cannot restore without residual image" << LogIO::POST;
    2358             :         return;
    2359             :       }
    2360             :     */
    2361             : 
    2362             :     //// Get/fill the beamset
    2363         927 :     IPosition beamset = itsPSFBeams.shape();
    2364         927 :     AlwaysAssert( beamset.nelements()==2 , AipsError );
    2365         927 :     if( beamset[0] != nchan || beamset[1] != npol )
    2366             :       {
    2367             :         
    2368             :         // Get PSF Beams....
    2369         253 :         ImageInfo ii = psf()->imageInfo();
    2370         253 :         itsPSFBeams = ii.getBeamSet();
    2371         253 :         itsRestoredBeams=itsPSFBeams;
    2372         253 :         IPosition beamset2 = itsPSFBeams.shape();
    2373             : 
    2374         253 :         AlwaysAssert( beamset2.nelements()==2 , AipsError );
    2375         253 :         if( beamset2[0] != nchan || beamset2[1] != npol )
    2376             :           {
    2377             :             // Make new beams.
    2378           0 :             os << LogIO::WARN << "Couldn't find pre-computed restoring beams. Re-fitting." << LogIO::POST;
    2379           0 :             makeImageBeamSet(psfcutoff);
    2380             :           }
    2381         253 :       }
    2382             : 
    2383             :     // toggle for printing common beam to the log 
    2384         927 :     Bool printcommonbeam(False);
    2385             :     //// Modify the beamset if needed
    2386             :     //// if ( rbeam is Null and usebeam=="" ) Don't do anything.
    2387             :     //// If rbeam is Null but usebeam=='common', calculate a common beam and set 'rbeam'
    2388             :     //// If rbeam is given (or exists due to 'common'), just use it.
    2389         927 :     if( rbeam.isNull() && usebeam=="common") {
    2390          12 :       os << "Getting common beam" << LogIO::POST;
    2391          12 :       rbeam = CasaImageBeamSet(itsPSFBeams).getCommonBeam();
    2392          12 :       os << "Common Beam : " << rbeam.getMajor(Unit("arcsec")) << " arcsec, " << rbeam.getMinor(Unit("arcsec"))<< " arcsec, " << rbeam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2393          12 :       printcommonbeam=True;
    2394             :     }
    2395         927 :     if( !rbeam.isNull() ) {
    2396             :       /*for( Int chanid=0; chanid<nchan;chanid++) {
    2397             :         for( Int polid=0; polid<npol; polid++ ) {
    2398             :           itsPSFBeams.setBeam( chanid, polid, rbeam );
    2399             :           /// Still need to add the 'common beam' option.
    2400             :         }//for chanid
    2401             :       }//for polid
    2402             :       */
    2403          17 :       itsRestoredBeams=ImageBeamSet(rbeam);
    2404          17 :       GaussianBeam beam = itsRestoredBeams.getBeam();
    2405             :      
    2406             :       //if commonbeam has not printed in the log
    2407          17 :       if (!printcommonbeam) {
    2408           5 :         os << "Common Beam : " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2409           5 :       printcommonbeam=True; // to avoid duplicate the info is printed to th elog
    2410             :       }
    2411          17 :     }// if rbeam not NULL
    2412             :     //// Done modifying beamset if needed
    2413             : 
    2414             : 
    2415             :     /// Before restoring, check for an empty model image and don't convolve (but still smooth residuals)
    2416             :     /// (for CAS-8271 : make output restored image even if .model is zero... )
    2417         927 :     Bool emptymodel = isModelEmpty();
    2418         927 :     if(emptymodel) os << LogIO::WARN << "Restoring with an empty model image. Only residuals will be processed to form the output restored image." << LogIO::POST;
    2419             : 
    2420             : 
    2421         927 :     LatticeLocker lock1(*(image(term)), FileLocker::Write);
    2422         927 :     LatticeLocker lock2(*(residual(term)), FileLocker::Write);
    2423         927 :     LatticeLocker lock3(*(model(term)), FileLocker::Read);
    2424             :     //// Use beamset to restore
    2425        3839 :     for( Int chanid=0; chanid<nchan;chanid++) {
    2426        6111 :       for( Int polid=0; polid<npol; polid++ ) {
    2427             :         
    2428        3199 :         IPosition substart(4,0,0,polid,chanid);
    2429        3199 :         IPosition substop(4,nx-1,ny-1,polid,chanid);
    2430        3199 :         Slicer imslice(substart, substop,Slicer::endIsLast);             
    2431        6398 :         SubImage<Float> subRestored( *image(term) , imslice, True );
    2432        6398 :         SubImage<Float> subModel( *model(term) , imslice, False );
    2433        6398 :         SubImage<Float> subResidual( *residual(term) , imslice, True );
    2434             :         
    2435        3199 :         GaussianBeam beam = itsRestoredBeams.getBeam( chanid, polid );;
    2436             :         //os << "Common Beam for chan : " << chanid << " : " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2437             :         // only print per-chan beam if the common beam is not used for restoring beam
    2438        3199 :         if(!printcommonbeam) { 
    2439        2973 :           os << "Beam for chan : " << chanid << " : " << beam.getMajor(Unit("arcsec")) << " arcsec, " << beam.getMinor(Unit("arcsec"))<< " arcsec, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2440             :         }
    2441             : 
    2442             :         try
    2443             :           {
    2444             :             // Initialize restored image
    2445        3199 :             subRestored.set(0.0);
    2446        3199 :              if( !emptymodel ) { 
    2447             :                // Copy model into it
    2448        2854 :                subRestored.copyData( LatticeExpr<Float>( subModel )  );
    2449             :                // Smooth model by beam
    2450        2854 :                StokesImageUtil::Convolve( subRestored, beam);
    2451             :              }
    2452             :             // Add residual image
    2453        3199 :             if( !rbeam.isNull() || usebeam == "common") // If need to rescale residuals, make a copy and do it.
    2454             :               {
    2455             :                 //              rescaleResolution(chanid, subResidual, beam, itsPSFBeams.getBeam(chanid, polid));
    2456         452 :                 TempImage<Float> tmpSubResidualCopy( IPosition(4,nx,ny,1,1), subResidual.coordinates());
    2457         226 :                 tmpSubResidualCopy.copyData( subResidual );
    2458             :                 
    2459         226 :                 rescaleResolution(chanid, tmpSubResidualCopy, beam, itsPSFBeams.getBeam(chanid, polid));
    2460         226 :                 subRestored.copyData( LatticeExpr<Float>( subRestored + tmpSubResidualCopy  ) );
    2461         226 :               }
    2462             :             else// if no need to rescale residuals, just add the residuals.
    2463             :               {
    2464             :                 
    2465             :                 
    2466        2973 :                 subRestored.copyData( LatticeExpr<Float>( subRestored + subResidual  ) );
    2467             :                 
    2468             :               }
    2469             :             
    2470             :           }
    2471           0 :         catch(AipsError &x)
    2472             :           {
    2473           0 :             throw( AipsError("Restoration Error in chan" + String::toString(chanid) + ":pol" + String::toString(polid) + " : " + x.getMesg() ) );
    2474           0 :           }
    2475             :         
    2476        3199 :       }// end of pol loop
    2477             :     }// end of chan loop
    2478             :     
    2479             :     try
    2480             :       {
    2481             :         //MSK// 
    2482         927 :         if( hasPB() )
    2483             :           {
    2484         905 :             if( (image(term)->getDefaultMask()).matches("mask0") ) removeMask( image(term) );
    2485         905 :             copyMask(residual(term),image(term));
    2486             :           }
    2487             : 
    2488             :         //      if(hasPB()){copyMask(residual(term),image(term));}
    2489         927 :         ImageInfo iminf = image(term)->imageInfo();
    2490             :         //iminf.setBeams( itsRestoredBeams);
    2491             : 
    2492         927 :         os << "Beam Set : Single beam : " << itsRestoredBeams.hasSingleBeam() << "  Multi-beam : " << itsRestoredBeams.hasMultiBeam() << LogIO::DEBUG2;
    2493             : 
    2494         927 :         iminf.removeRestoringBeam();
    2495             : 
    2496         927 :         if( itsRestoredBeams.hasSingleBeam() )
    2497         645 :           { iminf.setRestoringBeam( itsRestoredBeams.getBeam() );}
    2498             :         else
    2499         282 :           {iminf.setBeams( itsRestoredBeams);}
    2500             : 
    2501         927 :         image(term)->setImageInfo(iminf);
    2502             :  
    2503         927 :       }
    2504           0 :     catch(AipsError &x)
    2505             :       {
    2506           0 :         throw( AipsError("Restoration Error  : "  + x.getMesg() ) );
    2507           0 :       }
    2508             :         
    2509         927 :   }// end of restore()
    2510             : 
    2511           0 :   GaussianBeam SIImageStore::findGoodBeam()
    2512             :   {
    2513           0 :     LogIO os( LogOrigin("SIImageStore","findGoodBeam",WHERE) );
    2514           0 :     IPosition beamshp = itsPSFBeams.shape();
    2515           0 :     AlwaysAssert( beamshp.nelements()==2 , AipsError );
    2516             : 
    2517             :     /*
    2518             :     if( beamshp[0] != nchan || beamshp[1] != npol )
    2519             :       {
    2520             :         // Make new beams.
    2521             :         os << LogIO::WARN << "Couldn't find pre-computed restoring beams. Re-fitting." << LogIO::POST;
    2522             :         makeImageBeamSet();
    2523             :       }
    2524             :     */
    2525             : 
    2526           0 :     Vector<Float> areas(beamshp[0]*beamshp[1]);
    2527           0 :     Vector<Float> axrat(beamshp[0]*beamshp[1]);
    2528           0 :     areas=0.0; axrat=1.0;
    2529           0 :     Vector<Bool> flags( areas.nelements() );
    2530           0 :     flags=False;
    2531             :     
    2532           0 :     Int cnt=0;
    2533           0 :     for( Int chanid=0; chanid<beamshp[0];chanid++) {
    2534           0 :       for( Int polid=0; polid<beamshp[1]; polid++ ) {
    2535           0 :         GaussianBeam beam = itsPSFBeams(chanid, polid);
    2536           0 :         if( !beam.isNull() && beam.getMajor(Unit("arcsec"))>1.1e-06  )  // larger than default filler beam.
    2537             :           {
    2538           0 :             areas[cnt] = beam.getArea( Unit("arcsec2") );
    2539           0 :             axrat[cnt] = beam.getMajor( Unit("arcsec") ) / beam.getMinor( Unit("arcsec") );
    2540             :           }
    2541             :         else {
    2542           0 :           flags[cnt] = True;
    2543             :         }
    2544           0 :         cnt++;
    2545           0 :       }//for chanid
    2546             :     }//for polid
    2547             :     
    2548           0 :     Vector<Float> fit( areas.nelements() );
    2549           0 :     Vector<Float> fitaxr( areas.nelements() );
    2550           0 :     for (Int loop=0;loop<5;loop++)  {
    2551             :       /// Filter on outliers in PSF beam area
    2552           0 :       lineFit( areas, flags, fit, 0, areas.nelements()-1 );
    2553           0 :       Float sd = calcStd( areas , flags, fit );
    2554           0 :       for (uInt  i=0;i<areas.nelements();i++) {
    2555           0 :         if( fabs( areas[i] - fit[i] ) > 3*sd ) flags[i]=True;
    2556             :       }
    2557             :       /// Filter on outliers in PSF axial ratio
    2558           0 :       lineFit( axrat, flags, fitaxr, 0, areas.nelements()-1 );
    2559           0 :       Float sdaxr = calcStd( axrat , flags, fitaxr );
    2560           0 :       for (uInt  i=0;i<areas.nelements();i++) {
    2561           0 :         if( fabs( axrat[i] - fitaxr[i] ) > 3*sdaxr ) flags[i]=True;
    2562             :       }
    2563             :     }
    2564             :     //    cout << "Original areas : " << areas << endl;
    2565             :     //    cout << "Original axrats : " << axrat << endl;
    2566             :     //    cout << "Flags : " << flags << endl;
    2567             : 
    2568             :     // Find max area good beam.
    2569           0 :     GaussianBeam goodbeam;
    2570           0 :     Int cid=0,pid=0;
    2571           0 :     Float maxval=0.0;
    2572           0 :     cnt=0;
    2573           0 :     for( Int chanid=0; chanid<beamshp[0];chanid++) {
    2574           0 :       for( Int polid=0; polid<beamshp[1]; polid++ ) {
    2575           0 :         if( flags[cnt] == False ){ 
    2576           0 :           if( areas[cnt] > maxval ) {maxval = areas[cnt]; goodbeam = itsPSFBeams.getBeam(chanid,polid);cid=chanid;pid=polid;}
    2577             :         }
    2578           0 :         cnt++;
    2579             :       }//polid
    2580             :     }//chanid
    2581             : 
    2582           0 :     os << "Picking common beam from C"<<cid<<":P"<<pid<<" : " << goodbeam.getMajor(Unit("arcsec")) << " arcsec, " << goodbeam.getMinor(Unit("arcsec"))<< " arcsec, " << goodbeam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2583             : 
    2584           0 :     Bool badbeam=False;
    2585           0 :     for(uInt i=0;i<flags.nelements();i++){if(flags[i]==True) badbeam=True;}
    2586             : 
    2587           0 :     if( badbeam == True ) 
    2588             :       { 
    2589           0 :         os << "(Ignored beams from :";
    2590           0 :         cnt=0;
    2591           0 :         for( Int chanid=0; chanid<beamshp[0];chanid++) {
    2592           0 :           for( Int polid=0; polid<beamshp[1]; polid++ ) {
    2593           0 :             if( flags[cnt] == True ){ 
    2594           0 :               os << " C"<<chanid<<":P"<<polid;
    2595             :             }
    2596           0 :             cnt++;
    2597             :           }//polid
    2598             :         }//chanid
    2599           0 :         os << " as outliers either by area or by axial ratio)" << LogIO::POST;
    2600             :       } 
    2601             : 
    2602             : 
    2603             :     /*
    2604             :     // Replace 'bad' psfs with the chosen one.
    2605             :     if( goodbeam.isNull() ) {
    2606             :       os << LogIO::WARN << "No planes have non-zero restoring beams. Forcing artificial 1.0arcsec beam." << LogIO::POST;
    2607             :       Quantity majax(1.0,"arcsec"),minax(1.0,"arcsec"),pa(0.0,"deg");
    2608             :       goodbeam.setMajorMinor(majax,minax);
    2609             :       goodbeam.setPA(pa);
    2610             :     }
    2611             :     else  {
    2612             :       cnt=0;
    2613             :       for( Int chanid=0; chanid<nchan;chanid++) {
    2614             :         for( Int polid=0; polid<npol; polid++ ) {
    2615             :           if( flags[cnt]==True ) 
    2616             :             { itsPSFBeams.setBeam( chanid, polid, goodbeam ); }
    2617             :           cnt++;
    2618             :         }// end of pol loop
    2619             :       }// end of chan loop
    2620             :     }
    2621             :     */
    2622             : 
    2623           0 :     return goodbeam;
    2624           0 :   }// end of findGoodBeam
    2625             : 
    2626             :   ///////////////////////// Funcs to calculate robust mean and fit, taking into account 'flagged' points.
    2627           0 : void SIImageStore :: lineFit(Vector<Float> &data, Vector<Bool> &flag, Vector<Float> &fit, uInt lim1, uInt lim2)
    2628             : {
    2629           0 :   float Sx = 0, Sy = 0, Sxx = 0, Sxy = 0, S = 0, a, b, sd, mn;
    2630             :   
    2631           0 :   mn = calcMean(data, flag);
    2632           0 :   sd = calcStd (data, flag, mn);
    2633             :   
    2634           0 :   for (uInt i = lim1; i <= lim2; i++)
    2635             :     {
    2636           0 :       if (flag[i] == False) // if unflagged
    2637             :         {
    2638           0 :           S += 1 / (sd * sd);
    2639           0 :           Sx += i / (sd * sd);
    2640           0 :           Sy += data[i] / (sd * sd);
    2641           0 :           Sxx += (i * i) / (sd * sd);
    2642           0 :           Sxy += (i * data[i]) / (sd * sd);
    2643             :         }
    2644             :     }
    2645           0 :   a = (Sxx * Sy - Sx * Sxy) / (S * Sxx - Sx * Sx);
    2646           0 :   b = (S * Sxy - Sx * Sy) / (S * Sxx - Sx * Sx);
    2647             :   
    2648           0 :   for (uInt i = lim1; i <= lim2; i++)
    2649           0 :     fit[i] = a + b * i;
    2650             :   
    2651           0 : }
    2652             : /* Calculate the MEAN of 'vect' ignoring values flagged in 'flag' */
    2653           0 : Float SIImageStore :: calcMean(Vector<Float> &vect, Vector<Bool> &flag)
    2654             : {
    2655           0 :   Float mean=0;
    2656           0 :   Int cnt=0;
    2657           0 :   for(uInt i=0;i<vect.nelements();i++)
    2658           0 :     if(flag[i]==False)
    2659             :       {
    2660           0 :         mean += vect[i];
    2661           0 :         cnt++;
    2662             :       }
    2663           0 :   if(cnt==0) cnt=1;
    2664           0 :   return mean/cnt;
    2665             : }
    2666           0 : Float SIImageStore :: calcStd(Vector<Float> &vect, Vector<Bool> &flag, Vector<Float> &fit)
    2667             : {
    2668           0 :   Float std=0;
    2669           0 :   uInt n=0,cnt=0;
    2670           0 :   n = vect.nelements() < fit.nelements() ? vect.nelements() : fit.nelements();
    2671           0 :   for(uInt i=0;i<n;i++)
    2672           0 :     if(flag[i]==False)
    2673             :       {
    2674           0 :         cnt++;
    2675           0 :         std += (vect[i]-fit[i])*(vect[i]-fit[i]);
    2676             :       }
    2677           0 :   if(cnt==0) cnt=1;
    2678           0 :   return sqrt(std/cnt);
    2679             : 
    2680             : }
    2681           0 : Float SIImageStore :: calcStd(Vector<Float> &vect, Vector<Bool> &flag, Float mean)
    2682             : {
    2683           0 :   Float std=0;
    2684           0 :   uInt cnt=0;
    2685           0 :   for(uInt i=0;i<vect.nelements();i++)
    2686           0 :     if(flag[i]==False)
    2687             :       {
    2688           0 :         cnt++;
    2689           0 :         std += (vect[i]-mean)*(vect[i]-mean);
    2690             :       }
    2691           0 :   return sqrt(std/cnt);
    2692             : }
    2693             : 
    2694             :   ///////////////////////// End of Funcs to calculate robust mean and fit.
    2695             : 
    2696             : 
    2697             : 
    2698             : /*
    2699             :   GaussianBeam SIImageStore::restorePlane()
    2700             :   {
    2701             : 
    2702             :     LogIO os( LogOrigin("SIImageStore","restorePlane",WHERE) );
    2703             :     //     << ". Optionally, PB-correct too." << LogIO::POST;
    2704             : 
    2705             :     Bool validbeam=False;
    2706             :     GaussianBeam beam;
    2707             :     try
    2708             :       {
    2709             :         // Fit a Gaussian to the PSF.
    2710             :         beam = getPSFGaussian();
    2711             :         validbeam = True;
    2712             :       }
    2713             :     catch(AipsError &x)
    2714             :       {
    2715             :         os << LogIO::WARN << "Beam fit error : " + x.getMesg() << LogIO::POST;
    2716             :       }
    2717             :     
    2718             :     try
    2719             :       {
    2720             :         if( validbeam==True )
    2721             :           {
    2722             :             //os << "[" << itsImageName << "] " ;  // Add when parent image name is available.
    2723             :             //os << "Restore with beam : " << beam.getMajor(Unit("arcmin")) << " arcmin, " << beam.getMinor(Unit("arcmin"))<< " arcmin, " << beam.getPA(Unit("deg")) << " deg" << LogIO::POST; 
    2724             :             
    2725             :             // Initialize restored image
    2726             :             image()->set(0.0);
    2727             :             // Copy model into it
    2728             :             image()->copyData( LatticeExpr<Float>( *(model()) )  );
    2729             :             // Smooth model by beam
    2730             :             StokesImageUtil::Convolve( *(image()), beam);
    2731             :             // Add residual image
    2732             :             image()->copyData( LatticeExpr<Float>( *(image()) + *(residual())  ) );
    2733             :             
    2734             :             // Set restoring beam into the image
    2735             :             ImageInfo ii = image()->imageInfo();
    2736             :             //ii.setRestoringBeam(beam);
    2737             :             ii.setBeams(beam);
    2738             :             image()->setImageInfo(ii);
    2739             :           }
    2740             :       }
    2741             :     catch(AipsError &x)
    2742             :       {
    2743             :         throw( AipsError("Restoration Error : " + x.getMesg() ) );
    2744             :       }
    2745             :         
    2746             :     return beam;
    2747             : 
    2748             :   }
    2749             : */
    2750             : 
    2751          51 :   void SIImageStore::pbcor(uInt term)
    2752             :   {
    2753             : 
    2754         102 :     LogIO os( LogOrigin("SIImageStore","pbcor",WHERE) );
    2755             : 
    2756          51 :     if( !hasRestored() || !hasPB() )
    2757             :       {
    2758             :         // Cannot pbcor without restored image and pb
    2759           0 :         os << LogIO::WARN << "Cannot pbcor without restored image and pb" << LogIO::POST;
    2760           0 :         return;
    2761             :       }
    2762          51 :     LatticeLocker lock1(*(image(term)), FileLocker::Write);
    2763          51 :         LatticeLocker lock2(*(pb(term)), FileLocker::Write);
    2764          51 :         LatticeLocker lock3(*(imagepbcor(term)), FileLocker::Write);
    2765             : 
    2766         103 :         for(Int pol=0; pol<itsImageShape[2]; pol++)
    2767             :           {
    2768         178 :             for(Int chan=0; chan<itsImageShape[3]; chan++)
    2769             :               {
    2770             :                 
    2771         126 :                 CountedPtr<ImageInterface<Float> > restoredsubim=makeSubImage(0,1, 
    2772         126 :                                                                       chan, itsImageShape[3],
    2773         126 :                                                                       pol, itsImageShape[2], 
    2774         252 :                                                                       *image(term) );
    2775         126 :                 CountedPtr<ImageInterface<Float> > pbsubim=makeSubImage(0,1, 
    2776         126 :                                                                       chan, itsImageShape[3],
    2777         126 :                                                                       pol, itsImageShape[2], 
    2778         252 :                                                                       *pb() );
    2779             : 
    2780         126 :                 CountedPtr<ImageInterface<Float> > pbcorsubim=makeSubImage(0,1, 
    2781         126 :                                                                       chan, itsImageShape[3],
    2782         126 :                                                                       pol, itsImageShape[2], 
    2783         252 :                                                                       *imagepbcor(term) );
    2784             : 
    2785             : 
    2786         126 :                 LatticeExprNode pbmax( max( *pbsubim ) );
    2787         126 :                 Float pbmaxval = pbmax.getFloat();
    2788             : 
    2789         126 :                 if( pbmaxval<=0.0 )
    2790             :                   {
    2791           0 :                     os << LogIO::WARN << "Skipping PBCOR for C:" << chan << " P:" << pol << " because pb max is zero " << LogIO::POST;
    2792           0 :                     pbcorsubim->set(0.0);
    2793             :                   }
    2794             :                 else
    2795             :                   {
    2796             : 
    2797         252 :                     LatticeExpr<Float> thepbcor( iif( *(pbsubim) > 0.0 , (*(restoredsubim))/(*(pbsubim)) , 0.0 ) );
    2798         126 :                     pbcorsubim->copyData( thepbcor );
    2799             : 
    2800         126 :                 }// if not zero
    2801         126 :               }//chan
    2802             :           }//pol
    2803             : 
    2804             :         // Copy over the PB mask.
    2805          51 :         if((imagepbcor(term)->getDefaultMask()=="") && hasPB())
    2806          33 :           {copyMask(pb(),imagepbcor(term));}
    2807             : 
    2808             :         // Set restoring beam info
    2809          51 :         ImageInfo iminf = image(term)->imageInfo();
    2810             :         //iminf.setBeams( itsRestoredBeams );
    2811          51 :         imagepbcor(term)->setImageInfo(iminf);
    2812             : 
    2813          51 :   }// end pbcor
    2814             : 
    2815           0 :   Matrix<Float> SIImageStore::getSumWt(ImageInterface<Float>& target)
    2816             :   {
    2817           0 :     Record miscinfo = target.miscInfo();
    2818             :     
    2819           0 :     Matrix<Float> sumwt;
    2820           0 :     sumwt.resize();
    2821           0 :     if( miscinfo.isDefined("sumwt") 
    2822           0 :         && (miscinfo.dataType("sumwt")==TpArrayFloat || miscinfo.dataType("sumwt")==TpArrayDouble  )  ) 
    2823           0 :       { miscinfo.get( "sumwt" , sumwt ); } 
    2824           0 :     else   { sumwt.resize( IPosition(2, target.shape()[2], target.shape()[3] ) ); sumwt = 1.0;  }
    2825             :     
    2826           0 :     return sumwt;
    2827           0 :   }
    2828             :   
    2829           0 :   void SIImageStore::setSumWt(ImageInterface<Float>& target, Matrix<Float>& sumwt)
    2830             :   {
    2831           0 :     Record miscinfo = target.miscInfo();
    2832           0 :     miscinfo.define("sumwt", sumwt);
    2833           0 :     LatticeLocker lock1(target, FileLocker::Write);
    2834           0 :     target.setMiscInfo( miscinfo );
    2835           0 :   }
    2836             :   
    2837             : 
    2838        4654 :   Bool SIImageStore::getUseWeightImage(ImageInterface<Float>& target)
    2839             :   {
    2840        4654 :     Record miscinfo = target.miscInfo();
    2841             :     Bool useweightimage;
    2842        4654 :     if( miscinfo.isDefined("useweightimage") && miscinfo.dataType("useweightimage")==TpBool )
    2843        4654 :       { miscinfo.get( "useweightimage", useweightimage );  }
    2844           0 :     else { useweightimage = False; }
    2845             : 
    2846        4654 :     return useweightimage;
    2847        4654 :   }
    2848             :   /*
    2849             :   Bool SIImageStore::getUseWeightImage()
    2850             :   {
    2851             :     if( ! itsParentSumWt )
    2852             :       return False;
    2853             :     else 
    2854             :      return  getUseWeightImage( *itsParentSumWt );
    2855             :   }
    2856             :   */
    2857       16691 :   void SIImageStore::setUseWeightImage(ImageInterface<Float>& target, Bool useweightimage)
    2858             :   {
    2859       16691 :     Record miscinfo = target.miscInfo();
    2860       16691 :     miscinfo.define("useweightimage", useweightimage);
    2861       16691 :     LatticeLocker lock1(target, FileLocker::Write);
    2862       16691 :     target.setMiscInfo( miscinfo );
    2863       16691 :   }
    2864             :   
    2865             : 
    2866             : 
    2867        1911 :   Bool SIImageStore::divideImageByWeightVal( ImageInterface<Float>& target )
    2868             :   {
    2869             : 
    2870        1911 :     Array<Float> lsumwt;
    2871        1911 :     sumwt()->get( lsumwt , False ); // For MT, this will always pick the zeroth sumwt, which it should.
    2872        1911 :     LatticeLocker lock2(target, FileLocker::Write);
    2873             :     
    2874        1911 :     IPosition imshape = target.shape();
    2875             : 
    2876             :     //cerr << " SumWt  : " << lsumwt << " sumwtshape : " << lsumwt.shape() << " image shape : " << imshape << endl;
    2877             : 
    2878        1911 :     AlwaysAssert( lsumwt.shape()[2] == imshape[2] , AipsError ); // polplanes
    2879        1911 :     AlwaysAssert( lsumwt.shape()[3] == imshape[3] , AipsError ); // chanplanes
    2880             : 
    2881        1911 :     Bool div=False; // flag to signal if division actually happened, or weights are all 1.0
    2882             : 
    2883        4163 :     for(Int pol=0; pol<lsumwt.shape()[2]; pol++)
    2884             :       {
    2885        8790 :         for(Int chan=0; chan<lsumwt.shape()[3]; chan++)
    2886             :           {
    2887        6538 :             IPosition pos(4,0,0,pol,chan);
    2888        6538 :             if( lsumwt(pos) != 1.0 )
    2889             :               { 
    2890             :                 //              SubImage<Float>* subim=makePlane(  chan, True ,pol, True, target );
    2891             :                 std::shared_ptr<ImageInterface<Float> > subim=makeSubImage(0,1, 
    2892        6538 :                                                                       chan, lsumwt.shape()[3],
    2893        6538 :                                                                       pol, lsumwt.shape()[2], 
    2894       13076 :                                                                       target );
    2895        6538 :                 if ( lsumwt(pos) > 1e-07 ) {
    2896       12550 :                     LatticeExpr<Float> le( (*subim)/lsumwt(pos) );
    2897        6275 :                     subim->copyData( le );
    2898        6275 :                   }
    2899             :                 else  {
    2900         263 :                     subim->set(0.0);
    2901             :                   }
    2902        6538 :                 div=True;
    2903        6538 :               }
    2904        6538 :           }
    2905             :       }
    2906             : 
    2907             :     //    if( div==True ) cout << "Div image by sumwt : " << lsumwt << endl;
    2908             :     //    else cout << "Already normalized" << endl;
    2909             : 
    2910             :     //    lsumwt = 1.0; setSumWt( target , lsumwt );
    2911             : 
    2912        1911 :     return div;
    2913        1911 :   }
    2914             : 
    2915         946 :   void  SIImageStore::normPSF(Int term)
    2916             :   {
    2917             : 
    2918        2069 :     for(Int pol=0; pol<itsImageShape[2]; pol++)
    2919             :       {
    2920        4403 :         for(Int chan=0; chan<itsImageShape[3]; chan++)
    2921             :           {
    2922             :             ///     IPosition center(4,itsImageShape[0]/2,itsImageShape[1]/2,pol,chan);
    2923             :             
    2924             :             std::shared_ptr<ImageInterface<Float> > subim=makeSubImage(0,1, 
    2925        6560 :                                                                   chan, itsImageShape[3],
    2926        3280 :                                                                   pol, itsImageShape[2], 
    2927        6560 :                                                                   (*psf(term)) );
    2928             : 
    2929             :             std::shared_ptr<ImageInterface<Float> > subim0=makeSubImage(0,1, 
    2930        6560 :                                                                   chan, itsImageShape[3],
    2931        3280 :                                                                   pol, itsImageShape[2], 
    2932        6560 :                                                                   (*psf(0)) );
    2933             : 
    2934        3280 :             LatticeLocker lock1(*(subim), FileLocker::Write);
    2935             : 
    2936        3280 :             LatticeExprNode themax( max(*(subim0)) );
    2937        3280 :             Float maxim = themax.getFloat();
    2938             :             
    2939        3280 :             if ( maxim > 1e-07 )
    2940             :               {
    2941        6338 :                 LatticeExpr<Float> normed( (*(subim)) / maxim );
    2942        3169 :                 subim->copyData( normed );
    2943        3169 :               }
    2944             :             else
    2945             :               {
    2946         111 :                 subim->set(0.0);
    2947             :               }
    2948        3280 :           }//chan
    2949             :       }//pol
    2950             : 
    2951         946 :   }
    2952             : 
    2953         630 :   void SIImageStore::calcSensitivity()
    2954             :   {
    2955        1260 :     LogIO os( LogOrigin("SIImageStore","calcSensitivity",WHERE) );
    2956             : 
    2957         630 :     Array<Float> lsumwt;
    2958         630 :     sumwt()->get( lsumwt , False ); // For MT, this will always pick the zeroth sumwt, which it should.
    2959             : 
    2960         630 :     IPosition shp( lsumwt.shape() );
    2961             :     //cout << "Sumwt shape : " << shp << " : " << lsumwt << endl;
    2962             :     //AlwaysAssert( shp.nelements()==4 , AipsError );
    2963             :     
    2964         630 :     os << "[" << itsImageName << "] Theoretical sensitivity (Jy/bm):" ;
    2965             :     
    2966         630 :     IPosition it(4,0,0,0,0);
    2967        1267 :     for ( it[0]=0; it[0]<shp[0]; it[0]++)
    2968        1300 :       for ( it[1]=0; it[1]<shp[1]; it[1]++)
    2969        1476 :         for ( it[2]=0; it[2]<shp[2]; it[2]++)
    2970        3783 :           for ( it[3]=0; it[3]<shp[3]; it[3]++)
    2971             :             {
    2972        2970 :               if( shp[0]>1 ){os << "f"<< it[0]+(it[1]*shp[0]) << ":" ;}
    2973        2970 :               if( shp[3]>1 ) { os << "c"<< it[3] << ":"; }
    2974        2970 :               if( shp[2]>1 ) { os << "p"<< it[2]<< ":" ; }
    2975        2970 :               if( lsumwt( it )  > 1e-07 ) 
    2976             :                 { 
    2977        2817 :                   os << 1.0/(sqrt(lsumwt(it))) << " " ;
    2978             :                 }
    2979             :               else
    2980             :                 {
    2981         153 :                   os << "none" << " ";
    2982             :                 }
    2983             :             }
    2984             :     
    2985         630 :     os << LogIO::POST;
    2986             : 
    2987             :     //    Array<Float> sens = 1.0/sqrtsumwt;
    2988             : 
    2989             : 
    2990         630 :   }
    2991             : 
    2992           0 :   Double SIImageStore::calcFractionalBandwidth()
    2993             :   {
    2994           0 :     throw(AipsError("calcFractionalBandwidth is not implemented for SIImageStore. Only SIImageStoreMultiTerm"));
    2995             :   }
    2996             : 
    2997             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2998             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2999             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3000             : ///////////////////   Utility Functions to gather statistics on the imagestore.
    3001             : 
    3002        8885 : Float SIImageStore::getPeakResidual()
    3003             : {
    3004       17770 :     LogIO os( LogOrigin("SIImageStore","getPeakResidual",WHERE) );
    3005        8885 :     LatticeLocker lock2 (*(residual()), FileLocker::Read);
    3006       17770 :     ArrayLattice<Bool> pixelmask(residual()->getMask());
    3007       17770 :     LatticeExpr<Float> resd(iif(pixelmask,abs(*residual()),0));
    3008             :     //LatticeExprNode pres( max(abs( *residual() ) ));
    3009        8885 :     LatticeExprNode pres( max(resd) );
    3010        8885 :     Float maxresidual = pres.getFloat();
    3011             :     
    3012        8885 :     return maxresidual;
    3013        8885 :   }
    3014             :   
    3015        5188 : Float SIImageStore::getPeakResidualWithinMask()
    3016             :   {
    3017       10376 :     LogIO os( LogOrigin("SIImageStore","getPeakResidualWithinMask",WHERE) );
    3018             :     //Float minresmask, maxresmask, minres, maxres;
    3019             :     //findMinMax( residual()->get(), mask()->get(), minres, maxres, minresmask, maxresmask );
    3020             : 
    3021       10376 :     ArrayLattice<Bool> pixelmask(residual()->getMask());
    3022             :     //findMinMaxLattice(*residual(), *mask() , pixelmask, maxres,maxresmask, minres, minresmask);
    3023       10376 :     LatticeExpr<Float> resd(iif(((*mask()) > 0) && pixelmask ,abs((*residual())),0));
    3024        5188 :     LatticeExprNode pres( max(resd) );
    3025        5188 :     Float maxresidual = pres.getFloat();
    3026             :     //Float maxresidual=max( abs(maxresmask), abs(minresmask) );
    3027        5188 :     return maxresidual;
    3028        5188 :   }
    3029             : 
    3030             :   // Calculate the total model flux
    3031        5455 : Float SIImageStore::getModelFlux(uInt term)
    3032             :   {
    3033             :     //    LogIO os( LogOrigin("SIImageStore","getModelFlux",WHERE) );
    3034        5455 :     LatticeLocker lock2 (*(model(term)), FileLocker::Read);
    3035       10906 :     LatticeExprNode mflux( sum( *model(term) ) );
    3036        5453 :     Float modelflux = mflux.getFloat();
    3037             :     //    Float modelflux = sum( model(term)->get() );
    3038             : 
    3039        5453 :     return modelflux;
    3040        5453 :   }
    3041             : 
    3042             :   // Check for non-zero model (this is different from getting model flux, for derived SIIMMT)
    3043        2072 : Bool SIImageStore::isModelEmpty()
    3044             :   {
    3045        2072 :     if( !itsModel && (! hasModel()) ) return True;
    3046        1378 :     else return  ( fabs( getModelFlux(0) ) < 1e-08 );
    3047             :   }
    3048             : 
    3049             : 
    3050         276 : void SIImageStore::setPSFSidelobeLevel(const Float level){
    3051             : 
    3052         276 :   itsPSFSideLobeLevel=level;
    3053         276 : }
    3054             :   // Calculate the PSF sidelobe level...
    3055        5620 :   Float SIImageStore::getPSFSidelobeLevel()
    3056             :   {
    3057       11240 :     LogIO os( LogOrigin("SIImageStore","getPSFSidelobeLevel",WHERE) );
    3058             :     //cerr << "*****PSF sidelobe "<< itsPSFSideLobeLevel << endl;
    3059             :     /// Calculate only once, store and return for all subsequent calls.
    3060        5620 :     if( itsPSFSideLobeLevel == 0.0 )
    3061             :       {
    3062             : 
    3063         699 :         ImageBeamSet thebeams = getBeamSet();
    3064         699 :         LatticeLocker lock2 (*(psf()), FileLocker::Read);
    3065             :         
    3066             :         //------------------------------------------------------------
    3067         699 :         IPosition oneplaneshape( itsImageShape );
    3068         699 :         AlwaysAssert( oneplaneshape.nelements()==4, AipsError );
    3069         699 :         oneplaneshape[2]=1; oneplaneshape[3]=1;
    3070         699 :         TempImage<Float> psfbeam( oneplaneshape, itsCoordSys );
    3071             :         
    3072             :         // In a loop through channels, subtract out or mask out the main lobe
    3073         699 :         Float allmin=0.0, allmax=0.0;
    3074        1551 :         for(Int pol=0; pol<itsImageShape[2]; pol++)
    3075             :           {
    3076        3643 :             for(Int chan=0; chan<itsImageShape[3]; chan++)
    3077             :               {
    3078             :                 std::shared_ptr<ImageInterface<Float> > onepsf=makeSubImage(0,1, 
    3079        5582 :                                                                        chan, itsImageShape[3],
    3080        2791 :                                                                        pol, itsImageShape[2], 
    3081        5582 :                                                                        (*psf()) );
    3082             :                 
    3083             :                 
    3084        2791 :                 GaussianBeam beam = thebeams.getBeam( chan, pol );
    3085        2791 :                 Vector<Float> abeam(3); // Holds bmaj, bmin, pa  in asec, asec, deg 
    3086        2791 :                 abeam[0] = beam.getMajor().get("arcsec").getValue() * C::arcsec;
    3087        2791 :                 abeam[1] = beam.getMinor().get("arcsec").getValue() * C::arcsec;
    3088        2791 :                 abeam[2] = (beam.getPA().get("deg").getValue() + 90.0)* C::degree;
    3089             : 
    3090             :                 //cout << "Beam : " << abeam << endl;
    3091             : 
    3092        2791 :                 StokesImageUtil::MakeGaussianPSF( psfbeam,  abeam, False);
    3093             : 
    3094             :                 //              storeImg( String("psfbeam.im"), psfbeam );
    3095             :         
    3096             :                 //Subtract from PSF plane
    3097        5582 :                 LatticeExpr<Float> delobed(  (*onepsf) - psfbeam  );
    3098             :                 
    3099             :                 // For debugging
    3100             :                 //onepsf->copyData( delobed );
    3101             :                 
    3102             :                 //Calc max and min and accumulate across channels. 
    3103             :                 
    3104        2791 :                 LatticeExprNode minval_le( min( *onepsf ) );
    3105        2791 :                 LatticeExprNode maxval_le( max( delobed ) );
    3106             : 
    3107        2791 :                 Float minval = minval_le.getFloat();
    3108        2791 :                 Float maxval = maxval_le.getFloat();
    3109             : 
    3110        2791 :                 if( minval < allmin ) allmin = minval;
    3111        2791 :                 if( maxval > allmax ) allmax = maxval;
    3112             : 
    3113             :                 //cout << "Chan : " << chan << "   minval : " << minval << "  maxval : " << maxval << endl;
    3114             :                 
    3115        2791 :               }//chan
    3116             :           }//pol
    3117             :         
    3118             :         //------------------------------------------------------------
    3119             : 
    3120         699 :         itsPSFSideLobeLevel = max( fabs(allmin), fabs(allmax) );
    3121             : 
    3122             :         //os << "PSF min : " << allmin << " max : " << allmax << " psfsidelobelevel : " << itsPSFSideLobeLevel << LogIO::POST;
    3123             : 
    3124         699 :       }// if changed.
    3125             :     
    3126             :     //    LatticeExprNode psfside( min( *psf() ) );
    3127             :     //    itsPSFSideLobeLevel = fabs( psfside.getFloat() );
    3128             : 
    3129             :     //cout << "PSF sidelobe level : " << itsPSFSideLobeLevel << endl;
    3130        5620 :     return itsPSFSideLobeLevel;
    3131        5620 :   }
    3132             : 
    3133           0 :   void SIImageStore::findMinMax(const Array<Float>& lattice,
    3134             :                                         const Array<Float>& mask,
    3135             :                                         Float& minVal, Float& maxVal,
    3136             :                                         Float& minValMask, Float& maxValMask)
    3137             :   {
    3138           0 :     IPosition posmin(lattice.shape().nelements(), 0);
    3139           0 :     IPosition posmax(lattice.shape().nelements(), 0);
    3140             : 
    3141           0 :     if( sum(mask) <1e-06 ) {minValMask=0.0; maxValMask=0.0;}
    3142           0 :     else { minMaxMasked(minValMask, maxValMask, posmin, posmax, lattice,mask); }
    3143             : 
    3144           0 :     minMax( minVal, maxVal, posmin, posmax, lattice );
    3145           0 :   }
    3146             : 
    3147         122 : Array<Double> SIImageStore::calcRobustRMS(Array<Double>& mdns, const Float pbmasklevel, const Bool fastcalc)
    3148             : {    
    3149         244 :   LogIO os( LogOrigin("SIImageStore","calcRobustRMS",WHERE) );
    3150         122 :   Record*  regionPtr=0;
    3151         122 :   String LELmask("");
    3152         122 :   LatticeLocker lockres (*(residual()), FileLocker::Read);
    3153         244 :   ArrayLattice<Bool> pbmasklat(residual()->shape());
    3154         122 :   pbmasklat.set(False);
    3155         122 :   LatticeExpr<Bool> pbmask(pbmasklat);
    3156         122 :   if (hasPB()) {
    3157             :     // set bool mask: False = masked
    3158         122 :     pbmask = LatticeExpr<Bool> (iif(*pb() > pbmasklevel, True, False));
    3159         122 :     os << LogIO::DEBUG1 << "pbmask to be attached===> nfalse(pbmask.getMask())="<<nfalse(pbmask.getMask())<<endl; 
    3160             :   }
    3161             :   
    3162             :    
    3163         122 :   Record thestats;
    3164         122 :   if (fastcalc) { // older calculation 
    3165             :     // need to apply pbmask if present to be consistent between fastcalc = true and false.
    3166             :     //TempImage<Float>* tempRes = new TempImage<Float>(residual()->shape(), residual()->coordinates(), SDMaskHandler::memoryToUse());
    3167         240 :     auto tempRes = std::shared_ptr<TempImage<Float>>(new TempImage<Float>(residual()->shape(), residual()->coordinates(), SDMaskHandler::memoryToUse()));
    3168         120 :     tempRes->copyData(*residual());
    3169         120 :     tempRes->attachMask(pbmask);
    3170             :     //thestats = SDMaskHandler::calcImageStatistics(*residual(), LELmask, regionPtr, True);
    3171         120 :     thestats = SDMaskHandler::calcImageStatistics(*tempRes, LELmask, regionPtr, True);
    3172         120 :   }
    3173             :   else { // older way to calculate 
    3174             :     // use the new statistic calculation algorithm
    3175           2 :     Vector<Bool> dummyvec;
    3176             :     // TT: 2018.08.01 using revised version (the older version of this is renameed to calcRobustImageStatisticsOld)
    3177           2 :     thestats = SDMaskHandler::calcRobustImageStatistics(*residual(), *mask(), pbmask,  LELmask, regionPtr, True, dummyvec);
    3178           2 :   }
    3179             :     
    3180             : 
    3181             :   /***
    3182             :   ImageStatsCalculator imcalc( residual(), regionPtr, LELmask, False); 
    3183             : 
    3184             :   Vector<Int> axes(2);
    3185             :   axes[0] = 0;
    3186             :   axes[1] = 1;
    3187             :   imcalc.setAxes(axes);
    3188             :   imcalc.setRobust(True);
    3189             :   Record thestats = imcalc.statistics();
    3190             :   //cout<<"thestats="<<thestats<<endl;
    3191             :   ***/
    3192             : 
    3193             :   //Array<Double>rmss, mads, mdns;
    3194         122 :   Array<Double>rmss, mads;
    3195             :   //thestats.get(RecordFieldId("max"), maxs);
    3196         122 :   thestats.get(RecordFieldId("rms"), rmss);
    3197         122 :   thestats.get(RecordFieldId("medabsdevmed"), mads);
    3198         122 :   thestats.get(RecordFieldId("median"), mdns);
    3199             :   
    3200             :   //os << LogIO::DEBUG1 << "Max : " << maxs << LogIO::POST;
    3201         122 :   os << LogIO::DEBUG1 << "RMS : " << rmss << LogIO::POST;
    3202         122 :   os << LogIO::DEBUG1 << "MAD : " << mads << LogIO::POST;
    3203             :   
    3204             :   // this for the new noise calc
    3205             :   //return mdns+mads*1.4826;
    3206             :   // this is the old noise calc
    3207         244 :   return mads*1.4826;
    3208         122 : }
    3209             : 
    3210           0 :   void SIImageStore::printImageStats()
    3211             :   {
    3212           0 :     LogIO os( LogOrigin("SIImageStore","printImageStats",WHERE) );
    3213           0 :     Float minresmask=0, maxresmask=0, minres=0, maxres=0;
    3214             :     //    findMinMax( residual()->get(), mask()->get(), minres, maxres, minresmask, maxresmask );
    3215           0 :     LatticeLocker lock1 (*(residual()), FileLocker::Read);
    3216           0 :     ArrayLattice<Bool> pixelmask(residual()->getMask());
    3217           0 :     if(hasMask())
    3218             :       {
    3219           0 :         LatticeLocker lock2 (*(mask()), FileLocker::Read);
    3220           0 :         findMinMaxLattice(*residual(), *mask() , pixelmask, maxres,maxresmask, minres, minresmask);
    3221           0 :       }
    3222             :     else
    3223             :       {
    3224             :         //LatticeExprNode pres( max( *residual() ) );
    3225           0 :         LatticeExprNode pres( max( iif(pixelmask,*residual(),0) ) );
    3226           0 :         maxres = pres.getFloat();
    3227             :         //LatticeExprNode pres2( min( *residual() ) );
    3228           0 :         LatticeExprNode pres2( min( iif(pixelmask,*residual(),0) ) );
    3229           0 :         minres = pres2.getFloat();
    3230           0 :       }
    3231             : 
    3232           0 :     os << "[" << itsImageName << "]" ;
    3233           0 :     os << " Peak residual (max,min) " ;
    3234           0 :     if( minresmask!=0.0 || maxresmask!=0.0 )
    3235           0 :       { os << "within mask : (" << maxresmask << "," << minresmask << ") "; }
    3236           0 :     os << "over full image : (" << maxres << "," << minres << ")" << LogIO::POST;
    3237             : 
    3238           0 :     os << "[" << itsImageName << "] Total Model Flux : " << getModelFlux() << LogIO::POST; 
    3239             : 
    3240             :     
    3241           0 :     Record*  regionPtr=0;
    3242           0 :     String LELmask("");
    3243           0 :     Record thestats = SDMaskHandler::calcImageStatistics(*residual(), LELmask, regionPtr, True);
    3244           0 :     Array<Double> maxs, mins;
    3245           0 :     thestats.get(RecordFieldId("max"), maxs);
    3246           0 :     thestats.get(RecordFieldId("min"), mins);
    3247             :     //os << LogIO::DEBUG1 << "Max : " << maxs << LogIO::POST;
    3248             :     //os << LogIO::DEBUG1 << "Min : " << mins << LogIO::POST;
    3249             :     
    3250           0 :   }
    3251             : 
    3252             :   // Calculate the total model flux
    3253        6048 :   Float SIImageStore::getMaskSum()
    3254             :   {
    3255       12096 :     LogIO os( LogOrigin("SIImageStore","getMaskSum",WHERE) );
    3256        6048 :     LatticeLocker lock2 (*(mask()), FileLocker::Read);
    3257       12088 :     LatticeExprNode msum( sum( *mask() ) );
    3258        6044 :     Float masksum = msum.getFloat();
    3259             : 
    3260             :     //    Float masksum = sum( mask()->get() );
    3261             : 
    3262        6044 :     return masksum;
    3263        6048 :   }
    3264             : 
    3265           0 : Bool SIImageStore::findMinMaxLattice(const Lattice<Float>& lattice, 
    3266             :                                      const Lattice<Float>& mask,
    3267             :                                      const Lattice<Bool>& pixelmask,
    3268             :                                      Float& maxAbs, Float& maxAbsMask, 
    3269             :                                      Float& minAbs, Float& minAbsMask )
    3270             : {
    3271             : 
    3272             :   //FOR DEGUG
    3273             :   //LogIO os( LogOrigin("SIImageStore","findMinMaxLattice",WHERE) );
    3274             : 
    3275           0 :   maxAbs=0.0;maxAbsMask=0.0;
    3276           0 :   minAbs=1e+10;minAbsMask=1e+10;
    3277           0 :   LatticeLocker lock1 (const_cast<Lattice<Float>& > (lattice), FileLocker::Read);
    3278           0 :   LatticeLocker lock2 (const_cast<Lattice<Float>& >(mask), FileLocker::Read);
    3279           0 :   LatticeLocker lock3 (const_cast<Lattice<Bool>& >(pixelmask), FileLocker::Read);
    3280           0 :   const IPosition tileShape = lattice.niceCursorShape();
    3281           0 :   TiledLineStepper ls(lattice.shape(), tileShape, 0);
    3282             :   {
    3283           0 :     RO_LatticeIterator<Float> li(lattice, ls);
    3284           0 :     RO_LatticeIterator<Float> mi(mask, ls);
    3285           0 :     RO_LatticeIterator<Bool> pmi(pixelmask, ls);
    3286           0 :     for(li.reset(),mi.reset(),pmi.reset();!li.atEnd();li++, mi++, pmi++) {
    3287           0 :       IPosition posMax=li.position();
    3288           0 :       IPosition posMin=li.position();
    3289           0 :       IPosition posMaxMask=li.position();
    3290           0 :       IPosition posMinMask=li.position();
    3291           0 :       Float maxVal=0.0;
    3292           0 :       Float minVal=0.0;
    3293           0 :       Float maxValMask=0.0;
    3294           0 :       Float minValMask=0.0;
    3295             : 
    3296             : 
    3297             :       // skip if lattice chunk is masked entirely.
    3298           0 :       if(ntrue(pmi.cursor()) > 0 ) {
    3299           0 :         const MaskedArray<Float> marr(li.cursor(), pmi.cursor());
    3300           0 :         const MaskedArray<Float> marrinmask(li.cursor() * mi.cursor(), pmi.cursor());
    3301             :       //minMax( minVal, maxVal, posMin, posMax, li.cursor() );
    3302           0 :       minMax( minVal, maxVal, posMin, posMax, marr );
    3303             :       //minMaxMasked(minValMask, maxValMask, posMin, posMax, li.cursor(), mi.cursor());
    3304           0 :       minMax(minValMask, maxValMask, posMin, posMax, marrinmask);
    3305             :       
    3306             :       //os<<"DONE minMax"<<LogIO::POST; 
    3307           0 :       if( (maxVal) > (maxAbs) ) maxAbs = maxVal;
    3308           0 :       if( (maxValMask) > (maxAbsMask) ) maxAbsMask = maxValMask;
    3309             : 
    3310           0 :       if( (minVal) < (minAbs) ) minAbs = minVal;
    3311           0 :       if( (minValMask) < (minAbsMask) ) minAbsMask = minValMask;
    3312           0 :       }
    3313             : 
    3314           0 :     }
    3315           0 :   }
    3316             : 
    3317           0 :   return True;
    3318             : 
    3319             : 
    3320           0 : }
    3321             : 
    3322             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3323             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3324             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3325             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3326             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    3327             : 
    3328             :   //
    3329             :   //-------------------------------------------------------------
    3330             :   // Initialize the internals of the object.  Perhaps other such
    3331             :   // initializations in the constructors can be moved here too.
    3332             :   //
    3333       13033 :   void SIImageStore::init()
    3334             :   {
    3335       13033 :     imageExts.resize(MAX_IMAGE_IDS);
    3336             : 
    3337       13033 :     imageExts(MASK) = ".mask";
    3338       13033 :     imageExts(PSF) = ".psf";
    3339       13033 :     imageExts(MODEL) = ".model";
    3340       13033 :     if (not itsIsSingleDishStore) {
    3341       12568 :       imageExts(RESIDUAL) = ".residual";
    3342       12568 :       imageExts(IMAGE) = ".image";
    3343             :     }
    3344             :     else {
    3345             :       // The initial residual image IS the single-dish image
    3346         465 :       imageExts(RESIDUAL) = ".image";
    3347             :       // Make sure we have no duplicates in the vector
    3348             :       // Not sure what should be done here
    3349         465 :       imageExts(IMAGE) = ".wrongly-deconvolved-single-dish-image";
    3350             :     }
    3351       13033 :     imageExts(WEIGHT) = ".weight";
    3352       13033 :     imageExts(SUMWT) = ".sumwt";
    3353       13033 :     imageExts(GRIDWT) = ".gridwt";
    3354       13033 :     imageExts(PB) = ".pb";
    3355       13033 :     imageExts(FORWARDGRID) = ".forward";
    3356       13033 :     imageExts(BACKWARDGRID) = ".backward";
    3357       13033 :     imageExts(IMAGEPBCOR) = ".image.pbcor";
    3358             : 
    3359       13033 :     itsParentPsf = itsPsf;
    3360       13033 :     itsParentModel = itsModel;
    3361       13033 :     itsParentResidual = itsResidual;
    3362       13033 :     itsParentWeight = itsWeight;
    3363       13033 :     itsParentImage = itsImage;
    3364       13033 :     itsParentSumWt = itsSumWt;
    3365       13033 :     itsParentMask = itsMask;
    3366       13033 :     itsParentImagePBcor = itsImagePBcor;
    3367             : 
    3368             :     // cout << "parent shape : " << itsParentImageShape
    3369             :     //   << "   shape : " << itsImageShape << endl;
    3370       13033 :     itsParentImageShape = itsImageShape;
    3371       13033 :     itsParentCoordSys = itsCoordSys;
    3372             : 
    3373       13033 :     if ( itsNFacets>1 or itsNChanChunks>1 or itsNPolChunks>1 ) {
    3374         258 :       itsImageShape = IPosition(4,0,0,0,0);
    3375             :     }
    3376             : 
    3377       13033 :     itsOpened = 0;
    3378             : 
    3379       13033 :     itsPSFSideLobeLevel = 0.0;
    3380       13033 :     itsReadLock = nullptr;
    3381       13033 :     itsDataPolRep = StokesImageUtil::UNKNOWN; // Should throw an exception if
    3382             :                                               // it is not initialized properly
    3383       13033 :   }
    3384             : 
    3385             : 
    3386          15 : void SIImageStore::regridToModelImage( ImageInterface<Float> &inputimage, Int term )
    3387             :   {
    3388             :     try 
    3389             :       {
    3390             : 
    3391             :     //output coords
    3392          15 :         IPosition outshape = itsImageShape;
    3393          15 :         CoordinateSystem outcsys = itsCoordSys;
    3394          15 :         DirectionCoordinate outDirCsys = outcsys.directionCoordinate();
    3395          15 :         SpectralCoordinate outSpecCsys = outcsys.spectralCoordinate();
    3396             :      
    3397             :         // do regrid   
    3398          15 :         IPosition axes(3,0, 1, 2);
    3399          15 :         IPosition inshape = inputimage.shape();
    3400          15 :         CoordinateSystem incsys = inputimage.coordinates(); 
    3401          15 :         DirectionCoordinate inDirCsys = incsys.directionCoordinate();
    3402          15 :         SpectralCoordinate inSpecCsys = incsys.spectralCoordinate();
    3403             : 
    3404          15 :         Vector<Int> dirAxes = CoordinateUtil::findDirectionAxes(incsys);
    3405          15 :         axes(0) = dirAxes(0); 
    3406          15 :         axes(1) = dirAxes(1);
    3407          15 :         axes(2) = CoordinateUtil::findSpectralAxis(incsys);
    3408             :         
    3409             :         try {
    3410          15 :           ImageRegrid<Float> imregrid;
    3411          15 :           imregrid.regrid( *(model(term)), Interpolate2D::LINEAR, axes, inputimage ); 
    3412          15 :         } catch (AipsError &x) {
    3413           0 :           throw(AipsError("ImageRegrid error : "+ x.getMesg()));
    3414           0 :         }
    3415             :         
    3416          15 :       }catch(AipsError &x)
    3417             :       {
    3418           0 :         throw(AipsError("Error in regridding input model image to target coordsys : " + x.getMesg()));
    3419           0 :       }
    3420          15 :   }
    3421             : 
    3422             :   //
    3423             :   //---------------------------------------------------------------
    3424             :   //
    3425           0 :   void SIImageStore::makePersistent(String& fileName)
    3426             :   {
    3427           0 :     LogIO logIO(LogOrigin("SIImageStore", "makePersistent"));
    3428           0 :     ofstream outFile; outFile.open(fileName.c_str(),std::ofstream::out);
    3429           0 :     if (!outFile) logIO << "Failed to open filed \"" << fileName << "\"" << LogIO::EXCEPTION;
    3430             :     //  String itsImageName;
    3431           0 :     outFile << "itsImageNameBase: " << itsImageName << endl;
    3432             : 
    3433             :     //IPosition itsImageShape;
    3434           0 :     outFile << "itsImageShape: " << itsImageShape.nelements() << " ";
    3435           0 :     for (uInt i=0;i<itsImageShape.nelements(); i++) outFile << itsImageShape(i) << " "; outFile << endl;
    3436             : 
    3437             :     // Don't know what to do with this.  Looks like this gets
    3438             :     // filled-in from one of the images.  So load this from one of the
    3439             :     // images if they exist?
    3440             :     //CoordinateSystem itsCoordSys; 
    3441             : 
    3442             :     // Int itsNFacets;
    3443           0 :     outFile << "itsNFacets: " << itsNFacets << endl;
    3444           0 :     outFile << "itsUseWeight: " << itsUseWeight << endl;
    3445             :     
    3446             : 
    3447             :     // Misc Information to go into the header. 
    3448             :     //    Record itsMiscInfo; 
    3449           0 :     itsMiscInfo.print(outFile);
    3450             :     
    3451             :     // std::shared_ptr<ImageInterface<Float> > itsMask, itsPsf, itsModel, itsResidual, itsWeight, itsImage, itsSumWt;
    3452             :     // std::shared_ptr<ImageInterface<Complex> > itsForwardGrid, itsBackwardGrid;
    3453             : 
    3454           0 :     Vector<Bool> ImageExists(MAX_IMAGE_IDS);
    3455           0 :     if ( ! itsMask )     ImageExists(MASK)=False;
    3456           0 :     if ( ! itsPsf )      ImageExists(PSF)=False;
    3457           0 :     if ( ! itsModel )    ImageExists(MODEL)=False;
    3458           0 :     if ( ! itsResidual ) ImageExists(RESIDUAL)=False;
    3459           0 :     if ( ! itsWeight )   ImageExists(WEIGHT)=False;
    3460           0 :     if ( ! itsImage )    ImageExists(IMAGE)=False;
    3461           0 :     if ( ! itsSumWt )    ImageExists(SUMWT)=False;
    3462           0 :     if ( ! itsGridWt )   ImageExists(GRIDWT)=False;
    3463           0 :     if ( ! itsPB )       ImageExists(PB)=False;
    3464             : 
    3465           0 :     if ( ! itsForwardGrid )    ImageExists(FORWARDGRID)=False;
    3466           0 :     if ( ! itsBackwardGrid )   ImageExists(BACKWARDGRID)=False;
    3467             :     
    3468           0 :     outFile << "ImagesExist: " << ImageExists << endl;
    3469           0 :   }
    3470             :   //
    3471             :   //---------------------------------------------------------------
    3472             :   //
    3473           0 :   void SIImageStore::recreate(String& fileName)
    3474             :   {
    3475           0 :     LogIO logIO(LogOrigin("SIImageStore", "recreate"));
    3476           0 :     ifstream inFile; inFile.open(fileName.c_str(),std::ofstream::out);
    3477           0 :     if (!inFile) logIO << "Failed to open filed \"" << fileName << "\"" << LogIO::EXCEPTION;
    3478             : 
    3479           0 :     String token;
    3480           0 :     inFile >> token; if (token == "itsImageNameBase:") inFile >> itsImageName;
    3481             : 
    3482           0 :     inFile >> token; 
    3483           0 :     if (token=="itsImageShape:")
    3484             :       {
    3485             :         Int n;
    3486           0 :         inFile >> n;
    3487           0 :         itsImageShape.resize(n);
    3488           0 :         for (Int i=0;i<n; i++) inFile >> itsImageShape(i);
    3489             :       }
    3490             : 
    3491             :     // Int itsNFacets;
    3492           0 :     inFile >> token; if (token=="itsNFacets:") inFile >> itsNFacets;
    3493           0 :     inFile >> token; if (token=="itsUseWeight:") inFile >> itsUseWeight;
    3494             : 
    3495           0 :     Bool coordSysLoaded=False;
    3496           0 :     String itsName;      
    3497             :     try 
    3498             :       {
    3499           0 :         itsName=itsImageName+imageExts(MASK);casa::openImage(itsName,     itsMask);
    3500           0 :         if (coordSysLoaded==False) {itsCoordSys=itsMask->coordinates(); itsMiscInfo=itsImage->miscInfo();coordSysLoaded=True;}
    3501           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3502             :     try 
    3503             :       {
    3504           0 :         itsName=itsImageName+imageExts(MODEL);casa::openImage(itsName,    itsModel);
    3505           0 :         if (coordSysLoaded==False) {itsCoordSys=itsModel->coordinates(); itsMiscInfo=itsModel->miscInfo();coordSysLoaded=True;}
    3506           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3507             :     try 
    3508             :       {
    3509           0 :         itsName=itsImageName+imageExts(RESIDUAL);casa::openImage(itsName, itsResidual);
    3510           0 :         if (coordSysLoaded==False) {itsCoordSys=itsResidual->coordinates(); itsMiscInfo=itsResidual->miscInfo();coordSysLoaded=True;}
    3511           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3512             :     try 
    3513             :       {
    3514           0 :         itsName=itsImageName+imageExts(WEIGHT);casa::openImage(itsName,   itsWeight);
    3515           0 :         if (coordSysLoaded==False) {itsCoordSys=itsWeight->coordinates(); itsMiscInfo=itsWeight->miscInfo();coordSysLoaded=True;}
    3516           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3517             :     try 
    3518             :       {
    3519           0 :         itsName=itsImageName+imageExts(IMAGE);casa::openImage(itsName,    itsImage);
    3520           0 :         if (coordSysLoaded==False) {itsCoordSys=itsImage->coordinates(); itsMiscInfo=itsImage->miscInfo();coordSysLoaded=True;}
    3521           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3522             :     try 
    3523             :       {
    3524           0 :         itsName=itsImageName+imageExts(SUMWT);casa::openImage(itsName,    itsSumWt);
    3525           0 :         if (coordSysLoaded==False) {itsCoordSys=itsSumWt->coordinates(); itsMiscInfo=itsSumWt->miscInfo();coordSysLoaded=True;}
    3526           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3527             :     try
    3528             :       {
    3529           0 :         itsName=itsImageName+imageExts(PSF);casa::openImage(itsName,      itsPsf);
    3530           0 :         if (coordSysLoaded==False) {itsCoordSys=itsPsf->coordinates(); itsMiscInfo=itsPsf->miscInfo();coordSysLoaded=True;}
    3531           0 :       } catch (AipsIO& x) {logIO << "\"" << itsName << "\" not found." << LogIO::WARN;};
    3532             :     try
    3533             :       {
    3534           0 :         casa::openImage(itsImageName+imageExts(FORWARDGRID),  itsForwardGrid);
    3535           0 :         casa::openImage(itsImageName+imageExts(BACKWARDGRID), itsBackwardGrid);
    3536             :       }
    3537           0 :     catch (AipsError& x)
    3538             :       {
    3539           0 :         logIO << "Did not find forward and/or backward grid.  Just say'n..." << LogIO::POST;
    3540           0 :       }
    3541             : 
    3542           0 :   }
    3543             : //////////////
    3544          15 :   Bool SIImageStore::intersectComplexImage(const String& ComplexImageName){
    3545          15 :         Vector<Int> whichStokes(0);
    3546          15 :         CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord( itsCoordSys,
    3547          15 :                                                                   whichStokes, itsDataPolRep);
    3548             : 
    3549             : 
    3550             :         //cerr <<"itsDataPolRep " << itsDataPolRep << endl;
    3551             :         
    3552          15 :         CountedPtr<PagedImage<Complex> > compliantImage =nullptr;
    3553             :         {
    3554          15 :           PagedImage<Complex>inputImage(ComplexImageName);
    3555          15 :           IPosition theShape=itsImageShape;
    3556          15 :           theShape(0)=inputImage.shape()(0);
    3557          15 :           theShape(1)=inputImage.shape()(1);
    3558          15 :           CoordinateSystem inpcsys=inputImage.coordinates();
    3559          15 :           Vector<Double> refpix=cimageCoord.referencePixel();
    3560          15 :           refpix(0)+=(theShape(0)-itsImageShape(0))/2.0;
    3561          15 :           refpix(1)+=(theShape(1)-itsImageShape(1))/2.0;
    3562          15 :           cimageCoord.setReferencePixel(refpix);
    3563          30 :           String tmpImage=File::newUniqueName(".", "TempImage").absoluteName();
    3564          15 :           compliantImage=new PagedImage<Complex>(theShape, cimageCoord, tmpImage);
    3565          15 :           compliantImage->set(0.0);
    3566          15 :           IPosition iblc(theShape.nelements(),0);
    3567          15 :           IPosition itrc=theShape-1;
    3568             :           //cerr << "blc "  << iblc << " trc " << itrc  << " shape " << theShape << endl;
    3569          15 :           LCBox lbox(iblc, itrc, theShape);
    3570          15 :           ImageRegion imagreg(WCBox(lbox, cimageCoord));
    3571             :                 
    3572             :           
    3573          15 :           SubImage<Complex> subim(inputImage, imagreg, false);
    3574             :           //cerr << "shapes " << inputImage.shape() << "  sub " << subim.shape() << " compl " << compliantImage->shape() << endl;
    3575          15 :           compliantImage->copyData(subim);
    3576             :                         
    3577          15 :         }
    3578          15 :         TableUtil::deleteTable(ComplexImageName);
    3579          15 :         compliantImage->rename(ComplexImageName);
    3580          15 :         return True;
    3581             :                 
    3582          15 :   }
    3583             :         
    3584             : 
    3585             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
    3586             :   //////////////////////////////////////////////////////////////////////////////////////////////////////
    3587             : 
    3588             : } //# NAMESPACE CASA - END
    3589             : 

Generated by: LCOV version 1.16