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 :
|