LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SynthesisNormalizer.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 131 446 29.4 %
Date: 2025-08-21 08:01:32 Functions: 14 24 58.3 %

          Line data    Source code
       1             : //# SynthesisNormalizer.cc: Implementation of Gather/Scatter for parallel major cycles
       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             : 
      42             : #include <casacore/casa/OS/DirectoryIterator.h>
      43             : #include <casacore/casa/OS/File.h>
      44             : #include <casacore/casa/OS/Path.h>
      45             : 
      46             : #include <casacore/casa/OS/HostInfo.h>
      47             : #include <casacore/lattices/Lattices/LatticeLocker.h>
      48             : #include <casacore/images/Images/TempImage.h>
      49             : #include <casacore/images/Images/SubImage.h>
      50             : #include <casacore/images/Regions/ImageRegion.h>
      51             : 
      52             : #include <synthesis/ImagerObjects/SynthesisNormalizer.h>
      53             : 
      54             : #include <sys/types.h>
      55             : #include <unistd.h>
      56             : using namespace std;
      57             : 
      58             : using namespace casacore;
      59             : namespace casa { //# NAMESPACE CASA - BEGIN
      60             :   
      61          17 :   SynthesisNormalizer::SynthesisNormalizer() :
      62          17 :       itsImages(std::shared_ptr<SIImageStore>()),
      63          17 :       itsPartImages(Vector<std::shared_ptr<SIImageStore> >()),
      64          17 :       itsImageName(""),
      65          17 :       itsPartImageNames(Vector<String>(0)),
      66          17 :       itsPBLimit(0.2),
      67          17 :       itsMapperType("default"),
      68          17 :       itsNTaylorTerms(1),
      69          17 :       itsNFacets(1),
      70          51 :       itsIsSingleDish(False)
      71             :   {
      72          17 :     itsFacetImageStores.resize(0);
      73          17 :     itsPBLimit = 0.35;
      74          17 :   }
      75             :   
      76          17 :   SynthesisNormalizer::~SynthesisNormalizer() 
      77             :   {
      78          34 :     LogIO os( LogOrigin("SynthesisNormalizer","destructor",WHERE) );
      79          17 :     os << LogIO::DEBUG1 << "SynthesisNormalizer destroyed" << LogIO::POST;
      80          17 :     SynthesisUtilMethods::getResource("End SynthesisNormalizer");
      81             : 
      82          17 :   }
      83             :   
      84             :   
      85          17 :   void SynthesisNormalizer::setupNormalizer(Record normpars)
      86             :   {
      87          34 :     LogIO os( LogOrigin("SynthesisNormalizer","setupNormalizer",WHERE) );
      88             : 
      89             :     try {
      90          17 :       if ( normpars.isDefined("psfcutoff") ) { // A single string
      91          17 :         normpars.get( RecordFieldId("psfcutoff") , itsPsfcutoff );
      92             :       } else {
      93           0 :         itsPsfcutoff=0.35;
      94             :       }
      95             : 
      96          17 :       if ( normpars.isDefined("imagename") ) { // A single string
      97          17 :         itsImageName = normpars.asString( RecordFieldId("imagename")); 
      98             :       } else {
      99           0 :         throw AipsError("imagename not specified");
     100             :       }
     101             : 
     102          17 :       if ( normpars.isDefined("partimagenames") ) { // A vector of strings
     103           0 :         normpars.get( RecordFieldId("partimagenames") , itsPartImageNames );
     104             :       } else {
     105          17 :         itsPartImageNames.resize(0);
     106             :       }
     107             : 
     108          17 :       if ( normpars.isDefined("pblimit") ) {
     109          17 :         normpars.get( RecordFieldId("pblimit") , itsPBLimit );
     110             :       } else {
     111           0 :         itsPBLimit = 0.2;
     112             :       }
     113             : 
     114          17 :       if ( normpars.isDefined("normtype") ) { // A single string
     115          17 :         itsNormType = normpars.asString( RecordFieldId("normtype"));
     116             :       } else {
     117           0 :         itsNormType = "flatnoise"; // flatnoise, flatsky
     118             :       }
     119             : 
     120             :       { // Debug comments
     121             :         //      cout << "Chosen normtype : " << itsNormType << endl;
     122             : 
     123             :         // For multi-term choices.
     124             :         // Try to eliminate, after making imstores hold aux descriptive info.
     125             :         /*
     126             :         if ( normpars.isDefined("mtype") )  // A single string
     127             :           { itsMapperType = normpars.asString( RecordFieldId("mtype")); }
     128             :         else
     129             :           { itsMapperType = "default";}
     130             :         */
     131             :       }
     132             : 
     133          17 :       if ( normpars.isDefined("deconvolver") ) { // A single string
     134          17 :         String dec = normpars.asString( RecordFieldId("deconvolver"));
     135          17 :         if (dec == "mtmfs") { itsMapperType="multiterm"; }
     136          17 :         else itsMapperType="default";
     137          17 :       } else {
     138           0 :         itsMapperType = "default";
     139             :       }
     140             : 
     141          17 :       if ( normpars.isDefined("nterms") ) { // A single int
     142          17 :         itsNTaylorTerms = normpars.asuInt( RecordFieldId("nterms")); }
     143             :       else {
     144           0 :         itsNTaylorTerms = 1;
     145             :       }
     146             : 
     147          17 :       if ( normpars.isDefined("facets") ) { // A single int
     148          17 :         itsNFacets = normpars.asuInt( RecordFieldId("facets"));
     149             :       } else { 
     150           0 :         itsNFacets = 1;
     151             :       }
     152             : 
     153          17 :       if ( normpars.isDefined("restoringbeam") ) {
     154          17 :         if (normpars.dataType("restoringbeam") == TpString) {
     155           0 :           itsUseBeam = normpars.asString( RecordFieldId("restoringbeam") );
     156             :         } else {
     157          17 :           itsUseBeam = "";
     158             :         } 
     159             :       } // else: keep itsUseBeam unchanged
     160             : 
     161          17 :       if ( normpars.isDefined("makesingledishnormalizer") ) { // A single bool
     162          17 :         itsIsSingleDish =
     163          17 :           normpars.asBool( RecordFieldId("makesingledishnormalizer") );
     164             :       } else { 
     165           0 :         itsIsSingleDish = False;
     166             :       }
     167             : 
     168             :     }
     169           0 :     catch (AipsError &x) {
     170           0 :       throw AipsError(
     171           0 :           "Error in reading gather/scatter parameters: " + x.getMesg()
     172           0 :         );
     173           0 :     }
     174             : 
     175          17 :   } // end of setupNormalizer
     176             : 
     177             : 
     178          34 :   void SynthesisNormalizer::gatherImages(Bool dopsf, Bool doresidual, Bool dodensity)
     179             :   {
     180             :     //    cout << " partimagenames :" << itsPartImageNames << endl;
     181             : 
     182          34 :     Bool needToGatherImages = setupImagesOnDisk();
     183             :     //if(dopsf)
     184             :     //  cerr << "GATHER " << itsImages->psf()->shape() << endl;
     185             : 
     186          34 :     if( needToGatherImages )
     187             :       {
     188           0 :         LogIO os( LogOrigin("SynthesisNormalizer", "gatherImages",WHERE) );
     189             : 
     190           0 :         AlwaysAssert( itsPartImages.nelements()>0 , AipsError );
     191             :         //Bool doresidual = !dopsf;
     192           0 :         Bool doweight = dopsf ; //|| ( doresidual && ! itsImages->hasSensitivity() );
     193             :         //      Bool doweight = dopsf || ( doresidual && itsImages->getUseWeightImage(*(itsPartImages[0]->residual())) );
     194             :         
     195           0 :         os << "Gather "<< (doresidual?"residual":"") << ( (dopsf&&doresidual)?",":"")  
     196           0 :            << (dopsf?"psf":"") << ( (dopsf&&doweight)?",":"")  
     197             :            << (doweight?"weight":"")<< " images : " << itsPartImageNames 
     198           0 :            << " onto :" << itsImageName << LogIO::POST;
     199             :         
     200             :         // Add intelligence to modify all only the first time, but later, only residual;
     201           0 :         itsImages->resetImages( /*psf*/dopsf, /*residual*/doresidual, /*weight*/doweight ); 
     202             :         
     203           0 :         for( uInt part=0;part<itsPartImages.nelements();part++)
     204             :           {
     205           0 :             itsImages->addImages( itsPartImages[part], /*psf*/dopsf, /*residual*/doresidual, /*weight*/doweight, /*griddedwt*/dodensity );
     206           0 :             itsPartImages[part]->releaseLocks();
     207             :           }
     208             : 
     209           0 :       }// end of image gathering.
     210             :     
     211             :     // Normalize by the weight image.
     212             :     //    divideResidualByWeight();
     213          34 :     itsImages->releaseLocks();
     214             :     
     215          34 :   }// end of gatherImages
     216             : 
     217          17 :   void SynthesisNormalizer::gatherPB()
     218             :   {
     219          17 :     if( itsPartImageNames.nelements()>0 )
     220             :       {
     221             : 
     222             :         try
     223             :           {
     224           0 :             itsPartImages[0] = makeImageStore( itsPartImageNames[0] );
     225             :           }
     226           0 :         catch(AipsError &x)
     227             :           {
     228           0 :             throw(AipsError("Cannot construct ImageStore for "+itsPartImageNames[0]+". "+x.what()));
     229           0 :           }
     230             : 
     231             :         try{
     232           0 :             LatticeExpr<Float> thepb( *(itsPartImages[0]->pb()) );
     233           0 :             LatticeLocker lock1(*(itsImages->pb()), FileLocker::Write);
     234           0 :             itsImages->pb()->copyData(thepb);
     235             : 
     236           0 :           }
     237           0 :         catch(AipsError &x)
     238             :           {
     239           0 :             throw(AipsError("Cannot copy the PB : "+x.getMesg()));
     240           0 :           }
     241             : 
     242             :       }
     243          17 :   }
     244             : 
     245          17 :   void SynthesisNormalizer::scatterModel()
     246             :   {
     247             : 
     248          34 :     LogIO os( LogOrigin("SynthesisNormalizer", "scatterModel",WHERE) );
     249             : 
     250          17 :     setupImagesOnDisk(); // To open up and initialize itsPartImages.
     251             : 
     252             :     //    os << "In ScatterModel : " << itsPartImages.nelements() << " for " << itsPartImageNames << LogIO::POST;
     253             :     
     254          17 :     if( itsPartImages.nelements() > 0 ) // && itsImages->doesImageExist(modelName) )
     255             :       {
     256           0 :         os << "Send the model from : " << itsImageName << " to all nodes :" << itsPartImageNames << LogIO::POST;
     257             :         
     258             :         // Make the list of model images. This list is of length >1 only for multi-term runs.
     259             :         // Vector<String> modelNames( itsImages->getNTaylorTerms() );
     260             :         // if( modelNames.nelements() ==1 ) modelNames[0] = itsImages->getName()+".model";
     261             :         // if( modelNames.nelements() > 1 ) 
     262             :         //   {
     263             :         //     for( uInt nt=0;nt<itsImages->getNTaylorTerms();nt++)
     264             :         //       modelNames[nt] = itsImages->getName()+".model.tt" + String::toString(nt);
     265             :         //   }
     266             : 
     267             : 
     268           0 :         Vector<String> modelNames( itsImages->getNTaylorTerms() );
     269           0 :         if( itsImages->getType()=="default" ) modelNames[0] = itsImages->getName()+".model";
     270           0 :         if( itsImages->getType()=="multiterm" ) 
     271             :           {
     272           0 :             for( uInt nt=0;nt<itsImages->getNTaylorTerms();nt++)
     273           0 :               modelNames[nt] = itsImages->getName()+".model.tt" + String::toString(nt);
     274             :           }
     275             :         
     276             :         
     277             :         
     278           0 :         for( uInt part=0;part<itsPartImages.nelements();part++)
     279             :           {
     280           0 :             itsPartImages[part]->setModelImage( modelNames );
     281           0 :             itsPartImages[part]->releaseLocks();
     282             :           }
     283           0 :         itsImages->releaseLocks();
     284           0 :       }
     285             :     
     286          17 :   }// end of scatterModel
     287             :   
     288             : //----------------
     289             : 
     290           0 : void SynthesisNormalizer::gatherWeightDensity(){
     291             : 
     292           0 :   Bool needToGatherImages = setupImagesOnDisk();
     293             :   // if(dopsf)
     294             :   //   cerr << "GATHER " << itsImages->psf()->shape() << endl;
     295             : 
     296           0 :   if (needToGatherImages) {
     297           0 :     LogIO os(LogOrigin("SynthesisNormalizer", "gatherWeightDensity", WHERE));
     298             : 
     299           0 :     itsImages->gridwt()->set(0.0);
     300           0 :     Record iminfo(itsImages->gridwt()->miscInfo());
     301           0 :     Vector<Float> d2out;
     302           0 :     Vector<Float> f2out;
     303           0 :     if(iminfo.isDefined("d2")){
     304           0 :       iminfo.get("d2", d2out);
     305           0 :       iminfo.get("f2", f2out);
     306             :     }
     307           0 :     Vector<Float> f2part(f2out.nelements(), 0.0);
     308           0 :     bool recalcF2 = (d2out.nelements() >0 && d2out[0] == 1.0); // need to recalculate F2 for normalized Briggs
     309           0 :     if(recalcF2)
     310           0 :       f2out.set(0.0);
     311           0 :     Int nxim = itsImages->gridwt()->shape()(0);
     312           0 :     Int nyim = itsImages->gridwt()->shape()(1);
     313           0 :     for (uInt part = 0; part < itsPartImages.nelements(); part++) {
     314           0 :       itsImages->addImages(itsPartImages[part], false,
     315             :                            /*residual*/ false, /*weight*/ false,
     316             :                            /*griddedwt*/ true);
     317           0 :       Record partiminfo(itsPartImages[part]->gridwt()->miscInfo());
     318           0 :       mergeWeightDensityInfo(iminfo, partiminfo);
     319           0 :       if (recalcF2) {
     320           0 :         Vector<Float> f2in;
     321           0 :         (itsPartImages[part]->gridwt()->miscInfo()).get("f2", f2in);
     322           0 :         Array<Float> arr;
     323           0 :         if (d2out.nelements() > 1) {
     324           0 :           IPosition blc(5, 0, 0, 0, 0, 0);
     325           0 :           IPosition shp(5, nxim, nyim, 1, 1, 1);
     326           0 :           for (uInt k = 0; k < d2out.nelements(); ++k) {
     327           0 :             blc[4] = k;
     328           0 :             itsPartImages[part]->gridwt()->getSlice(arr, blc, shp, True);
     329           0 :             f2in[k] = f2in[k] * sum(arr * arr);
     330             :           }
     331           0 :         }
     332             :         else{ //not multifield weighting
     333           0 :           itsPartImages[part]->gridwt()->get(arr, True);
     334           0 :           f2in[0] = f2in[0] * sum(arr * arr);
     335             :         }
     336           0 :         f2out += f2in;
     337           0 :       }
     338           0 :       itsPartImages[part]->releaseLocks();
     339           0 :     }
     340           0 :     if(recalcF2){
     341           0 :       Array<Float> arr;
     342           0 :       if (d2out.nelements() > 1) {
     343           0 :         IPosition blc(5, 0, 0, 0, 0, 0);
     344           0 :         IPosition shp(5, nxim, nyim, 1, 1, 1);
     345           0 :         for (uInt k = 0; k < d2out.nelements(); ++k) {
     346           0 :           blc[4] = k;
     347           0 :           itsImages->gridwt()->getSlice(arr, blc, shp, True);
     348           0 :           Float sumarr2 = sum(arr * arr);
     349           0 :           if(sumarr2> 0)
     350           0 :             f2out[k] = f2out[k] / sumarr2;
     351             :         }
     352           0 :       }
     353             :       else{
     354           0 :         itsImages->gridwt()->get(arr, True);
     355           0 :         Float sumarr2 = sum(arr * arr);
     356           0 :         if (sumarr2 > 0)
     357           0 :           f2out[0] = f2out[0] / sumarr2;
     358             :       }
     359           0 :       iminfo.define("f2", f2out);
     360             :       
     361           0 :     }
     362           0 :     itsImages->gridwt()->setMiscInfo(iminfo);
     363             :     
     364           0 :   } // end of image gathering.
     365             : 
     366             :   // Normalize by the weight image.
     367             :   //    divideResidualByWeight();
     368           0 :   itsImages->releaseLocks();
     369             : 
     370           0 : }//end of gatherweightdensity
     371             : 
     372             : //-------------------------
     373             : 
     374             : 
     375           0 :   string SynthesisNormalizer::scatterWeightDensity()
     376             :   {
     377             : 
     378           0 :     LogIO os( LogOrigin("SynthesisNormalizer", "scatterWeightDensity",WHERE) );
     379             : 
     380           0 :     setupImagesOnDisk(); // To open up and initialize itsPartImages.
     381           0 :     string weightname = "";
     382             :     //    os << "In ScatterModel : " << itsPartImages.nelements() << " for " <<
     383             :     //    itsPartImageNames << LogIO::POST;
     384             : 
     385           0 :     if( itsPartImages.nelements() > 0 )
     386             :       {
     387           0 :         os << "Send the gridded weight from : " << itsImageName << " to all nodes :" << itsPartImageNames << LogIO::POST;
     388             :         
     389           0 :         for( uInt part=0;part<itsPartImages.nelements();part++)
     390             :           {
     391           0 :             itsPartImages[part]->setWeightDensity( itsImages );
     392           0 :             itsPartImages[part]->releaseLocks();
     393             :           }
     394           0 :           weightname=itsImages->gridwt()->name();
     395           0 :           itsImages->releaseLocks();
     396             :       }
     397           0 :       return weightname;
     398           0 :   } // end of gatherImages
     399             : 
     400          17 :   void SynthesisNormalizer::divideResidualByWeight()
     401             :   {
     402          34 :     LogIO os( LogOrigin("SynthesisNormalizer", "divideResidualByWeight",WHERE) );
     403             : 
     404          17 :     if( itsNFacets==1) {
     405          17 :       itsImages->divideResidualByWeight( itsPBLimit, itsNormType );
     406             :     }
     407             :     else {
     408           0 :       for ( uInt facet=0; facet<itsNFacets*itsNFacets; facet++ )
     409           0 :         { itsFacetImageStores[facet]->divideResidualByWeight( itsPBLimit , itsNormType ); }
     410             :     }
     411          17 :     itsImages->releaseLocks();
     412             :     
     413          17 :   }
     414             :   
     415           0 :   void SynthesisNormalizer::divideResidualByWeightSD()
     416             :   {
     417           0 :     LogIO os( LogOrigin("SynthesisNormalizer", "divideResidualByWeightSD",WHERE) );
     418             : 
     419           0 :     if( itsNFacets==1) {
     420           0 :       itsImages->divideResidualByWeightSD( itsPBLimit );
     421             :     }
     422             :     else {
     423           0 :       for ( uInt facet=0; facet<itsNFacets*itsNFacets; facet++ )
     424           0 :         { itsFacetImageStores[facet]->divideResidualByWeightSD( itsPBLimit ); }
     425             :     }
     426           0 :     itsImages->releaseLocks();
     427             : 
     428           0 :   }
     429           0 :   void SynthesisNormalizer::makePSFBeamset(){
     430           0 :     LogIO os(LogOrigin("SynthesisNormalizer", "dividePSFByWeight", WHERE));
     431             :     try{
     432           0 :       if(!itsImages){
     433           0 :         itsImages = makeImageStore( itsImageName, false );
     434             :       }
     435             : 
     436             : 
     437             :     }
     438           0 :     catch(AipsError& x){
     439             : 
     440           0 :       throw(AipsError("Programmers error no psf is made on disk and  trying to fit"));
     441           0 :     }
     442           0 :     itsImages->makeImageBeamSet(itsPsfcutoff);
     443           0 :     itsImages->releaseLocks();
     444           0 :   }
     445             : 
     446             : 
     447          17 :   void SynthesisNormalizer::divideWeightBySumWt() {
     448             : 
     449          34 :     LogIO os(LogOrigin("SynthesisNormalizer", "divideWeightBySumWt", WHERE));
     450          17 :     itsImages->divideWeightBySumwt();
     451             : 
     452          17 :   }
     453             :   
     454             : 
     455             :   
     456          17 :   void SynthesisNormalizer::dividePSFByWeight()
     457             :   {
     458          34 :     LogIO os( LogOrigin("SynthesisNormalizer", "dividePSFByWeight",WHERE) );
     459             :     {
     460             :      
     461          17 :       LatticeLocker lock1 (*(itsImages->psf()), FileLocker::Write);
     462             :     
     463          17 :       if( itsNFacets==1) {
     464          17 :         itsImages->dividePSFByWeight(itsPBLimit);
     465             :       }
     466             :       else {
     467             :         // Since PSFs are normed just by their max, this sequence is OK.
     468           0 :         setPsfFromOneFacet();
     469           0 :         itsImages->dividePSFByWeight(itsPBLimit);
     470             :       }
     471          17 :     }// release of lock1 otherwise releaselock below will cause it to core
     472             :     //dump as the psf pointer goes dangling
     473             :       // Check PSF quality by fitting beams
     474             :     {
     475          17 :       itsImages->calcSensitivity();
     476             :     
     477          17 :       itsImages->makeImageBeamSet(itsPsfcutoff);
     478          17 :       Bool verbose(False);
     479          17 :       if (itsUseBeam=="common") verbose=True;
     480          17 :       itsImages->printBeamSet(verbose);
     481             :     }
     482          17 :     itsImages->releaseLocks();
     483             : 
     484          17 :   }
     485             : 
     486          17 :   void SynthesisNormalizer::normalizePrimaryBeam()
     487             :   {
     488          34 :     LogIO os( LogOrigin("SynthesisNormalizer", "normalizePrimaryBeam",WHERE) );
     489             : 
     490          17 :     if( itsImages==NULL ) { itsImages = makeImageStore( itsImageName ); }
     491             : 
     492          17 :     gatherPB();
     493             : 
     494             :     // Irrespective of facets.
     495          17 :     itsImages->normalizePrimaryBeam(itsPBLimit);
     496          17 :   }
     497             : 
     498             : 
     499          17 :   void SynthesisNormalizer::divideModelByWeight()
     500             :   {
     501          34 :     LogIO os( LogOrigin("SynthesisNormalizer", "divideModelByWeight",WHERE) );
     502          17 :     if( ! itsImages ) 
     503             :       {
     504             :         //os << LogIO::WARN << "No imagestore yet. Trying to construct, so that the starting model can be divided by wt if needed...." << LogIO::POST;
     505             :         
     506             :         try
     507             :           {
     508           0 :             itsImages = makeImageStore( itsImageName );
     509             :           }
     510           0 :         catch(AipsError &x)
     511             :           {
     512           0 :             throw(AipsError("Cannot construct ImageStore for "+itsImageName+". "+x.what()));
     513           0 :           }
     514             :         //      return;
     515             :       }
     516          17 :     if( itsNFacets==1) {
     517          17 :       itsImages->divideModelByWeight( itsPBLimit, itsNormType );
     518             :     }
     519             :     else {
     520           0 :       for ( uInt facet=0; facet<itsNFacets*itsNFacets; facet++ )
     521           0 :         { itsFacetImageStores[facet]->divideModelByWeight( itsPBLimit, itsNormType ); }
     522             :     }
     523          17 :  }
     524             : 
     525          17 :   void SynthesisNormalizer::multiplyModelByWeight()
     526             :   {
     527             :     //    LogIO os( LogOrigin("SynthesisNormalizer", "multiplyModelByWeight",WHERE) );
     528          17 :     if( itsNFacets==1) {
     529          17 :       itsImages->multiplyModelByWeight( itsPBLimit , itsNormType );
     530             :     }
     531             :     else {
     532           0 :       for ( uInt facet=0; facet<itsNFacets*itsNFacets; facet++ )
     533           0 :         { itsFacetImageStores[facet]->multiplyModelByWeight( itsPBLimit , itsNormType); }
     534             :     }
     535          17 :  }
     536             : 
     537             : 
     538           0 :   std::shared_ptr<SIImageStore> SynthesisNormalizer::getImageStore()
     539             :   {
     540           0 :     LogIO os( LogOrigin("SynthesisNormalizer", "getImageStore", WHERE) );
     541           0 :     return itsImages;
     542           0 :   }
     543             : 
     544           0 :   void SynthesisNormalizer::setImageStore( SIImageStore* imstore )
     545             :   {
     546           0 :     LogIO os( LogOrigin("SynthesisNormalizer", "setImageStore", WHERE) );
     547           0 :     itsImages.reset( imstore );
     548           0 :   }
     549             : 
     550           0 :   void SynthesisNormalizer::setImageStore( std::shared_ptr<SIImageStore>& imstore )
     551             :   {
     552           0 :     LogIO os( LogOrigin("SynthesisNormalizer", "setImageStore", WHERE) );
     553           0 :     itsImages= imstore ;
     554             :     
     555           0 :   }
     556             : 
     557             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     558             :   ////    Internal Functions start here.  These are not visible to the tool layer.
     559             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     560             : 
     561             : 
     562          51 :   Bool SynthesisNormalizer::setupImagesOnDisk() {
     563         102 :     LogIO os( LogOrigin("SynthesisNormalizer","setupImagesOnDisk",WHERE) );
     564             : 
     565          51 :     Bool needToGatherImages = false;
     566             : 
     567          51 :     String err("");
     568             : 
     569             :     // Check if full images exist, and open them if possible.
     570          51 :     Bool foundFullImage = false;
     571             :     try {
     572          51 :       itsImages = makeImageStore( itsImageName );
     573          51 :       foundFullImage = true;
     574             :     }
     575           0 :     catch (AipsError &x) {
     576             :       //throw( AipsError("Error in constructing a Deconvolver : "+x.getMesg()) );
     577           0 :       err = err += String(x.getMesg()) + "\n";
     578           0 :       foundFullImage = false;
     579           0 :     }
     580             : 
     581             :     os << LogIO::DEBUG2
     582             :       << " Found full images : " << foundFullImage
     583          51 :       << LogIO::POST;
     584             : 
     585             :     // Check if part images exist
     586          51 :     Bool foundPartImages = itsPartImageNames.nelements() > 0 ? true : false ;
     587          51 :     itsPartImages.resize( itsPartImageNames.nelements() );
     588             : 
     589          51 :     for ( uInt part=0; part < itsPartImageNames.nelements() ; part++ ) {
     590             :       try {
     591           0 :         itsPartImages[part] = makeImageStore ( itsPartImageNames[part] );
     592           0 :         foundPartImages |= true;
     593             :       }
     594           0 :       catch (AipsError &x) {
     595             :         // throw AipsError(
     596             :         //        "Error in constructing a Deconvolver : " + x.getMesg()
     597             :         //       );
     598           0 :         err = err += String(x.getMesg()) + "\n";
     599           0 :         foundPartImages = false;
     600           0 :       }
     601             :     }
     602             : 
     603             :     os << LogIO::DEBUG2
     604             :       << " Found part images : " << foundPartImages
     605          51 :       << LogIO::POST;
     606             : 
     607          51 :     if ( not foundPartImages ) {
     608          51 :       if ( foundFullImage and itsPartImageNames.nelements() > 0 ) {
     609             :         // Pick the coordsys, etc from fullImage,
     610             :         // and construct new/fresh partial images.
     611             :         os << LogIO::DEBUG2
     612             :           << "Found full image, but no partial images."
     613             :           << " Making partImStores for : " << itsPartImageNames
     614           0 :           << LogIO::POST;
     615             : 
     616           0 :         String imopen = itsImages->getName() + ".residual"
     617           0 :           + ( (itsMapperType == "multiterm") ? ".tt0" : "" );
     618           0 :         Directory imdir( imopen );
     619           0 :         if ( not imdir.exists() ) {
     620           0 :           imopen = itsImages->getName() + ".psf"
     621           0 :           + ( (itsMapperType == "multiterm") ? ".tt0" : "" );
     622           0 :           Directory imdir2( imopen );
     623           0 :           if ( not imdir2.exists() )
     624           0 :             throw AipsError(
     625             :               "Cannot find partial image psf or residual for "
     626           0 :               + itsImages->getName() + err
     627           0 :             );
     628           0 :         }
     629             : 
     630           0 :         PagedImage<Float> temppart(imopen);
     631             : 
     632             :         Bool useweightimage =
     633           0 :           itsImages->getUseWeightImage( *(itsImages->sumwt()) );
     634           0 :         for ( uInt part=0; part<itsPartImageNames.nelements(); part++ ) {
     635           0 :           itsPartImages[part] = makeImageStore(
     636           0 :             itsPartImageNames[part], temppart, useweightimage);
     637             :         }
     638           0 :         foundPartImages = True;
     639           0 :       } else {
     640          51 :         itsPartImages.resize(0); 
     641          51 :         foundPartImages = False;
     642             :       }
     643             :     } else { // Check that all have the same shape.
     644           0 :       AlwaysAssert( itsPartImages.nelements() > 0 , AipsError );
     645           0 :       IPosition tempshape = itsPartImages[0]->getShape();
     646           0 :       for ( uInt part=1; part<itsPartImages.nelements(); part++ ) {
     647           0 :         if ( tempshape != itsPartImages[part]->getShape() ) {
     648           0 :           throw AipsError(
     649           0 :             "Shapes of partial images to be combined, do not match" + err
     650           0 :           );
     651             :         }
     652             :       }
     653           0 :     }
     654             : 
     655             :     // Make sure all images exist and are consistent with each other.
     656             :     // At the end, itsImages should be valid
     657          51 :     if ( foundPartImages ) { // Partial Images exist. Check that 'full' exists,
     658             :                              // and do the gather. 
     659           0 :       if ( foundFullImage ) { // Full image exists.
     660             :                               // Just check that shapes match with parts.
     661             :         os << LogIO::DEBUG2
     662             :           << "Partial and Full images exist."
     663           0 :           << "Checking if part images have the same shape as the full image : ";
     664             : 
     665           0 :         IPosition fullshape = itsImages->getShape();
     666           0 :         for ( uInt part=0; part < itsPartImages.nelements() ; part++ ) {
     667           0 :           IPosition partshape = itsPartImages[part]->getShape();
     668           0 :           if ( partshape != fullshape ) {
     669             :             os << LogIO::DEBUG2
     670           0 :               << "NO" << LogIO::POST;
     671           0 :             throw AipsError(
     672             :               "Shapes of the partial and full images on disk do not match."
     673           0 :               " Cannot gather" + err
     674           0 :             );
     675             :           }
     676           0 :         }
     677           0 :         os << LogIO::DEBUG2 << "Yes" << LogIO::POST;
     678             : 
     679           0 :       } else { // Full image does not exist. 
     680             :                // Need to make it, using the shape and coords of part[0]
     681             :         os << LogIO::DEBUG2 
     682             :           << "Only partial images exist. Need to make full images"
     683           0 :             << LogIO::POST  ;
     684             : 
     685           0 :         AlwaysAssert( itsPartImages.nelements() > 0, AipsError );
     686             : 
     687             :         // Find an image to open and pick csys,shape from.
     688           0 :         String imopen = itsPartImageNames[0] + ".residual"
     689           0 :           + ( (itsMapperType == "multiterm") ? ".tt0" : "" );
     690           0 :         Directory imdir( imopen );
     691           0 :         if ( not imdir.exists() ) {
     692           0 :           imopen = itsPartImageNames[0] + ".psf"
     693           0 :             + ( (itsMapperType == "multiterm") ? ".tt0" : "" );
     694           0 :           Directory imdir2( imopen );
     695           0 :           if ( not imdir2.exists() ) {
     696           0 :             imopen = itsPartImageNames[0] + ".gridwt";
     697           0 :             Directory imdir3( imopen );
     698           0 :             if ( not imdir3.exists() )
     699           0 :               throw AipsError(
     700             :                 "Cannot find partial image psf or residual or gridwt for "
     701           0 :                 + itsPartImageNames[0] + err
     702           0 :               );
     703           0 :           }
     704           0 :         }
     705             : 
     706           0 :         PagedImage<Float> temppart( imopen );
     707             : 
     708             :         Bool useweightimage =
     709           0 :           itsPartImages[0]->getUseWeightImage( *(itsPartImages[0]->sumwt()) );
     710           0 :         itsImages = makeImageStore (itsImageName, temppart, useweightimage);
     711           0 :         foundFullImage = true;
     712           0 :       }
     713             : 
     714             :       // By now, all partial images and the full images exist on disk,
     715             :       // and have the same shape.
     716           0 :       needToGatherImages = true;
     717             :     } else { // No partial images supplied. Operating only with full images.
     718             : 
     719          51 :       if ( foundFullImage ) {
     720             :           os << LogIO::DEBUG2
     721          51 :             << "Full images exist : " << itsImageName
     722          51 :             << LogIO::POST;
     723             :       }
     724             :       else { // No full image on disk either. Error.
     725           0 :           throw AipsError(
     726           0 :             "No images named " + itsImageName 
     727           0 :             + " found on disk. No partial images found either." + err
     728           0 :           );
     729             :       }
     730             :     }
     731             : 
     732             :     // Remove ?
     733          51 :     itsImages->psf();
     734             : 
     735          51 :     itsImages->validate();
     736             : 
     737             :     // Set up facet Imstores..... if needed
     738          51 :     if ( itsNFacets > 1 ) {
     739             :       // First, make sure that full images have been allocated
     740             :       // before trying to make references.....
     741             :       //    if ( not itsImages->checkValidity(
     742             :       //                true/*psf*/,
     743             :       //                true/*res*/,
     744             :       //                true/*wgt*/,
     745             :       //                true/*model*/,
     746             :       //                false/*image*/,
     747             :       //                false/*mask*/,
     748             :       //                true/*sumwt*/ ) ) {
     749             :       //      throw AipsError(
     750             :       //        "Internal Error : Invalid ImageStore for "
     751             :       //         + itsImages->getName())
     752             :       //      );
     753             :       //    }
     754             : 
     755             :       //        Array<Float> ttt;
     756             :       //        (itsImages->sumwt())->get(ttt);
     757             :       //        cout << "SUMWT full : " << ttt <<  endl;
     758             :         
     759           0 :       itsFacetImageStores.resize( itsNFacets*itsNFacets );
     760           0 :       for ( uInt facet=0; facet<itsNFacets*itsNFacets; ++facet ) {
     761           0 :         itsFacetImageStores[facet] =
     762           0 :           itsImages->getSubImageStore(facet, itsNFacets);
     763             :         // Array<Float> qqq;
     764             :         // itsFacetImageStores[facet]->sumwt()->get(qqq);
     765             :         // cout << "SUMWTs for " << facet << " : " << qqq << endl;
     766             :       }
     767             :     }
     768             : 
     769             :     os << LogIO::DEBUG2
     770             :       << "Need to Gather ? " << needToGatherImages
     771          51 :       << LogIO::POST;
     772             : 
     773          51 :     itsImages->releaseLocks();
     774             : 
     775          51 :     return needToGatherImages;
     776          51 :   } // end of setupImagesOnDisk
     777             : 
     778             : 
     779          51 :   std::shared_ptr<SIImageStore> SynthesisNormalizer::makeImageStore(
     780             :     const String &imagename,
     781             :     const bool useweightimage)
     782             :   {
     783             :     // The constructors use ignoresumwt so use the !useweightimage
     784          51 :     if ( itsMapperType == "multiterm" ) {
     785             :       return std::shared_ptr<SIImageStore>(
     786             :         new SIImageStoreMultiTerm(
     787             :           imagename,
     788             :           itsNTaylorTerms,
     789             :           /* ignorefacets= */ true,
     790           0 :           /* ignoresumwt=  */ not useweightimage
     791           0 :         )
     792           0 :       );
     793             :     } else {
     794             :       return std::shared_ptr<SIImageStore>(
     795             :         new SIImageStore(
     796             :           imagename,
     797             :           /* ignorefacets= */ true,
     798          51 :           /* noRequireSumwt= */ not useweightimage,
     799          51 :           /* makeSingleDishStore= */ itsIsSingleDish
     800          51 :         )
     801          51 :       );
     802             :     }
     803             :     itsImages->releaseLocks();
     804             :   }
     805             : 
     806             : 
     807             :  /**
     808             :   * build a new ImageStore, whether SIImageStore or SIImageStoreMultiTerm, borrowing
     809             :   * image information from one partial image.
     810             :   *
     811             :   * @param imagename image name for the new SIStorageManager
     812             :   * @param part partial image from which miscinfo, etc. data will be borrowed
     813             :   * @param useweightimage useweight option for the new SIStorageManager
     814             :   *
     815             :   * @return A new SIImageStore object for the image name given.
     816             :   */
     817           0 :   std::shared_ptr<SIImageStore> SynthesisNormalizer::makeImageStore(const String &imagename,
     818             :                                                                const PagedImage<Float> &part,
     819             :                                                                Bool useweightimage)
     820             :   {
     821             :     // borrow shape, coord, imageinfo and miscinfo
     822           0 :     auto shape = part.shape();
     823           0 :     auto csys = part.coordinates();
     824           0 :     auto objectname = part.imageInfo().objectName();
     825           0 :     auto miscinfo = part.miscInfo();
     826           0 :     if (itsMapperType == "multiterm") {
     827             :       std::shared_ptr<SIImageStore> multiTermStore =
     828           0 :           std::make_shared<SIImageStoreMultiTerm>(
     829           0 :               imagename, csys, shape, objectname, miscinfo, itsNFacets, false,
     830           0 :               itsNTaylorTerms, useweightimage);
     831           0 :       return multiTermStore;
     832           0 :     } else {
     833             :       return std::make_shared<SIImageStore>(imagename, csys, shape, objectname,
     834           0 :                                             miscinfo, false, useweightimage);
     835             :     }
     836           0 :   }
     837             : 
     838             :   //
     839             :   //---------------------------------------------------------------
     840             :   //
     841           0 :    void SynthesisNormalizer::setPsfFromOneFacet()
     842             :    {
     843             :        // Copy the PSF from one facet to the center of the full image, to use for the minor cycle
     844             :     //
     845             :     // This code segment will work for single and multi-term 
     846             :     // - for single term, the index will always be 0, and SIImageStore's access functions know this.
     847             :     // - for multi-term, the index will be the taylor index and SIImageStoreMultiTerm knows this.
     848             : 
     849             :      /// itsImages
     850             :      /// itsFacetImageStores
     851             : 
     852             :       {
     853           0 :         IPosition shape=(itsImages->psf(0))->shape();
     854           0 :         IPosition blc(4, 0, 0, 0, 0);
     855           0 :         IPosition trc=shape-1;
     856           0 :         for(uInt tix=0; tix<2 * itsImages->getNTaylorTerms() - 1; tix++)
     857             :           {
     858           0 :             TempImage<Float> onepsf((itsFacetImageStores[0]->psf(tix))->shape(), 
     859           0 :                                     (itsFacetImageStores[0]->psf(tix))->coordinates());
     860           0 :             onepsf.copyData(*(itsFacetImageStores[0]->psf(tix)));
     861             :             //now set the original to 0 as we have a copy of one facet psf
     862           0 :             (itsImages->psf(tix))->set(0.0);
     863           0 :             blc[0]=(shape[0]-(onepsf.shape()[0]))/2;
     864           0 :             trc[0]=onepsf.shape()[0]+blc[0]-1;
     865           0 :             blc[1]=(shape[1]-(onepsf.shape()[1]))/2;
     866           0 :             trc[1]=onepsf.shape()[1]+blc[1]-1;
     867           0 :             Slicer sl(blc, trc, Slicer::endIsLast);
     868           0 :             SubImage<Float> sub(*(itsImages->psf(tix)), sl, true);
     869           0 :             sub.copyData(onepsf);
     870           0 :           }
     871           0 :       }
     872             : 
     873             :       //      cout << "In setPsfFromOneFacet : sumwt : " << itsImages->sumwt()->get() << endl;
     874             :   
     875           0 :    }
     876             : 
     877           0 :    void SynthesisNormalizer::mergeWeightDensityInfo(Record& outinfo, const Record& partinfo){
     878           0 :      uInt mapsize=0;
     879           0 :      if(outinfo.isDefined("multimapsize"))
     880           0 :       outinfo.get("multimapsize", mapsize);
     881             :      uInt partsize;
     882           0 :      if(!partinfo.isDefined("multimapsize"))
     883           0 :        return;
     884           0 :      partinfo.get("multimapsize", partsize);
     885           0 :      std::vector<String> key2add;
     886           0 :      std::vector<Int> val2add;
     887           0 :      for (uInt k = 0; k < partsize; ++k){
     888           0 :       String key;
     889           0 :       partinfo.get("key" + String::toString(k), key);
     890           0 :       Bool hasKey = False;
     891           0 :       for (uInt j = 0; j < mapsize; ++j) {
     892           0 :         String imkey;
     893           0 :         outinfo.get("key" + String::toString(j), imkey);
     894           0 :         hasKey = hasKey || (imkey == key);
     895           0 :       }  
     896           0 :       if (!hasKey) {
     897           0 :           key2add.push_back(key);
     898             :           Int val;
     899           0 :           partinfo.get("val" + String::toString(k), val);
     900           0 :           val2add.push_back(val);
     901             :         }
     902           0 :        }
     903           0 :      if (key2add.size() > 0) {
     904           0 :        for (uInt k = mapsize; k < (mapsize + key2add.size()); ++k) {
     905           0 :          String key = "key" + String::toString(k);
     906           0 :         outinfo.define(key, key2add[k - mapsize]);
     907           0 :         String val = "val" + String::toString(k);
     908           0 :         outinfo.define(val, val2add[k - mapsize]);
     909           0 :       }
     910           0 :       mapsize += key2add.size();
     911           0 :       outinfo.define("multimapsize", mapsize);
     912             :      }
     913           0 :    }
     914             : 
     915             : } //# NAMESPACE CASA - END
     916             : 

Generated by: LCOV version 1.16