LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - HogbomCleanImageSkyModel.cc (source / functions) Hit Total Coverage
Test: casa_coverage.info Lines: 0 225 0.0 %
Date: 2023-10-25 08:47:59 Functions: 0 4 0.0 %

          Line data    Source code
       1             : //# HogbomCleanImageSkyModel.cc: Implementation of HogbomCleanImageSkyModel class
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: aips2-request@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : 
      28             : #include <casacore/casa/Arrays/Cube.h>
      29             : #include <casacore/casa/Arrays/Matrix.h>
      30             : #include <casacore/casa/Arrays/ArrayMath.h>
      31             : #include <casacore/casa/Arrays/ArrayMath.h>
      32             : #include <casacore/casa/Arrays/ArrayPosIter.h>
      33             : #include <msvis/MSVis/StokesVector.h>
      34             : #include <synthesis/MeasurementComponents/HogbomCleanImageSkyModel.h>
      35             : #include <casacore/images/Images/PagedImage.h>
      36             : #include <casacore/casa/OS/File.h>
      37             : #include <casacore/lattices/Lattices/LatticeStepper.h>
      38             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      39             : #include <casacore/lattices/LEL/LatticeExpr.h>
      40             : #include <casacore/lattices/LEL/LatticeExprNode.h>
      41             : #include <synthesis/MeasurementEquations/SkyEquation.h>
      42             : #include <casacore/casa/Exceptions/Error.h>
      43             : #include <casacore/casa/BasicSL/String.h>
      44             : #include <casacore/casa/Utilities/Assert.h>
      45             : 
      46             : #include <sstream>
      47             : 
      48             : #include <casacore/casa/Logging/LogMessage.h>
      49             : #include <casacore/casa/Logging/LogSink.h>
      50             : 
      51             : #include <casacore/casa/System/Choice.h>
      52             : 
      53             : 
      54             : using namespace casacore;
      55             : namespace casa { //# NAMESPACE CASA - BEGIN
      56             : 
      57             : #define NEED_UNDERSCORES
      58             : #if defined(NEED_UNDERSCORES)
      59             : #define hclean hclean_
      60             : #endif
      61             : extern "C" {
      62             :   void hclean(Float*, Float*, Float*, int*, Float*, int*, int*, int*,
      63             :               int*, int*, int*, int*, int*, int*, int*, Float*, Float*,
      64             :               Float*, void *, void *);
      65             :    };
      66             : 
      67           0 : void HogbomCleanImageSkyModelstopnow (Int *yes) {
      68           0 :   Vector<String> choices(2);
      69           0 :   choices(0)="Continue";
      70           0 :   choices(1)="Stop Now";
      71           0 :   LogMessage message(LogOrigin("HogbomCleanImageSkyModel","solve"));
      72           0 :   LogSink logSink;
      73           0 :   *yes=0;
      74           0 :   return;
      75             :   String choice=Choice::choice("Clean iteration: do you want to continue or stop?", choices);
      76             :   if (choice==choices(0)) {
      77             :     *yes=0;
      78             :   }
      79             :   else {
      80             :     message.message("Stopping");
      81             :     logSink.post(message);
      82             :     *yes=1;
      83             :   }
      84             : }
      85             : 
      86           0 : void HogbomCleanImageSkyModelmsgput(Int *npol, Int* /*pol*/, Int* iter, Int* px, Int* py,
      87             :                                     Float* fMaxVal) {
      88           0 :   LogMessage message(LogOrigin("HogbomCleanImageSkyModel","solve"));
      89           0 :   ostringstream o; 
      90           0 :   LogSink logSink;
      91             :   /*
      92             :   String stokes("Unknown");
      93             :   ///UUU
      94             :   // This code allows only  I, IV, IQU, IQUV !!!!!
      95             :   if(*npol==1) {
      96             :     stokes="I";
      97             :   }
      98             :   else if(*npol==2) {
      99             :     if(*pol==1) {
     100             :       stokes="I";
     101             :     }
     102             :     else if(*pol==2) {
     103             :       stokes="V";
     104             :     }
     105             :   }
     106             :   else if(*npol==3) {
     107             :     if(*pol==1) {
     108             :       stokes="I";
     109             :     }
     110             :     else if(*pol==2) {
     111             :       stokes="Q";
     112             :     }
     113             :     else if(*pol==3) {
     114             :       stokes="U";
     115             :     }
     116             :   }
     117             :   else if(*npol==4) {
     118             :     if(*pol==1) {
     119             :       stokes="I";
     120             :     }
     121             :     else if(*pol==2) {
     122             :       stokes="Q";
     123             :     }
     124             :     else if(*pol==3) {
     125             :       stokes="U";
     126             :     }
     127             :     else if(*pol==4) {
     128             :       stokes="V";
     129             :     }
     130             :   }
     131             :   if(*pol==-1) {
     132             :     stokes="I";
     133             :   }
     134             :   else if(*pol==-2) {
     135             :     stokes="I,V";
     136             :   }
     137             :   else if(*pol==-3) {
     138             :     stokes="I,Q,U";
     139             :   }
     140             :   else if(*pol==-4) {
     141             :     stokes="I,Q,U,V";
     142             :   }
     143             :   */  
     144           0 :   if(*npol<0) {
     145           0 :     StokesVector maxVal(fMaxVal[0], fMaxVal[1], fMaxVal[2], fMaxVal[3]);
     146           0 :     if(*iter==0) {
     147             :       //      o<<stokes<<": Before iteration, peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     148           0 :       o<<"Before iteration, peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     149           0 :       message.message(o);
     150           0 :       logSink.post(message);
     151             :     }
     152           0 :     else if(*iter>-1) {
     153             :       //      o<<stokes<<": Iteration "<<*iter<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     154           0 :       o<<"Iteration "<<*iter<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     155           0 :       message.message(o);
     156           0 :       logSink.post(message);
     157             :     }
     158             :     else {
     159             :       //      o<<stokes<<": Final iteration "<<abs(*iter)<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     160           0 :       o<<"Final iteration "<<abs(*iter)<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     161           0 :       message.message(o);
     162           0 :       logSink.post(message);
     163             :     }
     164             :   }
     165             :   else {
     166           0 :     Float maxVal(fMaxVal[0]);
     167           0 :     if(*iter==0) {
     168             :       //      o<<stokes<<": Before iteration, peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     169           0 :       o<<"Before iteration, peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     170           0 :       message.message(o);
     171           0 :       logSink.post(message);
     172             :     }
     173           0 :     else if(*iter>-1) {
     174             :       //      o<<stokes<<": Iteration "<<*iter<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     175           0 :       o<<"Iteration "<<*iter<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     176           0 :       message.message(o);
     177           0 :       logSink.post(message);
     178             :     }
     179             :     else {
     180             :       //      o<<stokes<<": Final iteration "<<abs(*iter)<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     181           0 :       o<<"Final iteration "<<abs(*iter)<<" peak is "<<maxVal<<" at "<<*px-1<<","<<*py-1;
     182           0 :       message.message(o);
     183           0 :       logSink.post(message);
     184             :     }
     185             :   }
     186             :   
     187           0 : }
     188             : 
     189             : // Clean solver
     190           0 : Bool HogbomCleanImageSkyModel::solve(SkyEquation& se) {
     191             :   
     192           0 :   LogIO os(LogOrigin("HogbomCleanImageSkyModel","solve"));
     193             :   
     194           0 :   Bool converged=false;
     195           0 :   if(numberOfModels()>1) {
     196           0 :     os << "Cannot process more than one field" << LogIO::EXCEPTION;
     197             :   }
     198             :   
     199             :   // Make the residual image
     200           0 :   if(modified_p)
     201           0 :     makeNewtonRaphsonStep(se, false, (numberIterations()<1)?true:False);
     202             :   
     203             :   //Make the PSF
     204           0 :   if(!donePSF_p)
     205           0 :     makeApproxPSFs(se);
     206             : 
     207           0 :   if(numberIterations() < 1){
     208           0 :     return true;
     209             :   }
     210             :   
     211           0 :   if(!isSolveable(0)) {
     212           0 :     os << "Model 1 is not solveable!" << LogIO::EXCEPTION;
     213             :   }
     214             :   
     215             :   
     216             : 
     217           0 :   Int nx=image(0).shape()(0);
     218           0 :   Int ny=image(0).shape()(1);
     219           0 :   Int npol=image(0).shape()(2);
     220           0 :   Int nchan=image(0).shape()(3);
     221           0 :   Bool isCubeMask=false; 
     222           0 :   AlwaysAssert((npol==1)||(npol==2)||(npol==3)||(npol==4), AipsError);
     223             :   
     224             :   // Loop over all channels
     225           0 :   LatticeStepper psfls(PSF(0).shape(), IPosition(4,nx,ny,1,1),
     226           0 :                        IPosition(4,0,1,2,3));
     227           0 :   RO_LatticeIterator<Float> psfli(PSF(0),psfls);
     228             :   
     229             :   // Read the entire image for each spectral channel
     230           0 :   LatticeStepper ls(image(0).shape(),
     231           0 :                     IPosition(4, nx, ny, npol, 1),
     232           0 :                     IPosition(4, 0, 1, 2, 3));
     233           0 :   LatticeIterator<Float> imageStepli(residual(0), ls);
     234           0 :   LatticeIterator<Float> imageli(image(0), ls);
     235             :   
     236             :   // Now set up the mask.
     237           0 :   RO_LatticeIterator<Float>* maskli = 0;
     238           0 :   Matrix<Float>* lmask= new Matrix<Float>(1,1); 
     239           0 :   lmask->set(1.0);
     240             :   Int xbeg, xend;
     241             :   Int ybeg, yend;
     242           0 :   Int newNx=nx;
     243           0 :   Int newNy=ny;
     244             :   //default clean support
     245           0 :   xbeg=nx/4; 
     246           0 :   xend=3*nx/4-1;
     247           0 :   ybeg=ny/4; 
     248           0 :   yend=3*ny/4-1;
     249           0 :   Bool domask=true;
     250           0 :   if(hasMask(0)) {
     251           0 :     domask=true;
     252           0 :     AlwaysAssert(mask(0).shape()(0)==nx, AipsError);
     253           0 :     AlwaysAssert(mask(0).shape()(1)==ny, AipsError);
     254           0 :     if(nchan >1){
     255           0 :       if(mask(0).shape()(3)==nchan){
     256           0 :         isCubeMask=true;
     257           0 :         os << "Using multichannel mask" << LogIO::POST;
     258             :       }
     259             :       else{
     260             :         os << "Image cube and mask donot match in number of channels" 
     261           0 :            << LogIO::WARN;
     262             :         os << "Will use first plane of the mask for all channels" 
     263           0 :            << LogIO::WARN;
     264             :       }
     265             :     }
     266           0 :     LatticeStepper mls(mask(0).shape(),
     267           0 :                        IPosition(4, nx, ny, 1, 1),
     268           0 :                        IPosition(4, 0, 1, 2, 3));
     269           0 :     maskli= new RO_LatticeIterator<Float>(mask(0), mls);
     270           0 :     maskli->reset();
     271           0 :     lmask=makeMaskMatrix(nx, ny, newNx, newNy, *maskli, xbeg, 
     272             :                          xend, ybeg, yend); 
     273             :   }
     274             :   else {
     275           0 :     domask=false;
     276             :   }
     277             :   
     278             :   //Some variables if we change the image size
     279           0 :   IPosition newshp(4, newNx, newNy, npol,1);
     280           0 :   Array<Float> newData;
     281           0 :   Array<Float> newStep;
     282           0 :   Array<Float> newPsf;
     283             :   //------------------
     284             : 
     285           0 :   Float maxRes=0.0;
     286           0 :   Int iterUsed=0;
     287           0 :   Int chan=0;
     288           0 :   for (imageStepli.reset(),imageli.reset(),psfli.reset();
     289           0 :        !imageStepli.atEnd();
     290           0 :        imageStepli++,imageli++,psfli++,chan++) {
     291             :     //Deal with cube mask
     292           0 :     if(hasMask(0) && isCubeMask && chan >0) {
     293           0 :       (*maskli)++;
     294           0 :       if(lmask) delete lmask;
     295           0 :       lmask=0;
     296           0 :       lmask=makeMaskMatrix(nx, ny, newNx, newNy, *maskli, xbeg, 
     297             :                            xend, ybeg, yend);       
     298             :     }
     299             :     
     300             :     // Make IPositions and find position of peak of PSF
     301           0 :     IPosition psfposmax(psfli.cursor().ndim());
     302           0 :     IPosition psfposmin(psfli.cursor().ndim());
     303             :     Float psfmax;
     304             :     Float psfmin;
     305           0 :     minMax(psfmin, psfmax, psfposmin, psfposmax, psfli.cursor()); 
     306             :     
     307           0 :     if(nchan>1) {
     308           0 :       os<<"Processing channel "<<chan+1<<" of "<<nchan<<LogIO::POST;
     309             :     }
     310           0 :     if((psfmax==0.0) || (hasMask(0) && (lmask==0))) {
     311           0 :       os<<"No data or blank mask for this channel: skipping"<<LogIO::POST;
     312             :     }
     313             :     else {
     314             :       
     315             :       Bool delete_iti, delete_its, delete_itp, delete_itm;
     316             :       const Float *lpsf_data, *lmask_data;
     317             :       Float *limage_data, *limageStep_data;
     318           0 :       lmask_data=lmask->getStorage(delete_itm);
     319           0 :       if(newNx==nx){
     320           0 :         limage_data=imageli.rwCursor().getStorage(delete_iti);
     321           0 :         limageStep_data=imageStepli.rwCursor().getStorage(delete_its);
     322           0 :         lpsf_data=psfli.cursor().getStorage(delete_itp);
     323             :       }
     324             :       else{
     325           0 :         IPosition blc(4, (newNx-nx)/2, (newNy-ny)/2, 0,0);
     326           0 :         IPosition trc(4, (newNx+nx)/2-1, (newNy+ny)/2-1, npol-1,0);
     327           0 :         newshp(0)=newNx; 
     328           0 :         newshp(1)=newNy;
     329           0 :         newData.resize(newshp);
     330           0 :         newStep.resize(newshp);
     331             :         
     332           0 :         newData.set(0.0); newStep.set(0.0);
     333           0 :         newData(blc,trc).assign(imageli.rwCursor());
     334           0 :         newStep(blc,trc).assign(imageStepli.rwCursor());
     335             :         //psf we use first plane only of pol image
     336           0 :         newshp(2)=1;
     337           0 :         newPsf.resize(newshp);
     338           0 :         newPsf.set(0.0);
     339           0 :         trc(2)=0;
     340           0 :         newPsf(blc,trc).assign(psfli.cursor());
     341           0 :         limage_data=newData.getStorage(delete_iti);
     342           0 :         limageStep_data=newStep.getStorage(delete_its);
     343           0 :         lpsf_data=newPsf.getStorage(delete_itp);
     344             :       }
     345           0 :       Int niter=numberIterations();
     346           0 :       Float g=gain();
     347           0 :       Float thres=threshold();
     348             :       // Fortran indexes at 1
     349           0 :       Int fxbeg=xbeg+1;
     350           0 :       Int fxend=xend+1;
     351           0 :       Int fybeg=ybeg+1;
     352           0 :       Int fyend=yend+1;
     353             :       Int domaskI;
     354           0 :       if (domask) {
     355           0 :         domaskI = 1;
     356             :       } else {
     357           0 :         domaskI = 0;
     358             :       }
     359             :       
     360           0 :       Int starting_iteration = 0;  
     361           0 :       Int ending_iteration=0;         
     362             :       //# The const of lpsf and mask has to be cast away for the
     363             :       //# fortran function hclean.
     364           0 :       Float cycleSpeedup = -1; // ie, ignore it
     365           0 :       hclean(limage_data, limageStep_data,
     366             :              (Float*)lpsf_data, &domaskI, (Float*)lmask_data,
     367             :              &newNx, &newNy, &npol,
     368             :              &fxbeg, &fxend, &fybeg, &fyend, &niter,
     369             :              &starting_iteration, &ending_iteration,
     370             :              &g, &thres, &cycleSpeedup,
     371             :              (void*) &HogbomCleanImageSkyModelmsgput,
     372             :              (void*) &HogbomCleanImageSkyModelstopnow);
     373             : 
     374           0 :       iterUsed=max(iterUsed, ending_iteration);
     375           0 :       if(nx==newNx){
     376           0 :         imageli.rwCursor().putStorage (limage_data, delete_iti);
     377           0 :         imageStepli.rwCursor().putStorage (limageStep_data, delete_its);
     378           0 :         psfli.cursor().freeStorage (lpsf_data, delete_itp);
     379             :       }
     380             :       else{
     381           0 :         IPosition blc(4, (newNx-nx)/2, (newNy-ny)/2, 0,0);
     382           0 :         IPosition trc(4, (newNx+nx)/2-1, (newNy+ny)/2-1, npol-1,0);
     383           0 :         newData.putStorage(limage_data, delete_iti);
     384           0 :         newStep.putStorage(limageStep_data, delete_its);
     385           0 :         newPsf.freeStorage(lpsf_data, delete_itp);
     386           0 :         imageli.rwCursor().assign(newData(blc,trc));
     387           0 :         imageStepli.rwCursor().assign(newStep(blc,trc));
     388             :       }
     389           0 :       lmask->freeStorage (lmask_data, delete_itm);
     390             :       Float residualmax, residualmin;
     391           0 :       minMax(residualmin, residualmax, imageStepli.cursor());
     392           0 :       residualmax=max(residualmax, abs(residualmin));
     393           0 :       maxRes=max(maxRes, residualmax);
     394             :       
     395           0 :       converged = (residualmax < threshold());
     396             :     }
     397           0 :     if (lmask != 0 && isCubeMask)  {
     398           0 :       lmask->resize(1,1);
     399             :     }
     400             : 
     401             :   }
     402           0 :    os << LatticeExprNode(sum(image(0))).getFloat() 
     403           0 :                << " Jy is the sum of clean components " << LogIO::POST;
     404           0 :   modified_p=true;
     405           0 :   setThreshold(maxRes);
     406           0 :   setNumberIterations(iterUsed);
     407           0 :   if (maskli != 0) {
     408           0 :     delete maskli;
     409           0 :     maskli = 0;
     410             :   }
     411           0 :   return(converged);
     412             : };
     413             : 
     414           0 : Matrix<Float>* HogbomCleanImageSkyModel::makeMaskMatrix(const Int& nx, 
     415             :                                                        const Int& ny,
     416             :                                                         Int& newNx, Int& newNy,
     417             :                                                         RO_LatticeIterator<Float>& maskIter,
     418             :                                                         Int& xbeg,
     419             :                                                         Int& xend,
     420             :                                                         Int& ybeg,
     421             :                                                         Int& yend) {
     422             : 
     423           0 :   LogIO os(LogOrigin("HogbomCleanImageSkyModel","makeMaskMatrix",WHERE)); 
     424             : 
     425             : 
     426           0 :   newNx=nx;
     427           0 :   newNy=ny;
     428           0 :   xbeg=nx/4;
     429           0 :   ybeg=ny/4;
     430             :   
     431           0 :   xend=xbeg+nx/2-1;
     432           0 :   yend=ybeg+ny/2-1;  
     433           0 :   Matrix<Float>* mask= new Matrix<Float>(maskIter.matrixCursor().shape());
     434           0 :   (*mask)=maskIter.matrixCursor();
     435             :   // ignore mask if none exists
     436           0 :   if(max(*mask) < 0.000001) {
     437             :     //os << "Mask seems to be empty; will CLEAN inner quarter" 
     438             :     //   << LogIO::WARN;
     439             :     //mask->resize(1,1);
     440             :     //mask->set(1.0);
     441           0 :     delete mask;
     442           0 :     mask=0;
     443           0 :     return mask;
     444             :   }
     445             :   // Now read the mask and determine the bounding box
     446           0 :   xbeg=nx-1;
     447           0 :   ybeg=ny-1;
     448           0 :   xend=0;
     449           0 :   yend=0;
     450             : 
     451           0 :   for (Int iy=0;iy<ny;iy++) {
     452           0 :     for (Int ix=0;ix<nx;ix++) {
     453           0 :       if((*mask)(ix,iy)>0.000001) {
     454           0 :         xbeg=min(xbeg,ix);
     455           0 :         ybeg=min(ybeg,iy);
     456           0 :         xend=max(xend,ix);
     457           0 :         yend=max(yend,iy);
     458             : 
     459             :       }
     460             :     }
     461             :   }
     462             :   // Now have possible BLC. Make sure that we don't go over the
     463             :   // edge later
     464           0 :   Bool larger_quarter=false;
     465           0 :   if((xend - xbeg)>nx/2) {
     466             :     //xbeg=nx/4-1; //if larger than quarter take inner of mask
     467             :     //os << LogIO::WARN << "Mask span over more than half the x-axis: Considering inner half of the x-axis"  << LogIO::POST;
     468           0 :     larger_quarter=true;
     469             :   } 
     470           0 :   if((yend - ybeg)>ny/2) { 
     471             :     //ybeg=ny/4-1;
     472             :     //os << LogIO::WARN << "Mask span over more than half the y-axis: Considering inner half of the y-axis" << LogIO::POST;
     473           0 :     larger_quarter=true;
     474             :   }  
     475           0 :   if(larger_quarter){
     476           0 :     newNx=2*nx;
     477           0 :     newNy=2*ny;
     478           0 :     Matrix<Float> * newMask= new Matrix<Float>(newNx, newNy);
     479           0 :     newMask->set(0.0);
     480           0 :     IPosition blc(2, (newNx-nx)/2, (newNy-ny)/2);
     481           0 :     IPosition trc(2, (newNx+nx)/2-1, (newNy+ny)/2-1);
     482           0 :     ((*newMask)(blc,trc)).assign(*mask);
     483           0 :     delete mask;
     484           0 :     mask=newMask;
     485           0 :     xbeg=xbeg+(newNx-nx)/2;
     486           0 :     ybeg=ybeg+(newNy-ny)/2;
     487           0 :     xend=xend+(newNx-nx)/2;
     488           0 :     yend=yend+(newNy-ny)/2;
     489             :   }
     490             :   
     491           0 :   xend=min(xend,xbeg+newNx/2-1);
     492           0 :   yend=min(yend,ybeg+newNy/2-1);   
     493             :   
     494             : 
     495           0 :   return mask;
     496             : }
     497             : 
     498             : 
     499             : } //# NAMESPACE CASA - END
     500             : 

Generated by: LCOV version 1.16