Line data Source code
1 : //# ImagePolProxy.cc: C++ casa namespace proxy for ImagePol tool
2 : //# Copyright (C) 2007
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: 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: ImagePolProxy.cc 20615 2009-06-09 02:16:01Z Malte.Marquarding $
27 : #include <imageanalysis/ImageAnalysis/ImagePolProxy.h>
28 : #include <casacore/casa/aips.h>
29 : #include <iostream>
30 : #include <sstream>
31 : #include <casacore/casa/IO/ArrayIO.h>
32 : #include <casacore/casa/Arrays/ArrayMath.h>
33 : #include <casacore/casa/Arrays/ArrayUtil.h>
34 : #include <casacore/casa/Arrays/MaskedArray.h>
35 : #include <casacore/casa/Arrays/MaskArrMath.h>
36 : #include <casacore/casa/BasicMath/Random.h>
37 : #include <casacore/casa/BasicSL/String.h>
38 : #include <casacore/casa/Containers/Record.h>
39 : #include <casacore/casa/Exceptions/Error.h>
40 : #include <casacore/casa/Logging/LogFilter.h>
41 : #include <casacore/casa/Logging/LogIO.h>
42 : #include <casacore/casa/Logging/LogOrigin.h>
43 : #include <casacore/coordinates/Coordinates/CoordinateUtil.h>
44 : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
45 : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
46 : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
47 : #include <casacore/images/Images/ImageExpr.h>
48 : #include <casacore/images/Images/ImageInterface.h>
49 : #include <casacore/images/Regions/ImageRegion.h>
50 : #include <casacore/images/Images/ImageUtilities.h>
51 : #include <casacore/images/Images/PagedImage.h>
52 : #include <casacore/images/Regions/RegionHandler.h>
53 : #include <casacore/images/Images/SubImage.h>
54 : #include <casacore/images/Images/TempImage.h>
55 : #include <casacore/lattices/Lattices/LatticeUtilities.h>
56 : #include <casacore/measures/Measures/Stokes.h>
57 : #include <casacore/tables/Tables/Table.h>
58 : #include <casacore/tables/LogTables/NewFile.h>
59 : #include <casacore/casa/namespace.h>
60 :
61 : #include <memory>
62 :
63 : using namespace casacore;
64 : namespace casa { //# name space casa begins
65 :
66 :
67 0 : ImagePol::ImagePol() : itsImPol(0)
68 : {
69 0 : itsLog= new LogIO();
70 :
71 0 : }
72 :
73 0 : ImagePol::ImagePol(ImageInterface<Float>& im) : itsLog(0),itsImPol(0)
74 : {
75 0 : open(im);
76 :
77 0 : }
78 :
79 0 : ImagePol::~ImagePol(){
80 0 : if(itsLog)
81 0 : delete itsLog;
82 0 : if(itsImPol)
83 0 : delete itsImPol;
84 0 : }
85 :
86 0 : Bool ImagePol::open(ImageInterface<Float>& im){
87 0 : if(!itsLog)
88 0 : itsLog= new LogIO();
89 0 : if(itsImPol)
90 0 : delete itsImPol;
91 0 : itsImPol= new ImagePolarimetry(im);
92 :
93 0 : return true;
94 :
95 : }
96 :
97 0 : Bool ImagePol::open(const String& infile) {
98 0 : Bool rstat(false);
99 :
100 0 : if(!itsLog) itsLog = new LogIO();
101 0 : *itsLog << LogOrigin("ImagePol", "open(const String& infile)");
102 0 : if (infile.size() == 0) {
103 0 : *itsLog << LogIO::WARN << "You must give an infile" << LogIO::POST;
104 0 : return rstat;
105 : }
106 :
107 0 : if(itsImPol) delete itsImPol;
108 0 : itsImPol=0;
109 : //
110 0 : ImageInterface<Float>* imagePointer = 0;
111 0 : ImageUtilities::openImage (imagePointer, infile);
112 :
113 : //
114 : try {
115 0 : itsImPol = new ImagePolarimetry(*imagePointer);
116 0 : rstat = true;
117 0 : } catch (AipsError x) {
118 0 : delete imagePointer;
119 0 : *itsLog << x.getMesg() << LogIO::EXCEPTION;
120 0 : }
121 : //
122 0 : delete imagePointer;
123 0 : imagePointer = 0;
124 0 : return rstat;
125 : }
126 :
127 : Bool
128 0 : ImagePol::imagepoltestimage(const String& outFile, const Vector<Double>& rm,
129 : Bool rmDefault, Double pa0, Double sigma,
130 : Int nx, Int ny, Int nf, Double f0, Double df)
131 : {
132 :
133 0 : Bool rstat(false);
134 :
135 0 : if (itsLog==0) itsLog= new LogIO();
136 0 : *itsLog << LogOrigin("ImagePol", "imagepoltestimage");
137 :
138 0 : if (outFile.size() == 0) {
139 0 : *itsLog << LogIO::WARN << "You must give an outfile" << LogIO::POST;
140 0 : return rstat;
141 : }
142 :
143 0 : if(itsImPol) delete itsImPol;
144 0 : itsImPol = 0;
145 :
146 : // If not given make RM with no ambiguity
147 0 : Vector<Float> rm2(rm.size());
148 0 : if (rmDefault) {
149 0 : Double l1 = QC::c( ).getValue(Unit("m/s")) / f0;
150 0 : Double l2 = QC::c( ).getValue(Unit("m/s")) / (f0+df);
151 0 : rm2.resize(1);
152 0 : rm2(0) = C::pi / 2 / (l1*l1 - l2*l2);
153 : } else {
154 0 : for (uInt i = 0; i < rm.size(); i++) rm2[i] = rm[i];
155 : }
156 :
157 0 : const uInt nRM = rm2.nelements();
158 : //
159 0 : if (nRM == 1) {
160 0 : *itsLog << LogIO::NORMAL << "Using Rotation Measure = " << rm2(0)
161 0 : << " radians/m/m" << endl;
162 : } else {
163 0 : *itsLog << LogIO::NORMAL << "Using Rotation Measures : " << endl;
164 0 : for (uInt i=0; i<nRM; i++) {
165 0 : *itsLog << " " << rm2(i)
166 0 : << " radians/m/m" << endl;
167 : }
168 : }
169 :
170 0 : *itsLog << "Using pa0 = " << pa0 << " degrees" << endl;
171 0 : *itsLog << "Using frequency = " << f0 << " Hz" << endl;
172 0 : *itsLog << "Using bandwidth = " << df << " Hz " << endl;
173 0 : *itsLog << "Using number channels = " << nf << LogIO::POST;
174 :
175 : // Make image
176 0 : IPosition shape(4,nx,ny,4,nf);
177 0 : ImageInterface<Float>* pImOut = 0;
178 0 : makeIQUVImage(pImOut, outFile, sigma, pa0*C::pi/180.0, rm2, shape, f0, df);
179 : try {
180 0 : itsImPol = new ImagePolarimetry(*pImOut);
181 0 : rstat = true;
182 0 : } catch (AipsError x) {
183 0 : delete pImOut;
184 0 : pImOut = 0;
185 0 : *itsLog << x.getMesg() << LogIO::EXCEPTION;
186 0 : }
187 : //
188 0 : delete pImOut;
189 0 : pImOut = 0;
190 :
191 0 : return rstat;
192 0 : }
193 :
194 :
195 0 : Bool ImagePol::depolratio(ImageInterface<Float>*& returnim,
196 : const String& infile, Bool debias,
197 : Double clip, Double sigma,
198 : const String& outfile){
199 0 : Bool rstat(false);
200 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
201 0 : if(itsImPol==0){
202 0 : *itsLog <<"No attached image, please use open "
203 0 : << LogIO::EXCEPTION;
204 0 : return rstat;
205 : }
206 0 : auto im1=itsImPol->imageInterface();
207 0 : std::unique_ptr<ImageInterface<Float> > im2;
208 0 : ImageUtilities::openImage(im2, infile);
209 0 : ImageExpr<Float> tmpim=itsImPol->depolarizationRatio(*im1, *im2,
210 : debias,
211 : Float(clip),
212 0 : Float(sigma));
213 :
214 0 : String err;
215 0 : if(!copyImage(returnim, tmpim, outfile, true)){
216 0 : *itsLog <<"Could not convert ratio image "
217 0 : << LogIO::EXCEPTION;
218 : }
219 0 : rstat = true;
220 0 : return rstat;
221 :
222 0 : }
223 :
224 :
225 0 : Bool ImagePol::complexlinpol(const String& outfile) {
226 0 : *itsLog << LogOrigin("ImagePolProxy", __FUNCTION__);
227 0 : if (! itsImPol) {
228 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
229 0 : << LogIO::POST;
230 0 : return false;
231 : }
232 :
233 0 : if (outfile.size() == 0) {
234 0 : *itsLog << LogIO::WARN << "You must give an outfile" << LogIO::POST;
235 0 : return false;
236 : }
237 0 : CoordinateSystem cSysPol;
238 0 : const auto shapePol = itsImPol->singleStokesShape(
239 : cSysPol, Stokes::Plinear
240 0 : );
241 0 : const auto isMasked = itsImPol->isMasked();
242 : auto pOutComplex = _makeImage(
243 : outfile, cSysPol, shapePol, isMasked, false
244 0 : );
245 0 : auto expr = itsImPol->complexLinearPolarization();
246 0 : fiddleStokesCoordinate(*pOutComplex, Stokes::Plinear);
247 :
248 : // Copy to output
249 :
250 0 : pOutComplex->setCoordinateInfo(expr.coordinates());
251 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutComplex, expr);
252 0 : auto p = itsImPol->imageInterface();
253 0 : copyMiscellaneous (*pOutComplex, *p);
254 0 : return true;
255 0 : }
256 :
257 : // Summary
258 0 : void ImagePol::summary() const {
259 0 : *itsLog << LogOrigin("imagepol", "summary()");
260 0 : if(itsImPol==0){
261 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
262 0 : << LogIO::POST;
263 0 : return;
264 : }
265 0 : itsImPol->summary(*itsLog);
266 : }
267 :
268 : // sigma
269 0 : Float ImagePol::sigma(Float clip) const {
270 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
271 0 : if(itsImPol==0){
272 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
273 0 : << LogIO::POST;
274 0 : return -1.0;
275 : }
276 0 : return itsImPol->sigma(clip);
277 : }
278 :
279 : // Stokes I
280 0 : Bool ImagePol::stokesI(ImageInterface<Float>*& rtnim, const String& outfile){
281 0 : Bool rstat(false);
282 0 : *itsLog << LogOrigin("imagepol", "stokesI(...)");
283 0 : if(itsImPol==0){
284 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
285 0 : << LogIO::POST;
286 0 : return rstat;
287 : }
288 0 : ImageExpr<Float> expr = itsImPol->stokesI();
289 : // Create output image
290 0 : rstat = copyImage (rtnim, expr, outfile, true);
291 0 : return rstat;
292 0 : }
293 :
294 0 : Float ImagePol::sigmaStokesI(Float clip) const {
295 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
296 0 : if(itsImPol==0){
297 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
298 0 : << LogIO::POST;
299 0 : return -1.0;
300 : }
301 0 : return itsImPol->sigmaStokesI(clip);
302 : }
303 :
304 : // Stokes Q
305 0 : Bool ImagePol::stokesQ(ImageInterface<Float>*& rtnim, const String& outfile){
306 0 : Bool rstat(false);
307 0 : *itsLog << LogOrigin("imagepol", "stokesQ(...)");
308 0 : if(itsImPol==0){
309 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
310 0 : << LogIO::POST;
311 0 : return rstat;
312 : }
313 0 : ImageExpr<Float> expr = itsImPol->stokesQ();
314 :
315 : // Create output image if needed
316 0 : rstat = copyImage (rtnim, expr, outfile, true);
317 0 : return rstat;
318 0 : }
319 :
320 0 : Float ImagePol::sigmaStokesQ(Float clip) const {
321 0 : *itsLog << LogOrigin("imagepol", "sigmaStokesQ(...)");
322 0 : if(itsImPol==0){
323 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
324 0 : << LogIO::POST;
325 0 : return -1.0;
326 : }
327 0 : return itsImPol->sigmaStokesQ(clip);
328 : }
329 :
330 : // Stokes U
331 0 : Bool ImagePol::stokesU(ImageInterface<Float>*& rtnim, const String& outfile){
332 0 : Bool rstat(false);
333 0 : *itsLog << LogOrigin("imagepol", "stokesU(...)");
334 0 : if(itsImPol==0){
335 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
336 0 : << LogIO::POST;
337 0 : return rstat;
338 : }
339 0 : ImageExpr<Float> expr = itsImPol->stokesU();
340 :
341 : // Create output image if needed
342 0 : rstat = copyImage (rtnim, expr, outfile, true);
343 0 : return rstat;
344 0 : }
345 :
346 0 : Float ImagePol::sigmaStokesU(Float clip) const {
347 0 : *itsLog << LogOrigin("imagepol", "sigmaStokesU(...)");
348 0 : if(itsImPol==0){
349 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
350 0 : << LogIO::POST;
351 0 : return -1.0;
352 : }
353 0 : return itsImPol->sigmaStokesU(clip);
354 : }
355 :
356 : // Stokes V
357 0 : Bool ImagePol::stokesV(ImageInterface<Float>*& rtnim, const String& outfile){
358 0 : Bool rstat(false);
359 0 : *itsLog << LogOrigin("imagepol", "stokesV(...)");
360 0 : if(itsImPol==0){
361 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
362 0 : << LogIO::POST;
363 0 : return rstat;
364 : }
365 0 : ImageExpr<Float> expr = itsImPol->stokesV();
366 :
367 : // Create output image if needed
368 0 : rstat = copyImage (rtnim, expr, outfile, true);
369 0 : return rstat;
370 0 : }
371 :
372 0 : Float ImagePol::sigmaStokesV(Float clip) const {
373 0 : *itsLog << LogOrigin("imagepol", "sigmaStokesV(...)");
374 0 : if(itsImPol==0){
375 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
376 0 : << LogIO::POST;
377 0 : return -1.0;
378 : }
379 0 : return itsImPol->sigmaStokesV(clip);
380 : }
381 :
382 0 : Float ImagePol::sigmaLinPolInt(Float clip, Float sigma) const {
383 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
384 0 : if(itsImPol==0){
385 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
386 0 : << LogIO::POST;
387 0 : return -1.0;
388 : }
389 0 : return itsImPol->sigmaLinPolInt(clip, sigma);
390 : }
391 :
392 0 : Float ImagePol::sigmaTotPolInt(Float clip, Float sigma) const {
393 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
394 0 : if(itsImPol==0){
395 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
396 0 : << LogIO::POST;
397 0 : return -1.0;
398 : }
399 0 : return itsImPol->sigmaTotPolInt(clip, sigma);
400 : }
401 :
402 : // Complex linear polarization
403 0 : void ImagePol::complexLinearPolarization (const String& outfile) {
404 0 : *itsLog << LogOrigin("imagepol", "complexLinearPolarization(...)");
405 0 : if(itsImPol==0){
406 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
407 0 : << LogIO::POST;
408 0 : return;
409 : }
410 :
411 0 : if (outfile.size() == 0)
412 0 : *itsLog << LogIO::WARN << "You must give an outfile" << LogIO::POST;
413 :
414 : // Make output complex image
415 0 : ImageInterface<Complex>* pOutComplex = 0;
416 0 : CoordinateSystem cSysPol;
417 0 : IPosition shapePol = itsImPol->singleStokesShape(cSysPol, Stokes::Plinear);
418 0 : _makeImage (pOutComplex, outfile, cSysPol, shapePol,
419 0 : itsImPol->isMasked(), false);
420 :
421 : // Make Expr
422 0 : ImageExpr<Complex> expr = itsImPol->complexLinearPolarization();
423 0 : fiddleStokesCoordinate(*pOutComplex, Stokes::Plinear);
424 :
425 : // Copy to output
426 0 : pOutComplex->setCoordinateInfo(expr.coordinates());
427 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutComplex, expr);
428 : //
429 0 : auto p = itsImPol->imageInterface();
430 0 : copyMiscellaneous (*pOutComplex, *p);
431 0 : delete pOutComplex;
432 0 : }
433 :
434 : // Complex linear polarization
435 0 : void ImagePol::complexFractionalLinearPolarization (const String& outfile) {
436 0 : *itsLog << LogOrigin("imagepol", "complexFractionalLinearPolarization(...)");
437 0 : if(itsImPol==0){
438 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
439 0 : << LogIO::POST;
440 0 : return;
441 : }
442 :
443 : // Make output complex image
444 0 : ImageInterface<Complex>* pOutComplex = 0;
445 0 : CoordinateSystem cSysPol;
446 0 : IPosition shapePol = itsImPol->singleStokesShape(cSysPol, Stokes::PFlinear);
447 0 : _makeImage (pOutComplex, outfile, cSysPol, shapePol,
448 0 : itsImPol->isMasked(), false);
449 :
450 0 : std::unique_ptr<ImageInterface<Complex> > x(pOutComplex);
451 :
452 : // Make Expr
453 0 : ImageExpr<Complex> expr = itsImPol->complexFractionalLinearPolarization();
454 0 : fiddleStokesCoordinate(*pOutComplex, Stokes::PFlinear);
455 :
456 : // Copy to output
457 0 : pOutComplex->setCoordinateInfo(expr.coordinates());
458 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutComplex, expr);
459 0 : copyMiscellaneous (*pOutComplex, *(itsImPol->imageInterface()));
460 0 : }
461 :
462 0 : Bool ImagePol::sigmaLinPolPosAng(ImageInterface<Float>*& rtnim, Float clip,
463 : Float sigma, const String& outfile) {
464 0 : Bool rstat(false);
465 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
466 0 : if(itsImPol==0){
467 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
468 0 : << LogIO::POST;
469 0 : return rstat;
470 : }
471 :
472 0 : Bool radians = false;
473 0 : ImageExpr<Float> expr = itsImPol->sigmaLinPolPosAng(radians, clip, sigma);
474 :
475 : // Create output image if needed
476 0 : rstat = copyImage (rtnim, expr, outfile, true);
477 0 : return rstat;
478 0 : }
479 :
480 :
481 : // Fractional linearly polarized intensity
482 0 : Bool ImagePol::fracLinPol(ImageInterface<Float>*& rtnim, Bool debias,
483 : Float clip, Float sigma, const String& outfile) {
484 0 : Bool rstat(false);
485 0 : *itsLog << LogOrigin("imagepol", "fracLinPol(...)");
486 0 : if(itsImPol==0){
487 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
488 0 : << LogIO::POST;
489 0 : return rstat;
490 : }
491 :
492 0 : ImageExpr<Float> expr = itsImPol->fracLinPol(debias, clip, sigma);
493 :
494 : // Create output image
495 0 : rstat = copyImage (rtnim, expr, outfile, true);
496 0 : return rstat;
497 0 : }
498 :
499 :
500 0 : Bool ImagePol::sigmaFracLinPol(ImageInterface<Float>*& rtnim, Float clip,
501 : Float sigma, const String& outfile){
502 0 : Bool rstat(false);
503 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
504 0 : if(itsImPol==0){
505 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
506 0 : << LogIO::POST;
507 0 : return rstat;
508 : }
509 :
510 0 : ImageExpr<Float> expr = itsImPol->sigmaFracLinPol(clip, sigma);
511 :
512 : // Create output image if needed
513 0 : rstat = copyImage (rtnim, expr, outfile, true);
514 0 : return rstat;
515 0 : }
516 :
517 :
518 : // Fractional total polarized intensity
519 0 : Bool ImagePol::fracTotPol(ImageInterface<Float>*& rtnim, Bool debias,
520 : Float clip, Float sigma, const String& outfile) {
521 0 : Bool rstat(false);
522 0 : *itsLog << LogOrigin("imagepol", "fracTotPol(...)");
523 0 : if(itsImPol==0){
524 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
525 0 : << LogIO::POST;
526 0 : return rstat;
527 : }
528 :
529 0 : ImageExpr<Float> expr = itsImPol->fracTotPol(debias, clip, sigma);
530 :
531 : // Create output image if needed
532 0 : rstat = copyImage (rtnim, expr, outfile, true);
533 0 : return rstat;
534 0 : }
535 :
536 :
537 0 : Bool ImagePol::sigmaFracTotPol(ImageInterface<Float>*& rtnim, Float clip,
538 : Float sigma, const String& outfile){
539 0 : Bool rstat(false);
540 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
541 0 : if(itsImPol==0){
542 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
543 0 : << LogIO::POST;
544 0 : return rstat;
545 : }
546 :
547 0 : ImageExpr<Float> expr = itsImPol->sigmaFracTotPol(clip, sigma);
548 :
549 : // Create output image if needed
550 0 : rstat = copyImage (rtnim, expr, outfile, true);
551 0 : return rstat;
552 0 : }
553 :
554 :
555 : // Depolarization ratio
556 0 : Bool ImagePol::depolarizationRatio (ImageInterface<Float>*& rtnim,
557 : const String& infile,
558 : Bool debias, Float clip,
559 : Float sigma, const String& outfile) {
560 0 : Bool rstat(false);
561 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
562 0 : if(itsImPol==0){
563 0 : *itsLog << "No attached image, please use open "
564 0 : << LogIO::EXCEPTION;
565 : }
566 0 : auto imagePointer1 = itsImPol->imageInterface();
567 0 : ImageInterface<Float>* imagePointer2 = 0;
568 0 : ImageUtilities::openImage (imagePointer2, infile);
569 : //
570 : ImageExpr<Float> expr =
571 0 : ImagePolarimetry::depolarizationRatio(*imagePointer1, *imagePointer2,
572 0 : debias, clip, sigma);
573 : //
574 0 : if (imagePointer2) delete imagePointer2;
575 0 : imagePointer2 = 0;
576 :
577 : // Create output image
578 0 : rstat = copyImage (rtnim, expr, outfile, true);
579 :
580 0 : return rstat;
581 0 : }
582 :
583 :
584 0 : Bool ImagePol::sigmaDepolarizationRatio (ImageInterface<Float>*& rtnim,
585 : const String& infile,
586 : Bool debias, Float clip,
587 : Float sigma, const String& outfile) {
588 0 : Bool rstat(false);
589 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
590 0 : if(itsImPol==0){
591 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
592 0 : << LogIO::POST;
593 0 : return rstat;
594 : }
595 : //
596 0 : auto imagePointer1 = itsImPol->imageInterface();
597 : //
598 0 : ImageInterface<Float>* imagePointer2 = 0;
599 0 : ImageUtilities::openImage(imagePointer2, infile);
600 : //
601 : ImageExpr<Float> expr =
602 0 : ImagePolarimetry::sigmaDepolarizationRatio(*imagePointer1,
603 : *imagePointer2,
604 0 : debias, clip, sigma);
605 : //
606 0 : if (imagePointer2) delete imagePointer2;
607 0 : imagePointer2 = 0;
608 :
609 : // Create output image
610 0 : rstat = copyImage (rtnim, expr, outfile, true);
611 0 : return rstat;
612 0 : }
613 :
614 :
615 : // Find Rotation Measure from Fourier method
616 0 : void ImagePol::fourierRotationMeasure(const String& outfile,
617 : const String& outfileAmp,
618 : const String& outfilePA,
619 : const String& outfileReal,
620 : const String& outfileImag,
621 : Bool zeroZeroLag) {
622 :
623 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__, WHERE);
624 0 : if(itsImPol==0){
625 0 : *itsLog <<"No attached image, please use open "
626 0 : << LogIO::EXCEPTION;
627 0 : return;
628 : }
629 0 : if (itsImPol->imageInterface()->imageInfo().hasMultipleBeams()) {
630 0 : *itsLog << "Cannot run " << __FUNCTION__
631 : << " on an image with multiple beams"
632 0 : << LogIO::EXCEPTION;
633 : }
634 :
635 :
636 : // Make output complex image
637 0 : ImageInterface<Complex>* pOutComplex = 0;
638 0 : CoordinateSystem cSysPol;
639 0 : IPosition shapePol = itsImPol->singleStokesShape(cSysPol, Stokes::Plinear);
640 0 : _makeImage (pOutComplex, outfile, cSysPol, shapePol,
641 0 : itsImPol->isMasked(), true);
642 :
643 : // Make output amplitude and position angle images
644 0 : ImageInterface<Float>* pOutAmp = 0;
645 0 : ImageInterface<Float>* pOutPA = 0;
646 0 : makeImage (pOutAmp, outfileAmp, cSysPol, shapePol,
647 0 : itsImPol->isMasked(), false);
648 0 : makeImage (pOutPA, outfilePA, cSysPol, shapePol,
649 0 : itsImPol->isMasked(), false);
650 :
651 : // Make output real and imaginary images
652 0 : ImageInterface<Float>* pOutReal = 0;
653 0 : ImageInterface<Float>* pOutImag = 0;
654 0 : makeImage (pOutReal, outfileReal, cSysPol, shapePol,
655 0 : itsImPol->isMasked(), false);
656 0 : makeImage (pOutImag, outfileImag, cSysPol, shapePol,
657 0 : itsImPol->isMasked(), false);
658 :
659 : // The output complex image will have correct Coordinates, mask, and
660 : // miscellaneous things copied to it
661 0 : itsImPol->fourierRotationMeasure(*pOutComplex, zeroZeroLag);
662 :
663 : // Copy to output
664 0 : auto p = itsImPol->imageInterface();
665 0 : if (pOutAmp!=0) {
666 0 : LatticeExprNode node(abs(*pOutComplex));
667 0 : LatticeExpr<Float> le(node);
668 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutAmp, le);
669 : //
670 0 : pOutAmp->setCoordinateInfo(pOutComplex->coordinates());
671 0 : copyMiscellaneous (*pOutAmp, *p);
672 0 : pOutAmp->setUnits(p->units());
673 0 : fiddleStokesCoordinate(*pOutAmp, Stokes::Plinear);
674 0 : delete pOutAmp;
675 0 : }
676 0 : if (pOutPA!=0) {
677 0 : LatticeExprNode node(pa(imag(*pOutComplex),real(*pOutComplex))); // degrees
678 0 : LatticeExpr<Float> le(node);
679 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutPA, le);
680 : //
681 0 : pOutPA->setCoordinateInfo(pOutComplex->coordinates());
682 0 : copyMiscellaneous (*pOutPA, *p);
683 0 : pOutPA->setUnits("deg");
684 0 : fiddleStokesCoordinate(*pOutPA, Stokes::Pangle);
685 0 : delete pOutPA;
686 0 : }
687 0 : if (pOutReal!=0) {
688 0 : LatticeExprNode node(real(*pOutComplex));
689 0 : LatticeExpr<Float> le(node);
690 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutReal, le);
691 0 : pOutReal->setCoordinateInfo(pOutComplex->coordinates());
692 0 : copyMiscellaneous (*pOutReal, *p);
693 0 : pOutReal->setUnits(p->units());
694 0 : fiddleStokesCoordinate(*pOutReal, Stokes::Plinear); // Not strictly correct
695 0 : delete pOutReal;
696 0 : }
697 0 : if (pOutImag!=0) {
698 0 : LatticeExprNode node(imag(*pOutComplex));
699 0 : LatticeExpr<Float> le(node);
700 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutImag, le);
701 0 : pOutImag->setCoordinateInfo(pOutComplex->coordinates());
702 0 : copyMiscellaneous (*pOutImag, *p);
703 0 : pOutImag->setUnits(p->units());
704 0 : fiddleStokesCoordinate(*pOutImag, Stokes::Plinear); // Not strictly correct
705 0 : delete pOutImag;
706 0 : }
707 0 : }
708 :
709 0 : void ImagePol::rotationMeasure(
710 : const String& outRM, const String& outRMErr,
711 : const String& outPA0, const String& outPA0Err,
712 : const String& outNTurns, const String& outChiSq,
713 : Int axis2, Float sigmaQU, Float rmFg,
714 : Float rmMax, Float maxPaErr
715 : ) {
716 : // Find Rotation Measure from traditional method
717 0 : *itsLog << LogOrigin("ImagePol", __func__);
718 0 : if(itsImPol==0) {
719 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
720 0 : << LogIO::POST;
721 0 : return;
722 : }
723 : // Make output images. Give them all a mask as we don't know if output
724 : // will be masked or not.
725 0 : CoordinateSystem cSysRM;
726 : Int fAxis, sAxis;
727 0 : Int axis = axis2;
728 0 : IPosition shapeRM = itsImPol->rotationMeasureShape(
729 0 : cSysRM, fAxis, sAxis, *itsLog, axis
730 0 : );
731 0 : ImageInterface<Float>* pRMOut = 0;
732 0 : ImageInterface<Float>* pRMOutErr = 0;
733 0 : makeImage (pRMOut, outRM, cSysRM, shapeRM, true, false);
734 : // manage naked pointers so exception throwing doesn't leave open images
735 0 : std::unique_ptr<ImageInterface<Float> > managed5(pRMOut);
736 0 : makeImage (pRMOutErr, outRMErr, cSysRM, shapeRM, true, false);
737 0 : std::unique_ptr<ImageInterface<Float> > managed6(pRMOutErr);
738 0 : CoordinateSystem cSysPA;
739 0 : IPosition shapePA = itsImPol->positionAngleShape(
740 0 : cSysPA, fAxis, sAxis, *itsLog, axis
741 0 : );
742 0 : ImageInterface<Float>* pPA0Out = 0;
743 0 : ImageInterface<Float>* pPA0OutErr = 0;
744 0 : makeImage (pPA0Out, outPA0, cSysPA, shapePA, true, false);
745 0 : std::unique_ptr<ImageInterface<Float> > managed1(pPA0Out);
746 0 : makeImage (pPA0OutErr, outPA0Err, cSysPA, shapePA, true, false);
747 0 : std::unique_ptr<ImageInterface<Float> > managed2(pPA0OutErr);
748 0 : ImageInterface<Float>* pNTurnsOut = 0;
749 0 : makeImage (pNTurnsOut, outNTurns, cSysRM, shapeRM, true, false);
750 0 : std::unique_ptr<ImageInterface<Float> > managed3(pNTurnsOut);
751 0 : ImageInterface<Float>* pChiSqOut = 0;
752 0 : makeImage (pChiSqOut, outChiSq, cSysRM, shapeRM, true, false);
753 0 : std::unique_ptr<ImageInterface<Float> > managed4(pChiSqOut);
754 0 : itsImPol->rotationMeasure(
755 : pRMOut, pRMOutErr, pPA0Out, pPA0OutErr,
756 : pNTurnsOut, pChiSqOut,
757 : axis, rmMax, maxPaErr,
758 : sigmaQU, rmFg, true
759 : );
760 0 : auto p = itsImPol->imageInterface();
761 0 : if (pRMOut) {
762 0 : copyMiscellaneous (*pRMOut, *p);
763 : }
764 0 : if (pRMOutErr) {
765 0 : copyMiscellaneous (*pRMOutErr, *p);
766 : }
767 0 : if (pPA0Out) {
768 0 : copyMiscellaneous (*pPA0Out, *p);
769 : }
770 0 : if (pPA0OutErr) {
771 0 : copyMiscellaneous (*pPA0OutErr, *p);
772 : }
773 0 : if (pNTurnsOut) {
774 0 : copyMiscellaneous (*pNTurnsOut, *p);
775 : }
776 0 : if (pChiSqOut) {
777 0 : copyMiscellaneous (*pChiSqOut, *p);
778 : }
779 0 : }
780 :
781 :
782 : // Make a complex image
783 0 : void ImagePol::makeComplex (const String& outfile, const String& real,
784 : const String& imag, const String& amp,
785 : const String& phase) {
786 :
787 0 : *itsLog << LogOrigin("imagepol", __FUNCTION__);
788 0 : if(itsImPol==0){
789 0 : *itsLog << LogIO::SEVERE <<"No attached image, please use open "
790 0 : << LogIO::POST;
791 0 : return;
792 : }
793 :
794 : // Checks
795 0 : if (outfile.empty()) {
796 0 : *itsLog << "You must give the output complex image file name"
797 0 : << LogIO::EXCEPTION;
798 : }
799 :
800 0 : Bool doRI = !real.empty() && !imag.empty();
801 0 : Bool doAP = !amp.empty() && !phase.empty();
802 0 : if (doRI && doAP) {
803 0 : *itsLog << "You must give either real and imaginary, or amplitude and phase; Not all four of them"
804 0 : << LogIO::EXCEPTION;
805 : }
806 :
807 : // Make output complex image
808 0 : ImageInterface<Complex>* pOutComplex = 0;
809 0 : CoordinateSystem cSysPol;
810 0 : IPosition shapePol = itsImPol->singleStokesShape(cSysPol, Stokes::I);
811 0 : _makeImage (pOutComplex, outfile, cSysPol, shapePol,
812 0 : itsImPol->isMasked(), false);
813 :
814 : // Make Expression. Only limited Stokes types that make sense are allowed.
815 0 : ImageExpr<Complex>* pExpr = 0;
816 0 : if (doRI) {
817 0 : PagedImage<Float> rr(real);
818 0 : Stokes::StokesTypes tR = stokesType(rr.coordinates());
819 : //
820 0 : PagedImage<Float> ii(imag);
821 0 : Stokes::StokesTypes tI = stokesType(ii.coordinates());
822 : //
823 0 : if (tR!=Stokes::Q || tI!=Stokes::U) {
824 0 : *itsLog << "The real and imaginary components must be Q and U, respectively"
825 0 : << LogIO::EXCEPTION;
826 : }
827 0 : Stokes::StokesTypes typeOut = Stokes::Plinear;
828 : //
829 0 : LatticeExprNode node(formComplex(rr,ii));
830 0 : LatticeExpr<Complex> le(node);
831 0 : pExpr = new ImageExpr<Complex>(le, String("ComplexLinearPolarization"));
832 0 : fiddleStokesCoordinate(*pExpr, typeOut);
833 0 : } else {
834 0 : PagedImage<Float> aa(amp);
835 0 : Stokes::StokesTypes tA = stokesType(aa.coordinates());
836 : //
837 0 : PagedImage<Float> pp(phase);
838 0 : Stokes::StokesTypes tP = stokesType(pp.coordinates());
839 : //
840 0 : if (tP!=Stokes::Pangle) {
841 0 : *itsLog << "The phase must be of Stokes type position angle (Pangle)"
842 0 : << LogIO::EXCEPTION;
843 : }
844 0 : Float fac = 1.0;
845 0 : String units = pp.units().getName();
846 0 : if (units.contains(String("deg"))) {
847 0 : fac = C::pi / 180.0;
848 0 : } else if (units.contains(String("rad"))) {
849 : } else {
850 0 : *itsLog << LogIO::WARN
851 : << "Units for phase are neither radians nor degrees. radians assumed"
852 0 : << LogIO::POST;
853 : }
854 : //
855 0 : Stokes::StokesTypes typeOut = Stokes::Undefined;
856 0 : String exprName("");
857 0 : if (tA==Stokes::Ptotal) {
858 0 : typeOut = Stokes::Ptotal;
859 0 : exprName = String("ComplexTotalPolarization");
860 0 : } else if (tA==Stokes::Plinear) {
861 0 : typeOut = Stokes::Plinear;
862 0 : exprName = String("ComplexLinearPolarization");
863 0 : } else if (tA==Stokes::PFtotal) {
864 0 : typeOut = Stokes::PFtotal;
865 0 : exprName = String("ComplexFractionalTotalPolarization");
866 0 : } else if (tA==Stokes::PFlinear) {
867 0 : typeOut = Stokes::PFlinear;
868 0 : exprName = String("ComplexFractionalLinearPolarization");
869 : } else {
870 0 : *itsLog << "Cannot form Complex image for this amplitude image"
871 0 : << endl;
872 0 : *itsLog << "Expect linear, total, or fractional polarization"
873 0 : << LogIO::EXCEPTION;
874 : }
875 : //
876 0 : LatticeExprNode node0(2.0*fac*pp);
877 0 : LatticeExprNode node(formComplex(aa*cos(node0),aa*sin(node0)));
878 0 : LatticeExpr<Complex> le(node);
879 0 : pExpr = new ImageExpr<Complex>(le, exprName);
880 0 : fiddleStokesCoordinate(*pExpr, typeOut);
881 0 : }
882 :
883 : // Copy to output
884 0 : pOutComplex->setCoordinateInfo(pExpr->coordinates());
885 0 : LatticeUtilities::copyDataAndMask(*itsLog, *pOutComplex, *pExpr);
886 : //
887 0 : auto p = itsImPol->imageInterface();
888 0 : copyMiscellaneous (*pOutComplex, *p);
889 : //
890 0 : delete pExpr; pExpr = 0;
891 0 : delete pOutComplex; pOutComplex = 0;
892 0 : }
893 :
894 :
895 : // Private functions
896 :
897 0 : Bool ImagePol::copyImage(ImageInterface<Float>*& out,
898 : const ImageInterface<Float>& in,
899 : const String& outfile, Bool overwrite){
900 :
901 : // if no outfile, just make out image from the input image
902 0 : if (outfile.empty()){
903 0 : out = in.cloneII();
904 0 : return true;
905 : }
906 :
907 : // The user wants to write the image out; verify file
908 0 : if (!overwrite) {
909 0 : NewFile validfile;
910 0 : String errmsg;
911 0 : if (!validfile.valueOK(outfile, errmsg)) {
912 0 : *itsLog << errmsg << LogIO::EXCEPTION;
913 : }
914 0 : }
915 :
916 : // Create output image
917 0 : out= new PagedImage<Float>(in.shape(), in.coordinates(), outfile);
918 0 : if (out == 0) {
919 0 : *itsLog << "Failed to create PagedImage" << LogIO::EXCEPTION;
920 : } else {
921 0 : *itsLog << LogIO::NORMAL << "Creating image '" << outfile
922 0 : << "' of shape " << out->shape() << LogIO::POST;
923 : }
924 :
925 : // Make mask
926 0 : if (in.isMasked()) makeMask(*out, false);
927 :
928 : // Copy stuff
929 0 : LatticeUtilities::copyDataAndMask (*itsLog, *out, in);
930 0 : ImageUtilities::copyMiscellaneous (*out, in);
931 :
932 0 : return true;
933 :
934 : }
935 :
936 0 : Bool ImagePol::makeMask(ImageInterface<Float>& out, Bool init){
937 :
938 0 : if (out.canDefineRegion()) {
939 :
940 : // Generate mask name if not given
941 0 : String maskName = out.makeUniqueRegionName(String("mask"), 0);
942 :
943 : // Make the mask if it does not exist
944 0 : if (!out.hasRegion (maskName, RegionHandler::Masks)) {
945 0 : out.makeMask (maskName, true, true, init, true);
946 : /* if (init) {
947 : *itsLog << LogIO::NORMAL << "Created and initialized mask `" << maskName << "'" << LogIO::POST;
948 : } else {
949 : *itsLog << LogIO::NORMAL << "Created mask `" << maskName << "'" << LogIO::POST;
950 : }*/
951 : }
952 0 : return true;
953 0 : } else {
954 0 : *itsLog << LogIO::WARN
955 0 : << "Cannot make requested mask for this type of image" << endl;
956 0 : return false;
957 : }
958 :
959 : }
960 0 : Bool ImagePol::makeMask(ImageInterface<Complex>& out, Bool init){
961 :
962 0 : if (out.canDefineRegion()) {
963 :
964 : // Generate mask name if not given
965 0 : String maskName = out.makeUniqueRegionName(String("mask"), 0);
966 :
967 : // Make the mask if it does not exist
968 0 : if (!out.hasRegion (maskName, RegionHandler::Masks)) {
969 0 : out.makeMask (maskName, true, true, init, true);
970 : /* if (init) {
971 : *itsLog << LogIO::NORMAL << "Created and initialized mask `" << maskName << "'" << LogIO::POST;
972 : } else {
973 : *itsLog << LogIO::NORMAL << "Created mask `" << maskName << "'" << LogIO::POST;
974 : }*/
975 : }
976 0 : return true;
977 0 : } else {
978 0 : *itsLog << LogIO::WARN
979 0 : << "Cannot make requested mask for this type of image" << endl;
980 0 : return false;
981 : }
982 :
983 : }
984 :
985 :
986 0 : Bool ImagePol::makeImage(ImageInterface<Float>*& out,
987 : const String& outfile, const CoordinateSystem& cSys,
988 : const IPosition& shape, Bool isMasked,
989 : Bool tempAllowed) {
990 : // Verify outfile
991 0 : if (outfile.empty()) {
992 0 : if (!tempAllowed) return false;
993 : }
994 : // else {
995 : // NewFile validfile;
996 : // String errmsg;
997 : // if (!validfile.valueOK(outfile, errmsg)) {
998 : // *itsLog << errmsg << LogIO::EXCEPTION;
999 : // }
1000 : //}
1001 :
1002 :
1003 0 : uInt ndim = shape.nelements();
1004 0 : if (ndim != cSys.nPixelAxes()) {
1005 0 : *itsLog << "Supplied CoordinateSystem and image shape are inconsistent"
1006 0 : << LogIO::EXCEPTION;
1007 : }
1008 0 : if (outfile.empty()) {
1009 0 : out = new TempImage<Float>(shape, cSys);
1010 0 : if (out == 0) {
1011 0 : *itsLog << "Failed to create TempImage" << LogIO::EXCEPTION;
1012 : }
1013 0 : *itsLog << LogIO::NORMAL << "Creating (temp)image of shape "
1014 0 : << out->shape() << LogIO::POST;
1015 : } else {
1016 0 : out = new PagedImage<Float>(shape, cSys, outfile);
1017 0 : if (out == 0) {
1018 0 : *itsLog << "Failed to create PagedImage" << LogIO::EXCEPTION;
1019 : }
1020 0 : *itsLog << LogIO::NORMAL << "Creating image '" << outfile
1021 0 : << "' of shape " << out->shape() << LogIO::POST;
1022 : }
1023 : //
1024 0 : if (isMasked) {
1025 0 : makeMask(*out, true);
1026 : }
1027 :
1028 0 : return true;
1029 : }
1030 :
1031 0 : Bool ImagePol::_makeImage(
1032 : ImageInterface<Complex>*& out, const String& outfile,
1033 : const CoordinateSystem& cSys, const IPosition& shape, Bool isMasked,
1034 : Bool tempAllowed
1035 : ) {
1036 0 : const auto ndim = shape.nelements();
1037 0 : if (ndim != cSys.nPixelAxes()) {
1038 0 : *itsLog << "Supplied CoordinateSystem and image shape are inconsistent"
1039 0 : << LogIO::EXCEPTION;
1040 : }
1041 0 : if (outfile.empty()) {
1042 0 : if (tempAllowed) {
1043 0 : out = new TempImage<Complex>(shape, cSys);
1044 0 : if (! out) {
1045 0 : *itsLog << "Failed to create TempImage" << LogIO::EXCEPTION;
1046 : }
1047 0 : *itsLog << LogIO::NORMAL << "Creating (temp)image of shape "
1048 0 : << out->shape() << LogIO::POST;
1049 : }
1050 : else {
1051 0 : return false;
1052 : }
1053 : }
1054 : else {
1055 0 : out = new PagedImage<Complex>(shape, cSys, outfile);
1056 0 : if (! out) {
1057 0 : *itsLog << "Failed to create PagedImage" << LogIO::EXCEPTION;
1058 : }
1059 0 : *itsLog << LogIO::NORMAL << "Creating image '" << outfile
1060 0 : << "' of shape " << out->shape() << LogIO::POST;
1061 : }
1062 0 : if (isMasked) {
1063 0 : makeMask(*out, true);
1064 : }
1065 0 : return true;
1066 : }
1067 :
1068 0 : SPIIC ImagePol::_makeImage(
1069 : const String& outfile, const CoordinateSystem& cSys,
1070 : const IPosition& shape, bool isMasked,
1071 : bool tempAllowed
1072 : ) {
1073 0 : ImageInterface<Complex>* out = NULL;
1074 0 : const auto res = _makeImage(
1075 : out, outfile, cSys, shape, isMasked, tempAllowed
1076 : );
1077 0 : if (res) {
1078 0 : return shared_ptr<ImageInterface<Complex>>(out);
1079 : }
1080 : else {
1081 0 : if (out) {
1082 0 : delete out;
1083 : }
1084 0 : return shared_ptr<ImageInterface<Complex>>();
1085 : }
1086 : }
1087 :
1088 0 : void ImagePol::copyMiscellaneous (ImageInterface<Complex>& out,
1089 : const ImageInterface<Float>& in)
1090 : {
1091 0 : out.setMiscInfo(in.miscInfo());
1092 0 : out.appendLog(in.logger());
1093 0 : }
1094 :
1095 0 : void ImagePol::copyMiscellaneous (ImageInterface<Float>& out,
1096 : const ImageInterface<Float>& in)
1097 : {
1098 0 : out.setMiscInfo(in.miscInfo());
1099 0 : out.appendLog(in.logger());
1100 0 : }
1101 :
1102 :
1103 0 : void ImagePol::fiddleStokesCoordinate(ImageInterface<Float>& ie,
1104 : Stokes::StokesTypes type)
1105 : {
1106 0 : CoordinateSystem cSys = ie.coordinates();
1107 : //
1108 0 : Int afterCoord = -1;
1109 0 : Int iStokes = cSys.findCoordinate(Coordinate::STOKES, afterCoord);
1110 : //
1111 0 : Vector<Int> which(1);
1112 0 : which(0) = Int(type);
1113 0 : StokesCoordinate stokes(which);
1114 0 : cSys.replaceCoordinate(stokes, iStokes);
1115 0 : ie.setCoordinateInfo(cSys);
1116 0 : }
1117 :
1118 0 : void ImagePol::fiddleStokesCoordinate(ImageInterface<Complex>& ie,
1119 : Stokes::StokesTypes type)
1120 : {
1121 0 : CoordinateSystem cSys = ie.coordinates();
1122 : //
1123 0 : Int afterCoord = -1;
1124 0 : Int iStokes = cSys.findCoordinate(Coordinate::STOKES, afterCoord);
1125 : //
1126 0 : Vector<Int> which(1);
1127 0 : which(0) = Int(type);
1128 0 : StokesCoordinate stokes(which);
1129 0 : cSys.replaceCoordinate(stokes, iStokes);
1130 0 : ie.setCoordinateInfo(cSys);
1131 0 : }
1132 :
1133 :
1134 0 : Bool ImagePol::makeIQUVImage (ImageInterface<Float>*& pImOut,
1135 : const String& outfile,
1136 : Double sigma, Double pa0,
1137 : const Vector<Float>& rm,
1138 : const IPosition& shape,
1139 : Double f0, Double dF)
1140 : //
1141 : // Must be 4D
1142 : //
1143 : {
1144 0 : AlwaysAssert(shape.nelements()==4,AipsError);
1145 0 : AlwaysAssert(shape(2)==4,AipsError);
1146 : //
1147 0 : CoordinateSystem cSys;
1148 0 : CoordinateUtil::addDirAxes(cSys);
1149 : //
1150 0 : Vector<Int> whichStokes(4);
1151 0 : whichStokes(0) = Stokes::I;
1152 0 : whichStokes(1) = Stokes::Q;
1153 0 : whichStokes(2) = Stokes::U;
1154 0 : whichStokes(3) = Stokes::V;
1155 0 : StokesCoordinate stokesCoord(whichStokes);
1156 0 : cSys.addCoordinate(stokesCoord);
1157 : //
1158 0 : const Int nchan = shape(3);
1159 0 : Double df = dF / nchan;
1160 0 : Double refpix = 0.0;
1161 0 : SpectralCoordinate spectCoord(MFrequency::TOPO, f0, df, refpix, f0);
1162 0 : cSys.addCoordinate(spectCoord);
1163 :
1164 : // Centre reference pixel
1165 0 : centreRefPix (cSys, shape);
1166 :
1167 : // Make image
1168 0 : makeImage (pImOut, outfile, cSys, shape, false, true);
1169 : //
1170 0 : uInt stokesAxis = 2;
1171 0 : uInt spectralAxis = 3;
1172 :
1173 : // Fill image with I, Q, U and V.
1174 0 : fillIQUV (*pImOut, stokesAxis, spectralAxis, rm, pa0);
1175 :
1176 : // Add noise
1177 0 : Array<Float> slice = pImOut->get();
1178 0 : Float maxVal = max(slice);
1179 0 : Float t = sigma * maxVal;
1180 0 : *itsLog << LogIO::NORMAL << "Using sigma = "
1181 0 : << t << LogIO::POST;
1182 0 : MLCG gen;
1183 0 : Normal noiseGen(&gen, 0.0, t*t);
1184 0 : addNoise(slice, noiseGen);
1185 0 : pImOut->put(slice);
1186 0 : return true;
1187 0 : }
1188 :
1189 0 : Bool ImagePol::fillIQUV (ImageInterface<Float>& im, uInt stokesAxis,
1190 : uInt spectralAxis, const Vector<Float>& rm,
1191 : Float pa0)
1192 : //
1193 : // Image must be 4D
1194 : //
1195 : {
1196 :
1197 : // Find spectral coordinate
1198 0 : const CoordinateSystem& cSys = im.coordinates();
1199 : Int spectralCoord, iDum;
1200 0 : cSys.findPixelAxis(spectralCoord, iDum, spectralAxis);
1201 0 : const SpectralCoordinate& sC = cSys.spectralCoordinate(spectralCoord);
1202 : //
1203 0 : IPosition shape = im.shape();
1204 0 : Double c = QC::c( ).getValue(Unit("m/s"));
1205 : Double lambdasq;
1206 0 : MFrequency freq;
1207 0 : IPosition blc(4,0);
1208 0 : IPosition trc(shape-1);
1209 : //
1210 0 : Double ii = 2.0; // arbitrary
1211 0 : Double vv = 0.05 * ii; // arbitrary
1212 0 : const Int n = shape(3);
1213 0 : const uInt nRM = rm.nelements();
1214 0 : for (Int i=0; i<n; i++) {
1215 0 : if (!sC.toWorld(freq, Double(i))) {
1216 0 : *itsLog << sC.errorMessage() << LogIO::EXCEPTION;
1217 : }
1218 0 : Double fac = c / freq.get(Unit("Hz")).getValue();
1219 0 : lambdasq = fac*fac;
1220 : //
1221 0 : Double chi = rm(0)*lambdasq + pa0;
1222 0 : Double q = cos(2*chi);
1223 0 : Double u = sin(2*chi);
1224 : //
1225 0 : if (nRM > 1) {
1226 0 : for (uInt j=1; j<nRM; j++) {
1227 0 : chi = rm(j)*lambdasq + pa0;
1228 0 : q += cos(2*chi);
1229 0 : u += sin(2*chi);
1230 : }
1231 : }
1232 0 : q = q / Double(nRM);
1233 0 : u = u / Double(nRM);
1234 : //
1235 0 : blc(spectralAxis) = i; // channel
1236 0 : trc(spectralAxis) = i;
1237 : {
1238 0 : blc(stokesAxis) = 1; // Q
1239 0 : trc(stokesAxis) = 1;
1240 0 : Slicer sl(blc, trc, Slicer::endIsLast);
1241 0 : SubImage<Float> subImage(im, sl, true);
1242 0 : subImage.set(q);
1243 0 : }
1244 : {
1245 0 : blc(stokesAxis) = 2; // U
1246 0 : trc(stokesAxis) = 2;
1247 0 : Slicer sl(blc, trc, Slicer::endIsLast);
1248 0 : SubImage<Float> subImage(im, sl, true);
1249 0 : subImage.set(u);
1250 0 : }
1251 : }
1252 : //
1253 0 : blc(spectralAxis) = 0;
1254 0 : trc(spectralAxis) = n-1;
1255 : {
1256 0 : blc(stokesAxis) = 0; // I
1257 0 : trc(stokesAxis) = 0;
1258 0 : Slicer sl(blc, trc, Slicer::endIsLast);
1259 0 : SubImage<Float> subImage(im, sl, true);
1260 0 : subImage.set(ii);
1261 0 : }
1262 : {
1263 0 : blc(stokesAxis) = 3; // V
1264 0 : trc(stokesAxis) = 3;
1265 0 : Slicer sl(blc, trc, Slicer::endIsLast);
1266 0 : SubImage<Float> subImage(im, sl, true);
1267 0 : subImage.set(vv);
1268 0 : }
1269 0 : return true;
1270 :
1271 0 : }
1272 :
1273 0 : void ImagePol::addNoise (Array<Float>& slice, Normal& noiseGen)
1274 : {
1275 : Bool deleteIt;
1276 0 : Float* p = slice.getStorage(deleteIt);
1277 0 : for (uInt i=0; i<slice.nelements(); i++) {
1278 0 : p[i] += noiseGen();
1279 : }
1280 0 : slice.putStorage(p, deleteIt);
1281 0 : }
1282 :
1283 0 : void ImagePol::centreRefPix (CoordinateSystem& cSys, const IPosition& shape)
1284 : {
1285 0 : Int after = -1;
1286 0 : Int iS = cSys.findCoordinate(Coordinate::STOKES, after);
1287 0 : Int sP = -1;
1288 0 : if (iS>=0) {
1289 0 : Vector<Int> pixelAxes = cSys.pixelAxes(iS);
1290 0 : sP = pixelAxes(0);
1291 0 : }
1292 0 : Vector<Double> refPix = cSys.referencePixel();
1293 0 : for (Int i=0; i<Int(refPix.nelements()); i++) {
1294 0 : if (i!=sP) refPix(i) = Double(shape(i) / 2);
1295 : }
1296 0 : cSys.setReferencePixel(refPix);
1297 0 : }
1298 :
1299 :
1300 0 : Stokes::StokesTypes ImagePol::stokesType(const CoordinateSystem& cSys)
1301 : {
1302 0 : Stokes::StokesTypes type = Stokes::Undefined;
1303 0 : Int afterCoord = -1;
1304 0 : Int iStokes = cSys.findCoordinate(Coordinate::STOKES, afterCoord);
1305 0 : if (iStokes >=0) {
1306 0 : Vector<Int> which = cSys.stokesCoordinate(iStokes).stokes();
1307 0 : if (which.nelements()>1) {
1308 0 : *itsLog << "Stokes axis must be of length unity" << LogIO::EXCEPTION;
1309 : } else {
1310 0 : type = Stokes::type(which(0));
1311 : }
1312 0 : } else {
1313 0 : *itsLog << "No StokesCoordinate" << LogIO::EXCEPTION;
1314 : }
1315 0 : return type;
1316 : }
1317 :
1318 :
1319 : } // end of casa namespace
|