Line data Source code
1 : //# SIImageStoreMultiTerm.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 :
42 : #include <casacore/casa/OS/DirectoryIterator.h>
43 : #include <casacore/casa/OS/File.h>
44 : #include <casacore/casa/OS/Path.h>
45 :
46 : #include <casacore/casa/OS/HostInfo.h>
47 : #include <casacore/images/Images/TempImage.h>
48 : #include <casacore/images/Images/PagedImage.h>
49 : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
50 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
51 : #include <synthesis/TransformMachines/StokesImageUtil.h>
52 : #include <casacore/images/Images/TempImage.h>
53 : #include <casacore/images/Images/SubImage.h>
54 : #include <casacore/images/Regions/ImageRegion.h>
55 :
56 : #include <synthesis/ImagerObjects/SIImageStoreMultiTerm.h>
57 :
58 : #include <casacore/casa/Arrays/MatrixMath.h>
59 : #include <casacore/scimath/Mathematics/MatrixMathLA.h>
60 :
61 : #include <sys/types.h>
62 : #include <unistd.h>
63 : using namespace std;
64 :
65 : using namespace casacore;
66 : namespace casa { //# NAMESPACE CASA - BEGIN
67 :
68 : //////////////////////////////////////////////////////////////////////////////////////////////////////
69 : //////////////////////////////////////////////////////////////////////////////////////////////////////
70 :
71 0 : SIImageStoreMultiTerm::SIImageStoreMultiTerm():SIImageStore()
72 : {
73 0 : itsNTerms=0;
74 :
75 0 : itsPsfs.resize(0);
76 0 : itsModels.resize(0);
77 0 : itsResiduals.resize(0);
78 0 : itsWeights.resize(0);
79 0 : itsImages.resize(0);
80 0 : itsSumWts.resize(0);
81 0 : itsImagePBcors.resize(0);
82 0 : itsPBs.resize(0);
83 :
84 0 : itsForwardGrids.resize(0);
85 0 : itsBackwardGrids.resize(0);
86 :
87 0 : itsUseWeight=false;
88 :
89 0 : init();
90 :
91 0 : validate();
92 :
93 0 : }
94 :
95 : // Used from SynthesisNormalizer::makeImageStore()
96 116 : SIImageStoreMultiTerm::SIImageStoreMultiTerm(const String &imagename,
97 : const CoordinateSystem &imcoordsys,
98 : const IPosition &imshape,
99 : const String &objectname,
100 : const Record &miscinfo,
101 : const Int /*nfacets*/,
102 : const Bool /*overwrite*/,
103 : uInt ntaylorterms,
104 116 : Bool useweightimage)
105 : {
106 232 : LogIO os( LogOrigin("SIImageStoreMultiTerm","Open new Images",WHERE) );
107 :
108 116 : itsNTerms = ntaylorterms;
109 :
110 116 : itsPsfs.resize(2 * itsNTerms - 1);
111 116 : itsModels.resize(itsNTerms);
112 116 : itsResiduals.resize(itsNTerms);
113 116 : itsWeights.resize(2 * itsNTerms - 1);
114 116 : itsImages.resize(itsNTerms);
115 116 : itsSumWts.resize(2 * itsNTerms - 1);
116 116 : itsPBs.resize(itsNTerms);
117 116 : itsImagePBcors.resize(itsNTerms);
118 :
119 116 : itsMask.reset( );
120 116 : itsGridWt.reset( );
121 :
122 116 : itsForwardGrids.resize(itsNTerms);
123 116 : itsBackwardGrids.resize(2 * itsNTerms - 1);
124 :
125 : // itsNFacets = nfacets; // So that sumwt shape happens properly, via checkValidity
126 : // itsFacetId = -1;
127 116 : itsNFacets=1;
128 116 : itsFacetId=0;
129 116 : itsNChanChunks = 1;
130 116 : itsChanId = 0;
131 116 : itsNPolChunks = 1;
132 116 : itsPolId = 0;
133 :
134 116 : itsImageName = imagename;
135 116 : itsCoordSys = imcoordsys;
136 116 : itsImageShape = imshape;
137 116 : itsObjectName = objectname;
138 116 : itsMiscInfo = miscinfo;
139 :
140 116 : itsUseWeight = useweightimage;
141 :
142 116 : init();
143 :
144 116 : validate();
145 :
146 116 : }
147 :
148 : // Used from SynthesisNormalizer::makeImageStore()
149 708 : SIImageStoreMultiTerm::SIImageStoreMultiTerm(const String &imagename, uInt ntaylorterms,
150 708 : const Bool ignorefacets, const Bool ignoresumwt)
151 : {
152 1416 : LogIO os( LogOrigin("SIImageStoreMultiTerm","Open existing Images",WHERE) );
153 :
154 708 : itsNTerms = ntaylorterms;
155 :
156 18566 : auto fltPtrReset = [](Block<shared_ptr<ImageInterface<Float> > >&a) {for(uInt i=0; i < a.nelements(); ++i) a[i].reset(); };
157 708 : itsPsfs.resize(2 * itsNTerms - 1); fltPtrReset(itsPsfs);
158 708 : itsModels.resize(itsNTerms); fltPtrReset(itsModels);
159 708 : itsResiduals.resize(itsNTerms); fltPtrReset(itsResiduals);
160 708 : itsWeights.resize(2 * itsNTerms - 1); fltPtrReset(itsWeights);
161 708 : itsImages.resize(itsNTerms); fltPtrReset(itsImages);
162 708 : itsPBs.resize(itsNTerms); fltPtrReset(itsPBs);
163 708 : itsSumWts.resize(2 * itsNTerms - 1); fltPtrReset(itsSumWts);
164 708 : itsMask.reset( );
165 708 : itsGridWt.reset( );
166 708 : itsImagePBcors.resize(itsNTerms); fltPtrReset(itsImagePBcors);
167 :
168 :
169 :
170 708 : itsMiscInfo=Record();
171 4806 : auto cmplxPtrReset = [](Block<shared_ptr<ImageInterface<Complex> > >&a) {for(uInt i=0; i < a.nelements(); ++i) a[i].reset(); };
172 708 : itsForwardGrids.resize(itsNTerms); cmplxPtrReset(itsForwardGrids);
173 708 : itsBackwardGrids.resize(2 * itsNTerms - 1); cmplxPtrReset(itsBackwardGrids);
174 :
175 708 : itsImageName = imagename;
176 :
177 708 : itsNFacets=1;
178 708 : itsFacetId=0;
179 708 : itsNChanChunks = 1;
180 708 : itsChanId = 0;
181 708 : itsNPolChunks = 1;
182 708 : itsPolId = 0;
183 :
184 708 : Bool exists=true;
185 708 : Bool sumwtexists=true;
186 708 : Bool modelexists=true;
187 2732 : for(uInt tix=0;tix<2*itsNTerms-1;tix++)
188 : {
189 2024 : if( tix<itsNTerms ) {
190 3268 : exists &= ( doesImageExist( itsImageName+String(".residual.tt")+String::toString(tix) ) ||
191 1902 : doesImageExist( itsImageName+String(".psf.tt")+String::toString(tix) ) );
192 3396 : modelexists &= ( doesImageExist( itsImageName+String(".model.tt")+String::toString(tix) ) ||
193 2030 : doesImageExist( itsImageName+String(".model.tt")+String::toString(tix) ) );
194 1366 : sumwtexists &= ( doesImageExist( itsImageName+String(".sumwt.tt")+String::toString(tix) ) );
195 : }else {
196 658 : exists &= ( doesImageExist( itsImageName+String(".psf.tt")+String::toString(tix) ) );
197 658 : sumwtexists &= ( doesImageExist( itsImageName+String(".sumwt.tt")+String::toString(tix) ) );
198 : }
199 : }
200 :
201 : // The PSF or Residual images must exist. ( or the gridwt image)
202 : // All this is just for the shape and coordinate system.
203 708 : if( exists || modelexists || doesImageExist(itsImageName+String(".gridwt")) )
204 : {
205 708 : std::shared_ptr<ImageInterface<Float> > imptr;
206 708 : if( doesImageExist(itsImageName+String(".psf.tt0")) )
207 : {
208 708 : buildImage( imptr, (itsImageName+String(".psf.tt0")) );
209 :
210 : //cout << "Opening PSF image to read csys" << endl;
211 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".psf.tt0")) );
212 : }
213 0 : else if( doesImageExist(itsImageName+String(".residual.tt0")) )
214 : {
215 0 : buildImage( imptr, (itsImageName+String(".residual.tt0")) );
216 : //cout << "Opening Residual image to read csys" << endl;
217 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".residual.tt0")) );
218 : }
219 0 : else if( doesImageExist(itsImageName+String(".model.tt0")) )
220 : {
221 0 : buildImage( imptr, (itsImageName+String(".model.tt0")) );
222 : //cout << "Opening Model image to read csys" << endl;
223 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".model.tt0")) );
224 : }
225 : else
226 : {
227 : // How can this be right ?
228 : //cout << "Opening Sumwt image to read csys" << endl;
229 0 : buildImage( imptr, (itsImageName+String(".gridwt")) );
230 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".gridwt")) );
231 : }
232 :
233 708 : itsObjectName=imptr->imageInfo().objectName();
234 708 : itsImageShape = imptr->shape();
235 708 : itsCoordSys = imptr->coordinates();
236 708 : itsMiscInfo=imptr->miscInfo();
237 :
238 708 : }
239 : else
240 : {
241 0 : throw( AipsError( "Multi-term PSF, Residual or Model Images do not exist. Please create one of them." ) );
242 : }
243 :
244 1691 : if( doesImageExist(itsImageName+String(".residual.tt0")) ||
245 983 : doesImageExist(itsImageName+String(".psf.tt0")) )
246 : {
247 708 : if( sumwtexists )
248 : {
249 679 : std::shared_ptr<ImageInterface<Float> > imptr;
250 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".sumwt.tt0")) );
251 679 : buildImage( imptr, (itsImageName+String(".sumwt.tt0")) );
252 679 : itsNFacets = imptr->shape()[0];
253 679 : itsFacetId = 0;
254 679 : itsUseWeight = getUseWeightImage( *imptr );
255 : /////redo this here as psf may have different coordinates
256 679 : itsCoordSys = imptr->coordinates();
257 679 : itsMiscInfo=imptr->miscInfo();
258 679 : if(!ignoresumwt)
259 : {
260 454 : if( itsUseWeight && ! doesImageExist(itsImageName+String(".weight.tt0")) )
261 : {
262 0 : throw(AipsError("Internal error : MultiTerm Sumwt has a useweightimage=true but the weight image does not exist."));
263 : }
264 : }
265 679 : }
266 : else
267 : {
268 29 : if(!ignoresumwt)
269 0 : {throw( AipsError( "Multi-term SumWt does not exist. Please create PSFs or Residuals." ) );}
270 : else
271 : {
272 29 : os << "SumWt.ttx do not exist. Proceeding only with PSFs" << LogIO::POST;
273 29 : std::shared_ptr<ImageInterface<Float> > imptr;
274 : // imptr.reset( new PagedImage<Float> (itsImageName+String(".sumwt.tt0")) );
275 29 : if( doesImageExist(itsImageName+String(".residual.tt0")) )
276 29 : {buildImage( imptr, (itsImageName+String(".residual.tt0")) );}
277 : else
278 0 : {buildImage( imptr, (itsImageName+String(".psf.tt0")) );}
279 :
280 29 : itsNFacets = 1;
281 29 : itsFacetId = 0;
282 29 : itsUseWeight = False;
283 29 : itsCoordSys = imptr->coordinates();
284 29 : itsMiscInfo=imptr->miscInfo();
285 29 : }
286 : }
287 : }// if psf0 or res0 exist
288 :
289 708 : if( ignorefacets==true ) itsNFacets=1;
290 :
291 708 : init();
292 708 : validate();
293 :
294 708 : }
295 :
296 : /*
297 : /////////////Constructor with pointers already created else where but taken over here
298 : SIImageStoreMultiTerm::SIImageStoreMultiTerm(Block<std::shared_ptr<ImageInterface<Float> > > modelims,
299 : Block<std::shared_ptr<ImageInterface<Float> > >residims,
300 : Block<std::shared_ptr<ImageInterface<Float> > >psfims,
301 : Block<std::shared_ptr<ImageInterface<Float> > >weightims,
302 : Block<std::shared_ptr<ImageInterface<Float> > >restoredims,
303 : Block<std::shared_ptr<ImageInterface<Float> > >sumwtims,
304 : std::shared_ptr<ImageInterface<Float> > newmask,
305 : std::shared_ptr<ImageInterface<Float> > newalpha,
306 : std::shared_ptr<ImageInterface<Float> > newbeta)
307 : {
308 :
309 : itsPsfs=psfims;
310 : itsModels=modelims;
311 : itsResiduals=residims;
312 : itsWeights=weightims;
313 : itsImages=restoredims;
314 : itsSumWts=sumwtims;
315 : itsMask = newmask;
316 : itsAlpha = newalpha;
317 : itsBeta = newbeta;
318 :
319 : itsNTerms = itsResiduals.nelements();
320 : itsMiscInfo=Record();
321 :
322 : AlwaysAssert( itsPsfs.nelements() == 2*itsNTerms-1 , AipsError );
323 : AlwaysAssert( itsPsfs.nelements()>0 && itsPsfs[0] , AipsError );
324 : AlwaysAssert( itsSumWts.nelements()>0 && itsSumWts[0] , AipsError );
325 :
326 : itsForwardGrids.resize( itsNTerms );
327 : itsBackwardGrids.resize( 2 * itsNTerms - 1 );
328 :
329 : itsImageShape=psfims[0]->shape();
330 : itsCoordSys = psfims[0]->coordinates();
331 : itsMiscInfo = psfims[0]->miscInfo();
332 :
333 : itsNFacets=sumwtims[0]->shape()[0];
334 : itsUseWeight=getUseWeightImage( *(sumwtims[0]) );
335 :
336 : itsImageName = String("reference"); // This is what the access functions use to guard against allocs...
337 :
338 : init();
339 : validate();
340 :
341 : }
342 : */
343 :
344 : //////////////////////////////////////////////////////////////////////////////////////////////////////
345 : /////////////Constructor with pointers already created else where but taken over here
346 : // used from getSubImageStore(), for example when creating the facets list
347 : // this would be safer if it was refactored as a copy constructor of the generic stuff +
348 : // initialization of the facet related parameters
349 307 : SIImageStoreMultiTerm::SIImageStoreMultiTerm(const Block<std::shared_ptr<ImageInterface<Float> > > &modelims,
350 : const Block<std::shared_ptr<ImageInterface<Float> > > &residims,
351 : const Block<std::shared_ptr<ImageInterface<Float> > > &psfims,
352 : const Block<std::shared_ptr<ImageInterface<Float> > > &weightims,
353 : const Block<std::shared_ptr<ImageInterface<Float> > > &restoredims,
354 : const Block<std::shared_ptr<ImageInterface<Float> > > &sumwtims,
355 : const Block<std::shared_ptr<ImageInterface<Float> > > &pbims,
356 : const Block<std::shared_ptr<ImageInterface<Float> > > &restoredpbcorims,
357 : const std::shared_ptr<ImageInterface<Float> > &newmask,
358 : const std::shared_ptr<ImageInterface<Float> > &newalpha,
359 : const std::shared_ptr<ImageInterface<Float> > &newbeta,
360 : const std::shared_ptr<ImageInterface<Float> > &newalphaerror,
361 : const std::shared_ptr<ImageInterface<Float> > &newalphapbcor,
362 : const std::shared_ptr<ImageInterface<Float> > &newbetapbcor,
363 : const CoordinateSystem& csys,
364 : const IPosition &imshape,
365 : const String &imagename,
366 : const String &objectname,
367 : const Record &miscinfo,
368 : const Int facet, const Int nfacets,
369 : const Int chan, const Int nchanchunks,
370 307 : const Int pol, const Int npolchunks)
371 : {
372 307 : itsPsfs=psfims;
373 307 : itsModels=modelims;
374 307 : itsResiduals=residims;
375 307 : itsWeights=weightims;
376 307 : itsImages=restoredims;
377 307 : itsSumWts=sumwtims;
378 307 : itsMask = newmask;
379 307 : itsAlpha = newalpha;
380 307 : itsBeta = newbeta;
381 307 : itsAlphaError = newalphaerror;
382 307 : itsAlphaPBcor = newalphapbcor;
383 307 : itsBetaPBcor = newbetapbcor;
384 :
385 307 : itsPBs=pbims;
386 307 : itsImagePBcors=restoredpbcorims;
387 :
388 307 : itsNTerms = itsResiduals.nelements();
389 307 : itsMiscInfo=Record();
390 :
391 307 : AlwaysAssert( itsPsfs.nelements() == 2*itsNTerms-1 , AipsError );
392 : // AlwaysAssert( itsPsfs.nelements()>0 && itsPsfs[0] , AipsError );
393 : // AlwaysAssert( itsSumWts.nelements()>0 && itsSumWts[0] , AipsError );
394 :
395 307 : itsForwardGrids.resize( itsNTerms );
396 307 : itsBackwardGrids.resize( 2 * itsNTerms - 1 );
397 :
398 307 : itsObjectName = objectname;
399 307 : itsMiscInfo = miscinfo;
400 :
401 307 : itsNFacets = nfacets;
402 307 : itsFacetId = facet;
403 307 : itsNChanChunks = nchanchunks;
404 307 : itsChanId = chan;
405 307 : itsNPolChunks = npolchunks;
406 307 : itsPolId = pol;
407 :
408 307 : itsParentImageShape = imshape;
409 307 : itsImageShape = imshape;
410 : ///// itsImageShape = IPosition(4,0,0,0,0);
411 :
412 307 : itsCoordSys = csys; // Hopefully this doesn't change for a reference image
413 307 : itsImageName = imagename;
414 :
415 :
416 : //-----------------------
417 307 : init(); // Connect parent pointers to the images.
418 : //-----------------------
419 :
420 : // Set these to null, to be set later upon first access.
421 : // Setting to null will hopefully set all elements of each array, to NULL.
422 307 : itsPsfs=std::shared_ptr<ImageInterface<Float> >();
423 307 : itsModels=std::shared_ptr<ImageInterface<Float> >();
424 307 : itsResiduals=std::shared_ptr<ImageInterface<Float> >();
425 307 : itsWeights=std::shared_ptr<ImageInterface<Float> >();
426 307 : itsImages=std::shared_ptr<ImageInterface<Float> >();
427 307 : itsSumWts=std::shared_ptr<ImageInterface<Float> >();
428 307 : itsPBs=std::shared_ptr<ImageInterface<Float> >();
429 :
430 307 : itsMask.reset( );
431 :
432 307 : validate();
433 :
434 307 : }
435 :
436 : //////////////////////////////////////////////////////////////////////////////////////////////////////
437 :
438 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
439 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
440 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
441 :
442 217 : uInt SIImageStoreMultiTerm::getNTaylorTerms(Bool dopsf)
443 : {
444 217 : return dopsf ? (2*itsNTerms-1) : itsNTerms;
445 : }
446 :
447 : // Check if images that are asked-for are ready and all have the same shape.
448 : /*
449 : Bool SIImageStoreMultiTerm::checkValidity(const Bool ipsf, const Bool iresidual,
450 : const Bool iweight, const Bool imodel, const Bool irestored,
451 : const Bool imask,const Bool isumwt,
452 : const Bool ialpha, const Bool ibeta)
453 : {
454 :
455 : // cout << "In MT::checkValidity imask is " << imask << endl;
456 :
457 : Bool valid = true;
458 :
459 : for(uInt tix=0; tix<2*itsNTerms-1; tix++)
460 : {
461 :
462 : if(ipsf==true)
463 : { psf(tix);
464 : valid = valid & ( itsPsfs[tix] && itsPsfs[tix]->shape()==itsImageShape ); }
465 : if(iweight==true)
466 : { weight(tix);
467 : valid = valid & ( itsWeights[tix] && itsWeights[tix]->shape()==itsImageShape ); }
468 :
469 : if(isumwt==true) {
470 : IPosition useShape(itsImageShape);
471 : useShape[0]=itsNFacets; useShape[1]=itsNFacets;
472 : sumwt(tix);
473 : valid = valid & ( itsSumWts[tix] && itsSumWts[tix]->shape()==useShape );
474 : }
475 :
476 : if( tix< itsNTerms )
477 : {
478 : if(iresidual==true)
479 : { residual(tix);
480 : valid = valid & ( itsResiduals[tix] && itsResiduals[tix]->shape()==itsImageShape ); }
481 : if(imodel==true)
482 : { model(tix);
483 : valid = valid & ( itsModels[tix] && itsModels[tix]->shape()==itsImageShape); }
484 : if(irestored==true)
485 : { image(tix);
486 : valid = valid & ( itsImages[tix] && itsImages[tix]->shape()==itsImageShape); }
487 : }
488 : }
489 :
490 : if(imask==true)
491 : { mask(); valid = valid & ( itsMask && itsMask->shape()==itsImageShape);
492 : // cout << " Mask null ? " << (bool) itsMask << endl;
493 : }
494 : if(ialpha==true)
495 : { alpha(); valid = valid & ( itsAlpha && itsAlpha->shape()==itsImageShape ); }
496 : if(ibeta==true)
497 : { beta(); valid = valid & ( itsBeta && itsBeta->shape()==itsImageShape ); }
498 :
499 : return valid;
500 :
501 : }
502 : */
503 :
504 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
505 : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
506 : //////////////////////////////////////////////////////////////////////////////////////////////////////
507 : //////////////////////////////////////////////////////////////////////////////////////////////////////
508 :
509 1839 : SIImageStoreMultiTerm::~SIImageStoreMultiTerm()
510 : {
511 1839 : }
512 :
513 : //////////////////////////////////////////////////////////////////////////////////////////////////////
514 : //////////////////////////////////////////////////////////////////////////////////////////////////////
515 :
516 2172 : Bool SIImageStoreMultiTerm::releaseLocks()
517 : {
518 4344 : LogIO os( LogOrigin("SIImageStoreMultiTerm","releaseLocks",WHERE) );
519 :
520 8574 : for(uInt tix=0; tix<2*itsNTerms-1; tix++)
521 : {
522 6402 : if( itsPsfs[tix] ) releaseImage( itsPsfs[tix] );
523 6402 : if( itsWeights[tix] ) releaseImage( itsWeights[tix] );
524 6402 : if( itsSumWts[tix] ) releaseImage( itsSumWts[tix] );
525 6402 : if( tix < itsNTerms )
526 : {
527 4287 : if( itsModels[tix] ) releaseImage( itsModels[tix] );
528 4287 : if( itsResiduals[tix] ) releaseImage( itsResiduals[tix] );
529 4287 : if( itsImages[tix] ) releaseImage( itsImages[tix] );
530 4287 : if( itsPBs[tix] ) releaseImage( itsPBs[tix] );
531 4287 : if( itsImagePBcors[tix] ) releaseImage( itsImagePBcors[tix] );
532 : }
533 : }
534 2172 : if( itsMask ) releaseImage( itsMask );
535 2172 : if( itsAlpha ) releaseImage( itsAlpha );
536 2172 : if( itsBeta ) releaseImage( itsBeta );
537 2172 : if( itsAlphaError ) releaseImage( itsAlphaError );
538 2172 : if( itsAlphaPBcor ) releaseImage( itsAlphaPBcor );
539 2172 : if( itsBetaPBcor ) releaseImage( itsBetaPBcor );
540 2172 : if( itsGridWt ) releaseImage( itsGridWt );
541 :
542 2172 : return true; // do something more intelligent here.
543 2172 : }
544 :
545 0 : Bool SIImageStoreMultiTerm::releaseComplexGrids()
546 : {
547 0 : LogIO os( LogOrigin("SIImageStoreMultiTerm","releaseComplexGrids",WHERE) );
548 :
549 0 : for(uInt tix=0; tix<2*itsNTerms-1; tix++)
550 : {
551 0 : if( itsBackwardGrids[tix] ) releaseImage( itsBackwardGrids[tix] );
552 0 : if( tix < itsNTerms )
553 : {
554 0 : if( itsForwardGrids[tix] ) releaseImage( itsForwardGrids[tix] );
555 : }
556 : }
557 0 : return True; // do something more intelligent here.
558 0 : }
559 :
560 :
561 610 : Double SIImageStoreMultiTerm::getReferenceFrequency()
562 : {
563 : Double theRefFreq;
564 :
565 610 : Vector<Double> refpix = (itsCoordSys.spectralCoordinate()).referencePixel();
566 610 : AlwaysAssert( refpix.nelements()>0, AipsError );
567 610 : (itsCoordSys.spectralCoordinate()).toWorld( theRefFreq, refpix[0] );
568 : // cout << "Reading ref freq as : " << theRefFreq << endl;
569 610 : return theRefFreq;
570 610 : }
571 :
572 : //////////////////////////////////////////////////////////////////////////////////////////////////////
573 : //////////////////////////////////////////////////////////////////////////////////////////////////////
574 0 : Vector<String> SIImageStoreMultiTerm::getModelImageName()
575 : {
576 0 : Vector<String> mods(itsNTerms);
577 0 : for(uInt tix=0;tix<itsNTerms;tix++)
578 0 : {mods[tix]=itsImageName + imageExts(MODEL)+".tt"+String::toString(tix);}
579 0 : return mods;
580 0 : }
581 :
582 12 : void SIImageStoreMultiTerm::setModelImage( const Vector<String> &modelnames )
583 : {
584 24 : LogIO os( LogOrigin("SIImageStoreMultiTerm","setModelImage",WHERE) );
585 :
586 12 : if( modelnames.nelements() > itsNTerms )
587 0 : { throw(AipsError("We currently cannot support more than nterms images as the starting model. "));
588 : }
589 :
590 12 : if( modelnames.nelements() > 0 && modelnames.nelements() <= itsNTerms )
591 : {
592 30 : for(uInt tix=0;tix<modelnames.nelements();tix++)
593 : {
594 19 : setModelImageOne( modelnames[tix], tix );
595 : }
596 : }
597 :
598 12 : }
599 :
600 : /*
601 : void SIImageStoreMultiTerm::setModelImage( String modelname )
602 : {
603 : LogIO os( LogOrigin("SIImageStoreMultiTerm","setModelImage",WHERE) );
604 :
605 : for(uInt tix=0;tix<itsNTerms;tix++)
606 : {
607 :
608 : Directory immodel( modelname+String(".model.tt")+String::toString(tix) );
609 : if( !immodel.exists() )
610 : {
611 : os << "Starting model image does not exist for term : " << tix << LogIO::POST;
612 : }
613 : else
614 : {
615 : std::shared_ptr<PagedImage<Float> > newmodel( new PagedImage<Float>( modelname+String(".model.tt")+String::toString(tix) ) );
616 : // Check shapes, coordsys with those of other images. If different, try to re-grid here.
617 :
618 : if( newmodel->shape() != model(tix)->shape() )
619 : {
620 : os << "Regridding input model to target coordinate system for term " << tix << LogIO::POST;
621 : regridToModelImage( *newmodel , tix);
622 : // For now, throw an exception.
623 : //throw( AipsError( "Input model image "+modelname+".model.tt"+String::toString(tix)+" is not the same shape as that defined for output in "+ itsImageName + ".model" ) );
624 : }
625 : else
626 : {
627 : os << "Setting " << modelname << " as model for term " << tix << LogIO::POST;
628 : // Then, add its contents to itsModel.
629 : //itsModel->put( itsModel->get() + model->get() );
630 : /////( model(tix) )->put( newmodel->get() );
631 : model(tix)->copyData( LatticeExpr<Float> (*newmodel) );
632 : }
633 : }
634 : }//nterms
635 : }
636 : */
637 :
638 : //////////////////////////////////////////////////////////////////////////////////////////////////////
639 : //////////////////////////////////////////////////////////////////////////////////////////////////////
640 :
641 3636 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::psf(uInt term)
642 : {
643 3636 : AlwaysAssert( itsPsfs.nelements() > term, AipsError );
644 3640 : accessImage( itsPsfs[term], itsParentPsfs[term], imageExts(PSF)+".tt"+String::toString(term) );
645 3634 : return itsPsfs[term];
646 : }
647 8145 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::residual(uInt term)
648 : {
649 8149 : accessImage( itsResiduals[term], itsParentResiduals[term], imageExts(RESIDUAL)+".tt"+String::toString(term) );
650 : // Record mi = itsResiduals[term]->miscInfo(); ostringstream oss;mi.print(oss);cout<<"MiscInfo(res) " << term << " : " << oss.str() << endl;
651 :
652 8143 : return itsResiduals[term];
653 : }
654 1167 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::weight(uInt term)
655 : {
656 1167 : accessImage( itsWeights[term], itsParentWeights[term], imageExts(WEIGHT)+".tt"+String::toString(term) );
657 1167 : return itsWeights[term];
658 : }
659 5695 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::sumwt(uInt term)
660 : {
661 5695 : accessImage( itsSumWts[term], itsParentSumWts[term], imageExts(SUMWT)+".tt"+String::toString(term) );
662 :
663 :
664 5695 : if( itsNFacets>1 || itsNChanChunks>1 || itsNPolChunks>1 )
665 276 : {itsUseWeight = getUseWeightImage( *itsParentSumWts[0] );}
666 5695 : setUseWeightImage( *(itsSumWts[term]) , itsUseWeight); // Sets a flag in the SumWt image.
667 :
668 5695 : return itsSumWts[term];
669 : }
670 3957 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::model(uInt term)
671 : {
672 :
673 3963 : accessImage( itsModels[term], itsParentModels[term], imageExts(MODEL)+".tt"+String::toString(term) );
674 :
675 3955 : itsModels[term]->setUnits("Jy/pixel");
676 3955 : return itsModels[term];
677 : }
678 :
679 3703 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::image(uInt term)
680 : {
681 :
682 3703 : accessImage( itsImages[term], itsParentImages[term], imageExts(IMAGE)+".tt"+String::toString(term) );
683 3703 : itsImages[term]->setUnits("Jy/beam");
684 3703 : return itsImages[term];
685 : }
686 :
687 1637 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::pb(uInt term)
688 : {
689 :
690 1641 : accessImage( itsPBs[term], itsParentPBs[term], imageExts(PB)+".tt"+String::toString(term) );
691 1635 : return itsPBs[term];
692 : }
693 :
694 20 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::imagepbcor(uInt term)
695 : {
696 :
697 20 : accessImage( itsImagePBcors[term], itsParentImagePBcors[term], imageExts(IMAGE)+".tt"+String::toString(term)+ ".pbcor" );
698 20 : itsImagePBcors[term]->setUnits("Jy/beam");
699 20 : return itsImagePBcors[term];
700 : }
701 :
702 624 : std::shared_ptr<ImageInterface<Complex> > SIImageStoreMultiTerm::forwardGrid(uInt term){
703 624 : if( itsForwardGrids[term] )// && (itsForwardGrids[term]->shape() == itsImageShape))
704 514 : return itsForwardGrids[term];
705 110 : Vector<Int> whichStokes(0);
706 110 : IPosition cimageShape;
707 110 : cimageShape=itsImageShape;
708 110 : CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord( itsCoordSys,
709 110 : whichStokes, itsDataPolRep);
710 110 : cimageCoord.setObsInfo(itsCoordSys.obsInfo());
711 110 : cimageShape(2)=whichStokes.nelements();
712 110 : itsForwardGrids[term].reset(new TempImage<Complex>(TiledShape(cimageShape, tileShape()), cimageCoord, memoryBeforeLattice()));
713 110 : return itsForwardGrids[term];
714 110 : }
715 1350 : std::shared_ptr<ImageInterface<Complex> > SIImageStoreMultiTerm::backwardGrid(uInt term){
716 :
717 1350 : if( itsBackwardGrids[term] && (itsBackwardGrids[term]->shape() == itsImageShape))
718 1005 : return itsBackwardGrids[term];
719 : // cout << "MT : Making backward grid of shape : " << itsImageShape << endl;
720 345 : Vector<Int> whichStokes(0);
721 345 : IPosition cimageShape;
722 345 : cimageShape=itsImageShape;
723 345 : CoordinateSystem cimageCoord = StokesImageUtil::CStokesCoord( itsCoordSys,
724 345 : whichStokes, itsDataPolRep);
725 345 : cimageCoord.setObsInfo(itsCoordSys.obsInfo());
726 345 : cimageShape(2)=whichStokes.nelements();
727 345 : itsBackwardGrids[term].reset(new TempImage<Complex>(TiledShape(cimageShape, tileShape()), cimageCoord, memoryBeforeLattice()));
728 345 : return itsBackwardGrids[term];
729 345 : }
730 :
731 480 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::alpha()
732 : {
733 480 : if( itsAlpha && itsAlpha->shape() == itsImageShape ) { return itsAlpha; }
734 : // checkRef( itsAlpha , "alpha" );
735 120 : itsAlpha = openImage( itsImageName+String(".alpha"), false );
736 : // itsAlpha->setUnits("Alpha");
737 120 : return itsAlpha;
738 : }
739 :
740 0 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::beta()
741 : {
742 0 : if( itsBeta && itsBeta->shape() == itsImageShape ) { return itsBeta; }
743 : // checkRef( itsBeta , "beta" );
744 0 : itsBeta = openImage( itsImageName+String(".beta"), false );
745 : // itsBeta->setUnits("Beta");
746 0 : return itsBeta;
747 : }
748 :
749 720 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::alphaerror()
750 : {
751 720 : if( itsAlphaError && itsAlphaError->shape() == itsImageShape ) { return itsAlphaError; }
752 : // checkRef( itsAlpha , "alpha" );
753 120 : itsAlphaError = openImage( itsImageName+String(".alpha.error"), false );
754 : // itsAlpha->setUnits("Alpha");
755 120 : return itsAlphaError;
756 : }
757 :
758 0 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::alphapbcor()
759 : {
760 0 : if( itsAlphaPBcor && itsAlphaPBcor->shape() == itsImageShape ) { return itsAlphaPBcor; }
761 : // checkRef( itsAlphaPBcor , "alpha" );
762 0 : itsAlphaPBcor = openImage( itsImageName+String(".alpha.pbcor"), False );
763 : // itsAlphaPBcor->setUnits("Alpha");
764 0 : return itsAlphaPBcor;
765 : }
766 :
767 0 : std::shared_ptr<ImageInterface<Float> > SIImageStoreMultiTerm::betapbcor()
768 : {
769 0 : if( itsBetaPBcor && itsBetaPBcor->shape() == itsImageShape ) { return itsBetaPBcor; }
770 : // checkRef( itsBetaPBcor , "beta" );
771 0 : itsBetaPBcor = openImage( itsImageName+String(".beta.pbcor"), False );
772 : // itsBetaPBcor->setUnits("Beta");
773 0 : return itsBetaPBcor;
774 : }
775 :
776 :
777 :
778 : // TODO : Move to an image-wrapper class ? Same function exists in SynthesisDeconvolver.
779 18740 : Bool SIImageStoreMultiTerm::doesImageExist(String imagename)
780 : {
781 37480 : LogIO os( LogOrigin("SIImageStoreMultiTerm","doesImageExist",WHERE) );
782 18740 : Directory image( imagename );
783 37480 : return image.exists();
784 18740 : }
785 :
786 :
787 0 : void SIImageStoreMultiTerm::resetImages( Bool resetpsf, Bool resetresidual, Bool resetweight )
788 : {
789 0 : for(uInt tix=0;tix<2*itsNTerms-1;tix++)
790 : {
791 0 : if( resetpsf ) psf(tix)->set(0.0);
792 :
793 0 : if( tix < itsNTerms ) {
794 0 : if( resetresidual ) {
795 : //removeMask( residual(tix) );
796 0 : residual(tix)->set(0.0);
797 : }
798 : }
799 0 : if( resetweight && itsWeights[tix] ) weight(tix)->set(0.0);
800 0 : if( resetweight ) sumwt(tix)->set(0.0);
801 : }//nterms
802 0 : }
803 :
804 0 : void SIImageStoreMultiTerm::addImages( std::shared_ptr<SIImageStore> imagestoadd,
805 : Bool addpsf, Bool addresidual, Bool addweight, Bool adddensity)
806 : {
807 0 : for(uInt tix=0;tix<2*itsNTerms-1;tix++)
808 : {
809 :
810 0 : if(addpsf)
811 : {
812 0 : LatticeExpr<Float> adderPsf( *(psf(tix)) + *(imagestoadd->psf(tix)) );
813 0 : psf(tix)->copyData(adderPsf);
814 0 : }
815 0 : if(addweight)
816 : {
817 :
818 0 : if(getUseWeightImage( *(imagestoadd->sumwt(tix)) ) ) // Access and add weight only if it is needed.
819 : {
820 0 : LatticeExpr<Float> adderWeight( *(weight(tix)) + *(imagestoadd->weight(tix)) );
821 0 : weight(tix)->copyData(adderWeight);
822 0 : }
823 :
824 0 : LatticeExpr<Float> adderSumWt( *(sumwt(tix)) + *(imagestoadd->sumwt(tix)) );
825 0 : sumwt(tix)->copyData(adderSumWt);
826 0 : setUseWeightImage( *sumwt(tix), getUseWeightImage(*(imagestoadd->sumwt(tix)) ) );
827 0 : }
828 :
829 0 : if(tix < itsNTerms && addresidual)
830 : {
831 0 : LatticeExpr<Float> adderRes( *(residual(tix)) + *(imagestoadd->residual(tix)) );
832 0 : residual(tix)->copyData(adderRes);
833 0 : }
834 :
835 0 : if( tix==0 && adddensity )
836 : {
837 0 : LatticeExpr<Float> adderDensity( *(gridwt()) + *(imagestoadd->gridwt()) );
838 0 : gridwt()->copyData(adderDensity);
839 0 : }
840 :
841 : }
842 0 : }
843 :
844 105 : void SIImageStoreMultiTerm::dividePSFByWeight(const Float /*pblimit*/)
845 : {
846 210 : LogIO os( LogOrigin("SIImageStoreMultiTerm","dividePSFByWeight",WHERE) );
847 :
848 : //// for(uInt tix=0;tix<2*itsNTerms-1;tix++)
849 414 : for(Int tix=2*itsNTerms-1-1;tix>-1;tix--) // AAH go backwards so that zeroth term is normalized last..... sigh sigh sigh.
850 : {
851 :
852 : //cout << "npsfs : " << itsPsfs.nelements() << " and tix : " << tix << endl;
853 :
854 309 : normPSF(tix);
855 :
856 309 : if ( itsUseWeight) {
857 118 : divideImageByWeightVal( *weight(tix) );
858 : }
859 :
860 : }
861 105 : }
862 :
863 105 : void SIImageStoreMultiTerm::normalizePrimaryBeam(const Float pblimit)
864 : {
865 210 : LogIO os( LogOrigin("SIImageStoreMultiTerm","normalizePrimaryBeam",WHERE) );
866 105 : if ( itsUseWeight) {
867 :
868 40 : makePBFromWeight(pblimit);
869 : }
870 65 : else { makePBImage(pblimit); }
871 : // calcSensitivity();
872 105 : }
873 :
874 :
875 : // Make another for the PSF too.
876 181 : void SIImageStoreMultiTerm::divideResidualByWeight(Float pblimit, const String normtype)
877 : {
878 362 : LogIO os( LogOrigin("SIImageStoreMultiTerm","divideResidualByWeight",WHERE) );
879 :
880 181 : if( itsUseWeight )
881 : {
882 64 : itsPBScaleFactor = getPbMax();
883 : }
884 :
885 538 : for(uInt tix=0;tix<itsNTerms;tix++)
886 : {
887 :
888 357 : divideImageByWeightVal( *residual(tix) );
889 :
890 : // if(doesImageExist(itsImageName+String(".weight.tt0")) )
891 357 : if( itsUseWeight )
892 : {
893 127 : LatticeExpr<Float> ratio;
894 127 : Float scalepb = fabs(pblimit) * itsPBScaleFactor * itsPBScaleFactor ;
895 127 : if( normtype=="flatnoise"){
896 238 : LatticeExpr<Float> deno = LatticeExpr<Float> ( sqrt( abs(*(weight(0)) ) ) * itsPBScaleFactor );
897 119 : os << LogIO::NORMAL1 << "Dividing " << itsImageName+String(".residual.tt")+String::toString(tix) ;
898 119 : os << " by [ sqrt(weightimage) * " << itsPBScaleFactor ;
899 119 : os << " ] to get flat noise with unit pb peak."<< LogIO::POST;
900 238 : LatticeExpr<Float> mask( iif( (deno) > scalepb , 1.0, 0.0 ) );
901 238 : LatticeExpr<Float> maskinv( iif( (deno) > scalepb , 0.0, 1.0 ) );
902 119 : ratio=LatticeExpr<Float> ( ( (*(residual(tix))) * mask ) / ( deno + maskinv ) );
903 119 : }
904 8 : else if(normtype=="pbsquare"){
905 8 : Float deno = itsPBScaleFactor*itsPBScaleFactor ;
906 8 : os << LogIO::NORMAL1 << "Dividing " << itsImageName+String(".residual.tt")+String::toString(tix) ;
907 8 : os << deno ;
908 8 : os << " ] to get optimal sig/noise with unit pb peak."<< LogIO::POST;
909 :
910 8 : ratio=LatticeExpr<Float> ( ( *(residual(tix)) ) / ( deno ) );
911 :
912 :
913 :
914 : }
915 0 : else if( normtype=="flatsky") {
916 0 : LatticeExpr<Float> deno( *(weight(0)) );
917 0 : os << LogIO::NORMAL1 << "Dividing " << itsImageName+String(".residual.tt")+String::toString(tix) ;
918 0 : os << " by [ weight ] to get flat sky"<< LogIO::POST;
919 0 : LatticeExpr<Float> mask( iif( (deno) > scalepb , 1.0, 0.0 ) );
920 0 : LatticeExpr<Float> maskinv( iif( (deno) > scalepb , 0.0, 1.0 ) );
921 0 : ratio=LatticeExpr<Float> ( ( (*(residual(tix))) * mask ) / ( deno + maskinv ) );
922 0 : }
923 : else{
924 0 : throw(AipsError("Don't know how to proceed with normtype "+normtype));
925 : }
926 :
927 :
928 :
929 127 : residual(tix)->copyData(ratio);
930 127 : }
931 :
932 357 : if( (residual(tix)->getDefaultMask()=="") && hasPB() && pblimit >= 0.0 )
933 177 : {copyMask(pb(),residual(tix));}
934 :
935 357 : if( pblimit <0.0 && (residual(tix)->getDefaultMask()).matches("mask0") ) removeMask( residual(tix) );
936 :
937 : }
938 181 : }
939 :
940 179 : void SIImageStoreMultiTerm::divideModelByWeight(Float pblimit, const String normtype)
941 : {
942 358 : LogIO os( LogOrigin("SIImageStoreMultiTerm","divideModelByWeight",WHERE) );
943 :
944 358 : if( itsUseWeight // only when needed
945 179 : && weight() )// i.e. only when possible. For an initial starting model, don't need wt anyway.
946 : {
947 :
948 64 : if( normtype=="flatsky") {
949 0 : Array<Float> arrmod;
950 0 : model(0)->get( arrmod, true );
951 :
952 0 : os << "Model is already flat sky with peak flux : " << max(arrmod);
953 0 : os << ". No need to divide before prediction" << LogIO::POST;
954 :
955 0 : return;
956 0 : }
957 :
958 64 : itsPBScaleFactor = getPbMax();
959 :
960 191 : for(uInt tix=0;tix<itsNTerms;tix++)
961 127 : { LatticeExpr<Float> deno;
962 127 : if(normtype=="flatnoise"){
963 119 : os << LogIO::NORMAL1 << "Dividing " << itsImageName+String(".model")+String::toString(tix);
964 119 : os << " by [ sqrt(weight) / " << itsPBScaleFactor ;
965 119 : os <<" ] to get to flat sky model before prediction" << LogIO::POST;
966 :
967 119 : deno = LatticeExpr<Float> ( sqrt( abs(*(weight(0))) ) / itsPBScaleFactor );
968 : }
969 8 : else if(normtype=="pbsquare"){
970 8 : os << LogIO::NORMAL1 << "Dividing " << itsImageName+String(".model")+String::toString(tix);
971 8 : os << " by [ (weight) / " << itsPBScaleFactor*itsPBScaleFactor ;
972 8 : os <<" ] to get an optimal sig/noise model before prediction" << LogIO::POST;
973 :
974 8 : deno = LatticeExpr<Float> ( abs(*(weight(0))) / (itsPBScaleFactor*itsPBScaleFactor) );
975 : }
976 254 : LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
977 254 : LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
978 254 : LatticeExpr<Float> ratio( ( (*(model(tix))) * mask ) / ( deno + maskinv ) );
979 :
980 127 : itsModels[tix]->copyData(ratio);
981 127 : }
982 : }
983 179 : }
984 :
985 :
986 179 : void SIImageStoreMultiTerm::multiplyModelByWeight(Float pblimit, const String normtype)
987 : {
988 358 : LogIO os( LogOrigin("SIImageStoreMultiTerm","multiplyModelByWeight",WHERE) );
989 :
990 :
991 358 : if( itsUseWeight // only when needed
992 179 : && weight() )// i.e. only when possible. For an initial starting model, don't need wt anyway.
993 : {
994 :
995 64 : if( normtype=="flatsky") {
996 0 : os << "Model is already flat sky. No need to multiply back after prediction" << LogIO::POST;
997 0 : return;
998 : }
999 :
1000 64 : itsPBScaleFactor = getPbMax();
1001 :
1002 191 : for(uInt tix=0;tix<itsNTerms;tix++)
1003 : {
1004 127 : LatticeExpr<Float> deno;
1005 127 : if( normtype=="flatnoise") {
1006 119 : os << LogIO::NORMAL1 << "Multiplying " << itsImageName+String(".model")+String::toString(tix);
1007 119 : os << " by [ sqrt(weight) / " << itsPBScaleFactor;
1008 119 : os << " ] to take model back to flat noise with unit pb peak." << LogIO::POST;
1009 :
1010 119 : deno=LatticeExpr<Float> ( sqrt( abs(*(weight(0)) ) ) / itsPBScaleFactor );
1011 : }
1012 8 : else if ( normtype=="pbsquare"){
1013 8 : os << LogIO::NORMAL1 << "Multiplying " << itsImageName+String(".model")+String::toString(tix);
1014 8 : os << " by [ weight / " << itsPBScaleFactor*itsPBScaleFactor;
1015 8 : os << " ] to take model back to optima sig/noise with unit pb peak." << LogIO::POST;
1016 :
1017 8 : deno=LatticeExpr<Float> ( abs(*(weight(0)) ) / (itsPBScaleFactor*itsPBScaleFactor) );
1018 : }
1019 : else{
1020 0 : throw(AipsError("No idea of what to do for "+normtype));
1021 : }
1022 :
1023 254 : LatticeExpr<Float> mask( iif( (deno) > fabs(pblimit) , 1.0, 0.0 ) );
1024 254 : LatticeExpr<Float> maskinv( iif( (deno) > fabs(pblimit) , 0.0, 1.0 ) );
1025 254 : LatticeExpr<Float> ratio( ( (*(model(tix))) * mask ) * ( deno + maskinv ) );
1026 :
1027 127 : itsModels[tix]->copyData(ratio);
1028 127 : }
1029 : }
1030 179 : }
1031 :
1032 :
1033 132 : void SIImageStoreMultiTerm::restore(GaussianBeam& rbeam, String& usebeam, uInt /*term*/, Float psfcutoff)
1034 : {
1035 :
1036 264 : LogIO os( LogOrigin("SIImageStoreMultiTerm","restore",WHERE) );
1037 :
1038 393 : for(uInt tix=0; tix<itsNTerms; tix++)
1039 : {
1040 261 : SIImageStore::restore(rbeam, usebeam, tix, psfcutoff);
1041 : }
1042 :
1043 132 : calculateAlphaBeta("image");
1044 :
1045 132 : }// restore
1046 :
1047 132 : void SIImageStoreMultiTerm::calculateAlphaBeta(String imtype)
1048 : {
1049 264 : LogIO os( LogOrigin("SIImageStoreMultiTerm","calculateAlphaBeta",WHERE) );
1050 : try
1051 : {
1052 :
1053 : // Check if this is Stokes I.
1054 132 : Bool isOnlyStokesI=True;
1055 :
1056 132 : Vector<Int> stokes ( (itsParentCoordSys.stokesCoordinate()).stokes() );
1057 132 : AlwaysAssert( stokes.nelements()>0 , AipsError);
1058 132 : if( stokes.nelements()>1 || stokes[0]!=1 ) isOnlyStokesI=False;
1059 :
1060 132 : if( ! isOnlyStokesI )
1061 9 : { os << "Alpha and Beta images will not be computed for images that contain anything other than stokes I in them." << LogIO::POST; }
1062 :
1063 : //Calculate alpha, beta
1064 132 : if( itsNTerms > 1 && isOnlyStokesI)
1065 : {
1066 : // Calculate alpha and beta
1067 240 : LatticeExprNode leMaxRes = max( *( residual(0) ) );
1068 120 : Float maxres = leMaxRes.getFloat();
1069 120 : Float specthreshold = maxres/10.0; //////////// do something better here.....
1070 :
1071 120 : os << "Calculating spectral parameters for Intensity > peakresidual/10 = " << specthreshold << " Jy/beam" << LogIO::POST;
1072 :
1073 : /////////////////////////////////////////////////////////
1074 : /////// Calculate alpha
1075 120 : if(imtype=="image")
1076 : {
1077 240 : LatticeExpr<Float> mask1(iif(((*(image(0))))>(specthreshold),1.0,0.0));
1078 240 : LatticeExpr<Float> mask0(iif(((*(image(0))))>(specthreshold),0.0,1.0));
1079 240 : LatticeExpr<Float> alphacalc( (((*(image(1))))*mask1)/(((*(image(0))))+(mask0)) );
1080 120 : alpha()->copyData(alphacalc);
1081 :
1082 120 : ImageInfo ii = image(0)->imageInfo();
1083 : // Set the restoring beam for alpha
1084 120 : alpha()->setImageInfo(ii);
1085 : //alpha()->table().unmarkForDelete();
1086 :
1087 : // Make a mask for the alpha image
1088 240 : LatticeExpr<Bool> lemask(iif(((*(image(0))) > specthreshold) , True, False));
1089 120 : removeMask( alpha() );
1090 120 : createMask( lemask, (alpha()) );
1091 :
1092 : /////// Calculate alpha error
1093 120 : alphaerror()->set(0.0);
1094 :
1095 240 : LatticeExpr<Float> alphacalcerror( abs(alphacalc) * sqrt( ( (*residual(0)*mask1)/(*image(0)+mask0) )*( (*residual(0)*mask1)/(*image(0)+mask0) ) + ( (*residual(1)*mask1)/(*image(1)+mask0) )*( (*residual(1)*mask1)/(*image(1)+mask0) ) ) );
1096 120 : alphaerror()->copyData(alphacalcerror);
1097 120 : alphaerror()->setImageInfo(ii);
1098 120 : removeMask(alphaerror());
1099 120 : createMask(lemask, alphaerror());
1100 : // alphaerror()->table().unmarkForDelete();
1101 120 : os << "Written Spectral Index Error Image : " << alphaerror()->name() << LogIO::POST;
1102 :
1103 120 : if(itsNTerms>2) // calculate beta too.
1104 : {
1105 0 : beta()->set(0.0);
1106 0 : LatticeExpr<Float> betacalc( (*image(2)*mask1)/((*image(0))+(mask0))-0.5*(*alpha())*((*alpha())-1.0) );
1107 0 : beta()->copyData(betacalc);
1108 0 : beta()->setImageInfo(ii);
1109 : //imbeta.setUnits(Unit("Spectral Curvature"));
1110 0 : removeMask(beta());
1111 0 : createMask(lemask, beta());
1112 0 : os << "Written Spectral Curvature Image : " << beta()->name() << LogIO::POST;
1113 0 : }
1114 :
1115 120 : }
1116 : else
1117 : {
1118 0 : LatticeExpr<Float> mask1(iif(((*(imagepbcor(0))))>(specthreshold),1.0,0.0));
1119 0 : LatticeExpr<Float> mask0(iif(((*(imagepbcor(0))))>(specthreshold),0.0,1.0));
1120 0 : LatticeExpr<Float> alphacalc( (((*(imagepbcor(1))))*mask1)/(((*(imagepbcor(0))))+(mask0)) );
1121 0 : alphapbcor()->copyData(alphacalc);
1122 :
1123 0 : ImageInfo ii = image(0)->imageInfo();
1124 : // Set the restoring beam for alpha
1125 0 : alphapbcor()->setImageInfo(ii);
1126 : //alpha()->table().unmarkForDelete();
1127 :
1128 : // Make a mask for the alpha image
1129 0 : LatticeExpr<Bool> lemask(iif(((*(imagepbcor(0))) > specthreshold) , True, False));
1130 0 : removeMask( alphapbcor() );
1131 0 : createMask( lemask, (alphapbcor()) );
1132 :
1133 : /////////////////////////////////////////////////////////
1134 0 : if(itsNTerms>2) // calculate beta too.
1135 : {
1136 0 : betapbcor()->set(0.0);
1137 0 : LatticeExpr<Float> betacalc( (*imagepbcor(2)*mask1)/((*imagepbcor(0))+(mask0))-0.5*(*alphapbcor())*((*alphapbcor())-1.0) );
1138 0 : betapbcor()->copyData(betacalc);
1139 0 : betapbcor()->setImageInfo(ii);
1140 : //imbeta.setUnits(Unit("Spectral Curvature"));
1141 0 : removeMask(betapbcor());
1142 0 : createMask(lemask, betapbcor());
1143 0 : os << "Written Spectral Curvature Image : " << betapbcor()->name() << LogIO::POST;
1144 0 : }
1145 :
1146 0 : }// pbcor
1147 :
1148 120 : }//if nterms>1
1149 132 : }
1150 0 : catch(AipsError &x)
1151 : {
1152 0 : throw( AipsError("Error in computing Alpha (and Beta) : " + x.getMesg() ) );
1153 0 : }
1154 :
1155 132 : }// calculateAlphaBeta
1156 :
1157 2 : void SIImageStoreMultiTerm::pbcor()
1158 : {
1159 :
1160 4 : LogIO os( LogOrigin("SIImageStoreMultiTerm","pbcorPlane",WHERE) );
1161 :
1162 2 : os << "Multi-term PBcor : Dividing all Taylor coefficient images by the tt0 average PB. Please refer to documentation of the 'pbcor' parameter in tclean for information about accurate correction of wideband primary beam effects." << LogIO::POST;
1163 :
1164 6 : for(uInt tix=0; tix<itsNTerms; tix++)
1165 : {
1166 4 : SIImageStore::pbcor(tix);
1167 : }
1168 :
1169 : //calculateAlphaBeta("pbcor");
1170 :
1171 2 : }
1172 :
1173 105 : void SIImageStoreMultiTerm::calcSensitivity()
1174 : {
1175 210 : LogIO os( LogOrigin("SIImageStoreMultiTerm","calcSensitivity",WHERE) );
1176 :
1177 : // Construct Hessian.
1178 :
1179 105 : Matrix<Float> hess(IPosition(2,itsNTerms,itsNTerms));
1180 312 : for(uInt tay1=0;tay1<itsNTerms;tay1++)
1181 618 : for(uInt tay2=0;tay2<itsNTerms;tay2++)
1182 : {
1183 : //uInt taymin = (tay1<=tay2)? tay1 : tay2;
1184 : //uInt taymax = (tay1>=tay2)? tay1 : tay2;
1185 : //uInt ind = (taymax*(taymax+1)/2)+taymin;
1186 :
1187 411 : uInt ind = tay1+tay2;
1188 411 : AlwaysAssert( ind < 2*itsNTerms-1, AipsError );
1189 :
1190 411 : Array<Float> lsumwt;
1191 411 : sumwt( ind )->get( lsumwt, false );
1192 : // cout << "lsumwt shape : " << lsumwt.shape() << endl;
1193 411 : AlwaysAssert( lsumwt.shape().nelements()==4, AipsError );
1194 411 : AlwaysAssert( lsumwt.shape()[0]>0, AipsError );
1195 :
1196 : // hess(tay1,tay2) = lsumwt(IPosition(1,0)); //Always pick sumwt from first facet only.
1197 411 : hess(tay1,tay2) = lsumwt(IPosition(4,0,0,0,0)); //Always pick sumwt from first facet only.
1198 411 : }
1199 :
1200 105 : os << "Multi-Term Hessian Matrix : " << hess << LogIO::POST;
1201 :
1202 : // Invert Hessian.
1203 : try
1204 : {
1205 105 : Float deter=0.0;
1206 105 : Matrix<Float> invhess;
1207 105 : invertSymPosDef(invhess,deter,hess);
1208 105 : os << "Multi-Term Covariance Matrix : " << invhess << LogIO::POST;
1209 :
1210 : // Just print the sqrt of the diagonal elements.
1211 :
1212 312 : for(uInt tix=0;tix<itsNTerms;tix++)
1213 : {
1214 207 : os << "[" << itsImageName << "][Taylor"<< tix << "] Theoretical sensitivity (Jy/bm):" ;
1215 207 : if( invhess(tix,tix) > 0.0 ) { os << sqrt(invhess(tix,tix)) << LogIO::POST; }
1216 0 : else { os << "none" << LogIO::POST; }
1217 : }
1218 105 : }
1219 0 : catch(AipsError &x)
1220 : {
1221 0 : os << LogIO::WARN << "Cannot invert Hessian Matrix : " << x.getMesg() << " || Calculating approximate sensitivity " << LogIO::POST;
1222 :
1223 : // Approximate : 1/h^2
1224 0 : for(uInt tix=0;tix<itsNTerms;tix++)
1225 : {
1226 0 : Array<Float> lsumwt;
1227 0 : AlwaysAssert( 2*tix < 2*itsNTerms-1, AipsError );
1228 0 : sumwt(2*tix)->get( lsumwt , false );
1229 :
1230 0 : IPosition shp( lsumwt.shape() );
1231 : //cout << "Sumwt shape : " << shp << " : " << lsumwt << endl;
1232 : //AlwaysAssert( shp.nelements()==4 , AipsError );
1233 :
1234 0 : os << "[" << itsImageName << "][Taylor"<< tix << "] Approx Theoretical sensitivity (Jy/bm):" ;
1235 :
1236 0 : IPosition it(4,0,0,0,0);
1237 0 : for ( it[0]=0; it[0]<shp[0]; it[0]++)
1238 0 : for ( it[1]=0; it[1]<shp[1]; it[1]++)
1239 0 : for ( it[2]=0; it[2]<shp[2]; it[2]++)
1240 0 : for ( it[3]=0; it[3]<shp[3]; it[3]++)
1241 : {
1242 0 : if( shp[0]>1 ){os << "f"<< it[0]+(it[1]*shp[0]) << ":" ;}
1243 0 : if( lsumwt( it ) > 1e-07 )
1244 : {
1245 0 : os << 1.0/(sqrt(lsumwt(it))) << " " ;
1246 : }
1247 : else
1248 : {
1249 0 : os << "none" << " ";
1250 : }
1251 : }
1252 :
1253 0 : os << LogIO::POST;
1254 0 : }
1255 0 : }
1256 :
1257 105 : calcFractionalBandwidth();
1258 105 : }
1259 :
1260 242 : Double SIImageStoreMultiTerm::calcFractionalBandwidth()
1261 : {
1262 :
1263 484 : LogIO os( LogOrigin("SIImageStoreMultiTerm","calcFractionalBandwidth",WHERE) );
1264 :
1265 242 : Double fbw=1.0;
1266 :
1267 968 : for(uInt i=0; i<itsCoordSys.nCoordinates(); i++)
1268 : {
1269 726 : if( itsCoordSys.type(i) == Coordinate::SPECTRAL )
1270 : {
1271 242 : SpectralCoordinate speccoord(itsCoordSys.spectralCoordinate(i));
1272 242 : Double startfreq=0.0,startpixel=-0.5;
1273 242 : Double endfreq=0.0,endpixel=+0.5;
1274 242 : speccoord.toWorld(startfreq,startpixel);
1275 242 : speccoord.toWorld(endfreq,endpixel);
1276 242 : Double midfreq = (endfreq+startfreq)/2.0;
1277 242 : fbw = ((endfreq - startfreq)/midfreq) * 100.0;
1278 242 : os << "MFS frequency range : " << startfreq/1.0e+9 << " GHz -> " << endfreq/1.0e+9 << "GHz.";
1279 242 : os << "Fractional Bandwidth : " << fbw << " %.";
1280 242 : os << "Reference Frequency for Taylor Expansion : "<< getReferenceFrequency()/1.0e+9 << "GHz." << LogIO::POST;
1281 242 : }
1282 : }
1283 242 : return fbw;
1284 242 : }
1285 :
1286 :
1287 : // Check for non-zero model (this is different from getting model flux, for derived SIIMMT)
1288 442 : Bool SIImageStoreMultiTerm::isModelEmpty()
1289 : {
1290 : /// There MUST be a more efficient way to do this !!!!! I hope.
1291 : /// Maybe save this info and change it anytime model() is accessed....
1292 442 : Bool emptymodel=true;
1293 1318 : for(uInt tix=0;tix<itsNTerms;tix++)
1294 : {
1295 : //if( fabs( getModelFlux(tix) ) > 1e-08 ) emptymodel=false;
1296 1600 : if( doesImageExist(itsImageName+String(".model.tt")+String::toString(tix)) &&
1297 1234 : fabs( getModelFlux(tix) ) > 1e-08 ) emptymodel=false;
1298 : }
1299 442 : return emptymodel;
1300 : }
1301 :
1302 0 : void SIImageStoreMultiTerm::printImageStats()
1303 : {
1304 0 : LogIO os( LogOrigin("SIImageStoreMultiTerm","printImageStats",WHERE) );
1305 : // FIXME minresmask needs to be initialized here, or else compiler complains
1306 0 : Float minresmask = 0, maxresmask, minres, maxres;
1307 0 : ArrayLattice<Bool> pixelmask(residual()->getMask());
1308 :
1309 : // findMinMax( residual()->get(), mask()->get(), minres, maxres, minresmask, maxresmask );
1310 :
1311 0 : if (hasMask())
1312 : {
1313 : // findMinMaxLattice(*residual(), *mask() , maxres,maxresmask, minres, minresmask);
1314 0 : findMinMaxLattice(*residual(), *mask() , pixelmask, maxres,maxresmask, minres, minresmask);
1315 : }
1316 : else
1317 : {
1318 0 : LatticeExpr<Float> reswithpixmask(iif(pixelmask, *residual(), 0));
1319 : //LatticeExprNode pres( max( *residual() ) );
1320 0 : LatticeExprNode pres( max( reswithpixmask ) );
1321 0 : maxres = pres.getFloat();
1322 : //LatticeExprNode pres2( min( *residual() ) );
1323 0 : LatticeExprNode pres2( min( reswithpixmask ) );
1324 0 : minres = pres2.getFloat();
1325 0 : }
1326 :
1327 0 : os << "[" << itsImageName << "]" ;
1328 0 : os << " Peak residual (max,min) " ;
1329 0 : if( minresmask!=0.0 || maxresmask!=0.0 )
1330 0 : { os << "within mask : (" << maxresmask << "," << minresmask << ") "; }
1331 0 : os << "over full image : (" << maxres << "," << minres << ")" << LogIO::POST;
1332 :
1333 0 : os << "[" << itsImageName << "] Total Model Flux : " ;
1334 0 : for(uInt tix=0;tix<itsNTerms;tix++)
1335 0 : {os << getModelFlux(tix) << "(tt" << String::toString(tix) << ")"; }
1336 0 : os<<LogIO::POST;
1337 :
1338 0 : }
1339 :
1340 307 : std::shared_ptr<SIImageStore> SIImageStoreMultiTerm::getSubImageStore(const Int facet, const Int nfacets,
1341 : const Int chan, const Int nchanchunks,
1342 : const Int pol, const Int npolchunks)
1343 : {
1344 : std::shared_ptr<SIImageStore> multiTermStore =
1345 307 : std::make_shared<SIImageStoreMultiTerm>(itsModels, itsResiduals, itsPsfs, itsWeights, itsImages, itsSumWts, itsPBs, itsImagePBcors, itsMask, itsAlpha, itsBeta, itsAlphaError,itsAlphaPBcor, itsBetaPBcor, itsCoordSys, itsParentImageShape, itsImageName, itsObjectName, itsMiscInfo, facet, nfacets, chan, nchanchunks, pol, npolchunks);
1346 307 : return multiTermStore;
1347 : }
1348 :
1349 :
1350 : //////////////////////////////////////////////////////////////////////////////////////////////////////
1351 :
1352 : //
1353 : //-------------------------------------------------------------
1354 : // Initialize the internals of the object. Perhaps other such
1355 : // initializations in the constructors can be moved here too.
1356 : //
1357 1131 : void SIImageStoreMultiTerm::init()
1358 : {
1359 1131 : imageExts.resize(MAX_IMAGE_IDS);
1360 :
1361 1131 : imageExts(MASK)=".mask";
1362 1131 : imageExts(PSF)=".psf";
1363 1131 : imageExts(MODEL)=".model";
1364 1131 : imageExts(RESIDUAL)=".residual";
1365 1131 : imageExts(WEIGHT)=".weight";
1366 1131 : imageExts(IMAGE)=".image";
1367 1131 : imageExts(SUMWT)=".sumwt";
1368 1131 : imageExts(GRIDWT)=".gridwt";
1369 1131 : imageExts(PB)=".pb";
1370 1131 : imageExts(FORWARDGRID)=".forward";
1371 1131 : imageExts(BACKWARDGRID)=".backward";
1372 : // imageExts(IMAGEPBCOR)=".image.pbcor";
1373 :
1374 1131 : itsParentPsfs.resize(itsPsfs.nelements());
1375 1131 : itsParentModels.resize(itsModels.nelements());
1376 1131 : itsParentResiduals.resize(itsResiduals.nelements());
1377 1131 : itsParentWeights.resize(itsWeights.nelements());
1378 1131 : itsParentImages.resize(itsImages.nelements());
1379 1131 : itsParentSumWts.resize(itsSumWts.nelements());
1380 1131 : itsParentImagePBcors.resize(itsImagePBcors.nelements());
1381 1131 : itsParentPBs.resize(itsPBs.nelements());
1382 :
1383 1131 : itsParentPsfs = itsPsfs;
1384 1131 : itsParentModels=itsModels;
1385 1131 : itsParentResiduals=itsResiduals;
1386 1131 : itsParentWeights=itsWeights;
1387 1131 : itsParentImages=itsImages;
1388 1131 : itsParentSumWts=itsSumWts;
1389 1131 : itsParentImagePBcors=itsImagePBcors;
1390 1131 : itsParentPBs=itsPBs;
1391 :
1392 1131 : itsParentMask=itsMask;
1393 :
1394 1131 : itsParentImageShape = itsImageShape;
1395 1131 : itsParentCoordSys = itsCoordSys;
1396 1131 : if( itsNFacets>1 || itsNChanChunks>1 || itsNPolChunks>1 ) { itsImageShape=IPosition(4,0,0,0,0); }
1397 :
1398 1131 : itsOpened=0;
1399 :
1400 1131 : }
1401 :
1402 : /*
1403 : Bool SIImageStoreMultiTerm::getUseWeightImage()
1404 : { if( itsParentSumWts.nelements()==0 || ! itsParentSumWts[0] )
1405 : {return false;}
1406 : else
1407 : {
1408 : Bool ret = SIImageStore::getUseWeightImage( *(itsParentSumWts[0]) );
1409 : return ret;
1410 : }
1411 : }
1412 : */
1413 : //////////////////////////////////////////////////////////////////////////////////////////////////////
1414 : //////////////////////////////////////////////////////////////////////////////////////////////////////
1415 :
1416 : } //# NAMESPACE CASA - END
1417 :
|