Line data Source code
1 : //# Imager.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 <casacore/casa/iostream.h>
30 : #include <synthesis/MeasurementEquations/Imager.h>
31 : #include <synthesis/MeasurementComponents/EPJones.h>
32 : #include <synthesis/TransformMachines/VisModelData.h>
33 :
34 : #include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
35 :
36 : #include <casacore/casa/Arrays/Matrix.h>
37 : #include <casacore/casa/Arrays/ArrayMath.h>
38 : #include <casacore/casa/Arrays/ArrayLogical.h>
39 :
40 : #include <casacore/casa/Logging.h>
41 : #include <casacore/casa/Logging/LogIO.h>
42 : #include <casacore/casa/Logging/LogMessage.h>
43 :
44 : #include <casacore/casa/OS/DirectoryIterator.h>
45 : #include <casacore/casa/OS/File.h>
46 : #include <casacore/casa/OS/Path.h>
47 :
48 : #include <casacore/casa/OS/HostInfo.h>
49 : #include <casacore/tables/Tables/RefRows.h>
50 : #include <casacore/tables/Tables/Table.h>
51 : #include <casacore/tables/Tables/TableUtil.h>
52 : #include <casacore/tables/Tables/SetupNewTab.h>
53 : #include <casacore/tables/TaQL/TableParse.h>
54 : #include <casacore/tables/Tables/TableRecord.h>
55 : #include <casacore/tables/Tables/TableDesc.h>
56 : #include <casacore/tables/Tables/TableLock.h>
57 : #include <casacore/tables/TaQL/ExprNode.h>
58 :
59 : #include <casacore/casa/BasicSL/String.h>
60 : #include <casacore/casa/Utilities/Assert.h>
61 : #include <casacore/casa/Utilities/Fallible.h>
62 : #include <casacore/casa/Utilities/CompositeNumber.h>
63 :
64 : #include <casacore/casa/BasicSL/Constants.h>
65 : #include <casacore/casa/Utilities/Regex.h>
66 :
67 : #include <casacore/casa/Logging/LogSink.h>
68 : #include <casacore/casa/Logging/LogMessage.h>
69 :
70 : #include <casacore/casa/Arrays/ArrayMath.h>
71 : #include <casacore/casa/Arrays/Slice.h>
72 : #include <casacore/images/Images/ImageExpr.h>
73 : #include <imageanalysis/ImageAnalysis/ImagePolarimetry.h>
74 : #include <synthesis/MeasurementEquations/ClarkCleanProgress.h>
75 : #include <casacore/lattices/LatticeMath/LatticeCleanProgress.h>
76 : #include <msvis/MSVis/MSUtil.h>
77 : #include <msvis/MSVis/VisSet.h>
78 : #include <msvis/MSVis/VisSetUtil.h>
79 : #include <msvis/MSVis/VisImagingWeight.h>
80 : /////////#include <msvis/MSVis/VisBufferAsync.h>
81 :
82 : // Disabling Imager::correct() (gmoellen 06Nov20)
83 : //#include <synthesis/MeasurementComponents/TimeVarVisJones.h>
84 :
85 : #include <casacore/measures/Measures/Stokes.h>
86 : #include <casacore/casa/Quanta/UnitMap.h>
87 : #include <casacore/casa/Quanta/UnitVal.h>
88 : #include <casacore/casa/Quanta/MVAngle.h>
89 : #include <casacore/measures/Measures/MDirection.h>
90 : #include <casacore/measures/Measures/MPosition.h>
91 : #include <casacore/casa/Quanta/MVEpoch.h>
92 : #include <casacore/casa/Quanta/MVTime.h>
93 : #include <casacore/measures/Measures/MEpoch.h>
94 : #include <casacore/measures/Measures/MeasTable.h>
95 :
96 : #include <casacore/ms/MeasurementSets/MeasurementSet.h>
97 : #include <casacore/ms/MeasurementSets/MSColumns.h>
98 : #include <casacore/ms/MSSel/MSSelection.h>
99 : #include <casacore/ms/MSSel/MSSelectionTools.h>
100 : #include <casacore/ms/MSSel/MSDataDescIndex.h>
101 : #include <casacore/ms/MeasurementSets/MSDopplerUtil.h>
102 : #include <casacore/ms/MSSel/MSSourceIndex.h>
103 : #include <casacore/ms/MSOper/MSSummary.h>
104 : #include <synthesis/MeasurementEquations/CubeSkyEquation.h>
105 : #include <synthesis/MeasurementEquations/Feather.h>
106 : #include <synthesis/MeasurementComponents/ImageSkyModel.h>
107 : #include <synthesis/MeasurementComponents/CEMemImageSkyModel.h>
108 : #include <synthesis/MeasurementComponents/MFCEMemImageSkyModel.h>
109 : #include <synthesis/MeasurementComponents/MFCleanImageSkyModel.h>
110 : #include <synthesis/MeasurementComponents/CSCleanImageSkyModel.h>
111 : #include <synthesis/MeasurementComponents/MFMSCleanImageSkyModel.h>
112 : #include <synthesis/MeasurementComponents/HogbomCleanImageSkyModel.h>
113 : #include <synthesis/MeasurementComponents/MSCleanImageSkyModel.h>
114 : #include <synthesis/MeasurementComponents/NNLSImageSkyModel.h>
115 : #include <synthesis/MeasurementComponents/WBCleanImageSkyModel.h>
116 : #include <synthesis/MeasurementComponents/GridBoth.h>
117 : #include <synthesis/TransformMachines/SetJyGridFT.h>
118 : #include <synthesis/TransformMachines/MosaicFT.h>
119 : #include <synthesis/TransformMachines/WProjectFT.h>
120 : #include <synthesis/MeasurementComponents/nPBWProjectFT.h>
121 : #include <synthesis/MeasurementComponents/PBMosaicFT.h>
122 : #include <synthesis/TransformMachines/PBMath.h>
123 : #include <synthesis/TransformMachines/SimpleComponentFTMachine.h>
124 : #include <synthesis/TransformMachines/VPSkyJones.h>
125 : #include <synthesis/TransformMachines/SynthesisError.h>
126 : #include <synthesis/TransformMachines/HetArrayConvFunc.h>
127 :
128 : #include <synthesis/DataSampling/SynDataSampling.h>
129 : #include <synthesis/DataSampling/SDDataSampling.h>
130 : #include <synthesis/DataSampling/ImageDataSampling.h>
131 :
132 : #include <casacore/lattices/LRegions/LattRegionHolder.h>
133 : #include <casacore/lattices/Lattices/TiledLineStepper.h>
134 : #include <casacore/lattices/Lattices/LatticeIterator.h>
135 : #include <casacore/lattices/LEL/LatticeExpr.h>
136 : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
137 : #include <casacore/lattices/LRegions/LCEllipsoid.h>
138 : #include <casacore/lattices/LRegions/LCRegion.h>
139 : #include <casacore/lattices/LRegions/LCBox.h>
140 : #include <casacore/lattices/LRegions/LCIntersection.h>
141 : #include <casacore/lattices/LRegions/LCUnion.h>
142 : #include <casacore/lattices/LRegions/LCExtension.h>
143 :
144 : #include <casacore/images/Images/ImageRegrid.h>
145 : #include <casacore/images/Regions/ImageRegion.h>
146 : #include <casacore/images/Regions/RegionManager.h>
147 : #include <casacore/images/Regions/WCBox.h>
148 : #include <casacore/images/Regions/WCUnion.h>
149 : #include <casacore/images/Regions/WCIntersection.h>
150 : #include <synthesis/TransformMachines/PBMath.h>
151 : #include <casacore/images/Images/PagedImage.h>
152 : #include <casacore/images/Images/ImageInfo.h>
153 : #include <casacore/images/Images/SubImage.h>
154 : #include <casacore/images/Images/ImageUtilities.h>
155 : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
156 : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
157 : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
158 : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
159 : #include <casacore/coordinates/Coordinates/Projection.h>
160 : #include <casacore/coordinates/Coordinates/ObsInfo.h>
161 :
162 : #include <components/ComponentModels/ComponentList.h>
163 : #include <components/ComponentModels/ConstantSpectrum.h>
164 : #include <components/ComponentModels/SpectralIndex.h>
165 : #include <components/ComponentModels/TabularSpectrum.h>
166 : #include <components/ComponentModels/Flux.h>
167 : #include <components/ComponentModels/FluxStandard.h>
168 : #include <components/ComponentModels/PointShape.h>
169 : #include <components/ComponentModels/DiskShape.h>
170 :
171 : #ifdef USE_GRPC
172 : #include <synthesis/ImagerObjects/grpcInteractiveClean.h>
173 : #endif
174 :
175 : #include <casacore/casa/OS/HostInfo.h>
176 :
177 : #include <components/ComponentModels/ComponentList.h>
178 :
179 : #include <casacore/measures/Measures/UVWMachine.h>
180 :
181 : #include <casacore/casa/sstream.h>
182 :
183 : #include <sys/types.h>
184 : #include <unistd.h>
185 : #ifdef _OPENMP
186 : #include <omp.h>
187 : #endif
188 : using namespace std;
189 :
190 : using namespace casacore;
191 : namespace casa { //# NAMESPACE CASA - BEGIN
192 :
193 50 : Imager::Imager()
194 50 : : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), ft_p(0),
195 50 : cft_p(0), se_p(0),
196 50 : sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false),
197 50 : mssFreqSel_p(), mssChanSel_p(),
198 50 : clean_panel_p(0), image_id_p(0), mask_id_p(0),
199 150 : prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
200 : {
201 50 : ms_p=0;
202 50 : mssel_p=0;
203 50 : lockCounter_p=0;
204 50 : numMS_p=0;
205 50 : defaults();
206 50 : };
207 :
208 :
209 50 : void Imager::defaults()
210 : {
211 :
212 50 : setimaged_p=false;
213 50 : nullSelect_p=false;
214 50 : nx_p=128; ny_p=128; facets_p=1;
215 50 : wprojPlanes_p=-1;
216 50 : mcellx_p=Quantity(1, "arcsec"); mcelly_p=Quantity(1, "arcsec");
217 50 : shiftx_p=Quantity(0.0, "arcsec"); shifty_p=Quantity(0.0, "arcsec");
218 50 : distance_p=Quantity(0.0, "m");
219 50 : stokes_p="I"; npol_p=1;
220 50 : nscales_p=5;
221 50 : ntaylor_p=1;
222 50 : reffreq_p=0.0;
223 50 : useNewMTFT_p=false;
224 50 : scaleMethod_p="nscales";
225 50 : scaleInfoValid_p=false;
226 50 : dataMode_p="none";
227 50 : imageMode_p="MFS";
228 50 : dataNchan_p=0;
229 50 : imageNchan_p=0;
230 50 : doVP_p=false;
231 50 : doDefaultVP_p = true;
232 50 : parAngleInc_p=Quantity(360.,"deg");
233 50 : skyPosThreshold_p=Quantity(180.,"deg");
234 50 : telescope_p="";
235 50 : gridfunction_p="SF";
236 50 : minWeight_p=0.;
237 50 : clipminmax_p=false;
238 50 : doMultiFields_p=false;
239 50 : doWideBand_p=false;
240 50 : multiFields_p=false;
241 : // Use half the machine memory as cache. The user can override
242 : // this via the setoptions function().
243 50 : cache_p=(HostInfo::memoryTotal(true)/8)*1024;
244 : //On 32 bit machines with more than 2G of mem this can become negative
245 : // overriding it to 2 Gb.
246 50 : if(cache_p <=0 )
247 0 : cache_p=2000000000/8;
248 50 : tile_p=16;
249 50 : ftmachine_p="ft";
250 50 : wfGridding_p=false;
251 50 : padding_p=1.2;
252 50 : sdScale_p=1.0;
253 50 : sdWeight_p=1.0;
254 50 : sdConvSupport_p=-1;
255 :
256 50 : doShift_p=false;
257 50 : spectralwindowids_p.resize(1);
258 50 : spectralwindowids_p=0;
259 50 : fieldid_p=0;
260 50 : dataspectralwindowids_p.resize(0);
261 50 : datadescids_p.resize(0);
262 50 : datafieldids_p.resize(0);
263 50 : mImageStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
264 50 : mImageStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
265 50 : mDataStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
266 50 : mDataStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
267 50 : beamValid_p=false;
268 50 : beam_p = ImageBeamSet();
269 50 : images_p.resize(0);
270 50 : masks_p.resize(0);
271 50 : fluxMasks_p.resize(0);
272 50 : residuals_p.resize(0);
273 50 : componentList_p=0;
274 :
275 50 : cyclefactor_p = 1.5;
276 50 : cyclespeedup_p = -1;
277 50 : cyclemaxpsffraction_p = 0.8;
278 50 : stoplargenegatives_p = 2;
279 50 : stoppointmode_p = -1;
280 50 : fluxscale_p.resize(0);
281 50 : scaleType_p = "NONE";
282 50 : minPB_p = 0.1;
283 50 : constPB_p = 0.4;
284 50 : redoSkyModel_p=true;
285 50 : nmodels_p=0;
286 50 : useModelCol_p=false;
287 50 : freqFrameValid_p=false;
288 50 : doTrackSource_p=false;
289 50 : freqInterpMethod_p="nearest";
290 50 : pointingDirCol_p="DIRECTION";
291 50 : logSink_p=LogSink(LogMessage::NORMAL, false);
292 50 : imwgt_p=VisImagingWeight();
293 50 : smallScaleBias_p=0.6;
294 50 : freqFrame_p=MFrequency::LSRK;
295 50 : imageTileVol_p=0;
296 50 : singlePrec_p=false;
297 50 : spwchansels_p.resize();
298 50 : flatnoise_p=true;
299 50 : freqrange_p.resize();
300 50 : numthreads_p=-1;
301 50 : avoidTempLatt_p=false;
302 50 : mssFreqSel_p.resize();
303 50 : mssChanSel_p.resize();
304 50 : projection_p=String("SIN");
305 :
306 50 : }
307 :
308 :
309 0 : Imager::Imager(MeasurementSet& theMS, Bool compress, Bool useModel)
310 0 : : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0),
311 0 : ft_p(0), cft_p(0), se_p(0),
312 0 : sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false),
313 0 : mssFreqSel_p(), mssChanSel_p(),
314 0 : clean_panel_p(0), image_id_p(0), mask_id_p(0), prev_image_id_p(0), prev_mask_id_p(0),
315 0 : projection_p("SIN")
316 :
317 : {
318 :
319 0 : mssel_p=0;
320 0 : ms_p=0;
321 0 : lockCounter_p=0;
322 0 : LogIO os(LogOrigin("Imager", "Imager(MeasurementSet &theMS)", WHERE));
323 0 : if(!open(theMS, compress, useModel)) {
324 0 : os << LogIO::SEVERE << "Open of MeasurementSet failed" << LogIO::EXCEPTION;
325 : };
326 :
327 0 : numMS_p=1;
328 0 : defaults();
329 0 : latestObsInfo_p=ObsInfo();
330 0 : }
331 :
332 :
333 :
334 0 : Imager::Imager(MeasurementSet& theMS, Bool compress)
335 0 : : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), ft_p(0), cft_p(0), se_p(0),
336 0 : sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false),
337 0 : mssFreqSel_p(), mssChanSel_p(),
338 0 : clean_panel_p(0), image_id_p(0), mask_id_p(0),
339 0 : prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
340 : {
341 0 : mssel_p=0;
342 0 : ms_p=0;
343 0 : lockCounter_p=0;
344 0 : LogIO os(LogOrigin("Imager", "Imager(MeasurementSet &theMS)", WHERE));
345 0 : if(!open(theMS, compress)) {
346 0 : os << LogIO::SEVERE << "Open of MeasurementSet failed" << LogIO::EXCEPTION;
347 : };
348 :
349 0 : numMS_p=1;
350 0 : defaults();
351 :
352 0 : latestObsInfo_p=ObsInfo();
353 0 : }
354 :
355 0 : Imager::Imager(const Imager & other)
356 0 : : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0),
357 0 : ft_p(0), cft_p(0), se_p(0),
358 0 : sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false),
359 0 : clean_panel_p(0), image_id_p(0), mask_id_p(0), prev_image_id_p(0), prev_mask_id_p(0)
360 : {
361 0 : mssel_p=0;
362 0 : ms_p=0;
363 0 : operator=(other);
364 0 : }
365 :
366 0 : Imager &Imager::operator=(const Imager & other)
367 : {
368 0 : if (!ms_p.null() && this != &other) {
369 0 : *ms_p = *(other.ms_p);
370 : }
371 0 : if(this != &other){
372 : //Equating the table and ms parameters
373 0 : antab_p=other.antab_p;
374 0 : datadesctab_p=other.datadesctab_p;
375 0 : feedtab_p=other.feedtab_p;
376 0 : fieldtab_p=other.fieldtab_p;
377 0 : obstab_p=other.obstab_p;
378 0 : pointingtab_p=other.pointingtab_p;
379 0 : poltab_p=other.poltab_p;
380 0 : proctab_p=other.proctab_p;
381 0 : spwtab_p=other.spwtab_p;
382 0 : statetab_p=other.statetab_p;
383 0 : latestObsInfo_p=other.latestObsInfo_p;
384 0 : parAngleInc_p=other.parAngleInc_p;
385 0 : skyPosThreshold_p=other.skyPosThreshold_p;
386 0 : doTrackSource_p=other.doTrackSource_p;
387 0 : trackDir_p=other.trackDir_p;
388 0 : smallScaleBias_p=other.smallScaleBias_p;
389 0 : numMS_p=other.numMS_p;
390 0 : if (!mssel_p.null() && this != &other) {
391 0 : *mssel_p = *(other.mssel_p);
392 : }
393 0 : if (vs_p && this != &other) {
394 0 : *vs_p = *(other.vs_p);
395 : }
396 0 : if (wvi_p && this != &other) {
397 0 : *wvi_p = *(other.wvi_p);
398 0 : rvi_p=wvi_p;
399 : }
400 0 : else if(rvi_p && this != &other){
401 0 : *rvi_p = *(other.rvi_p);
402 0 : wvi_p=NULL;
403 : }
404 0 : if (ft_p && this != &other) {
405 0 : *ft_p = *(other.ft_p);
406 : }
407 0 : if (cft_p && this != &other) {
408 0 : *cft_p = *(other.cft_p);
409 : }
410 0 : if (se_p && this != &other) {
411 0 : *se_p = *(other.se_p);
412 : }
413 0 : if (sm_p && this != &other) {
414 0 : *sm_p = *(other.sm_p);
415 : }
416 0 : if (vp_p && this != &other) {
417 0 : *vp_p = *(other.vp_p);
418 : }
419 0 : if (gvp_p && this != &other) {
420 0 : *gvp_p = *(other.gvp_p);
421 : }
422 0 : imageTileVol_p=other.imageTileVol_p;
423 0 : flatnoise_p=other.flatnoise_p;
424 0 : mssFreqSel_p.assign(other.mssFreqSel_p);
425 0 : mssChanSel_p.assign(other.mssChanSel_p);
426 0 : projection_p = other.projection_p;
427 : }
428 0 : return *this;
429 : }
430 :
431 64 : Imager::~Imager()
432 : {
433 : try{
434 50 : destroySkyEquation();
435 50 : this->unlock(); //unlock things if they are in a locked state
436 :
437 : //if (mssel_p) {
438 : // delete mssel_p;
439 : // }
440 50 : mssel_p = 0;
441 : //if (ms_p) {
442 : // delete ms_p;
443 : //}
444 50 : ms_p = 0;
445 50 : if (vs_p) {
446 0 : delete vs_p;
447 : }
448 50 : if(rvi_p)
449 14 : delete rvi_p;
450 50 : rvi_p=wvi_p=0;
451 :
452 50 : vs_p = 0;
453 50 : if (ft_p) {
454 0 : delete ft_p;
455 : }
456 :
457 :
458 50 : ft_p = 0;
459 50 : if (cft_p) {
460 14 : delete cft_p;
461 : }
462 50 : cft_p = 0;
463 :
464 : }
465 0 : catch (AipsError x){
466 0 : String mess=x.getMesg();
467 : //This is a bug for wproject and facet together...
468 : //somebody is erasing a TempLattice before desturctor.
469 : //will keep this in place till i figure it out...its benign
470 0 : if(mess.contains("does not exist") && mess.contains("TempLattice")){
471 0 : String rootpath="/"+String(mess.after("/")).before("TempLattice");
472 0 : String pid=String(mess.after("TempLattice")).before("_");
473 0 : DirectoryIterator dir(rootpath, Regex(Regex::fromPattern("TempLattice"+pid+"*")));
474 0 : while(!dir.pastEnd()){
475 0 : Directory ledir(rootpath+"/"+dir.name());
476 0 : ledir.removeRecursive();
477 0 : dir++;
478 :
479 0 : }
480 :
481 0 : }
482 : else{
483 0 : throw(AipsError(x));
484 :
485 : }
486 :
487 0 : }
488 :
489 :
490 64 : }
491 :
492 :
493 14 : Bool Imager::open(MeasurementSet& theMs, Bool /*compress*/, Bool useModelCol)
494 : {
495 :
496 28 : LogIO os(LogOrigin("Imager", "open()", WHERE));
497 :
498 14 : if (!ms_p.null()) {
499 0 : *ms_p = theMs;
500 : } else {
501 14 : ms_p = new MeasurementSet(theMs);
502 14 : AlwaysAssert(!ms_p.null(), AipsError);
503 : }
504 :
505 :
506 : try {
507 14 : this->openSubTables();
508 14 : this->lock();
509 14 : msname_p = ms_p->tableName();
510 :
511 14 : os << "Opening MeasurementSet " << msname_p << LogIO::POST;
512 :
513 : // Check for DATA or FLOAT_DATA column
514 28 : if(!ms_p->tableDesc().isColumn("DATA") &&
515 14 : !ms_p->tableDesc().isColumn("FLOAT_DATA")) {
516 0 : ms_p->unlock();
517 : //delete ms_p;
518 0 : ms_p=0;
519 : os << LogIO::SEVERE
520 : << "Missing DATA or FLOAT_DATA column: imager cannot be run"
521 0 : << LogIO::EXCEPTION;
522 0 : return false;
523 : }
524 :
525 : // The unused return value creates a compiler warning, there shouldn't be any side-effect of this statement
526 : //(!ms_p->tableDesc().isColumn("CORRECTED_DATA")); // if no side effect then delete this statement?
527 :
528 : /*if(vs_p) {
529 : delete vs_p; vs_p=0;
530 : }
531 : */
532 14 : if(rvi_p){
533 0 : delete rvi_p;
534 0 : rvi_p=0;
535 0 : wvi_p=0;
536 : }
537 :
538 : // Now open the selected MeasurementSet to be initially the
539 : // same as the original MeasurementSet
540 :
541 14 : mssel_p=new MeasurementSet(*ms_p);
542 14 : useModelCol_p=useModelCol;
543 :
544 : // Now create the VisSet
545 14 : this->makeVisSet(*mssel_p);
546 14 : AlwaysAssert(rvi_p, AipsError);
547 :
548 : // Polarization
549 14 : MSColumns msc(*mssel_p);
550 14 : Vector<String> polType=msc.feed().polarizationType()(0);
551 14 : if (polType(0)!="X" && polType(0)!="Y" &&
552 14 : polType(0)!="R" && polType(0)!="L") {
553 0 : this->unlock();
554 : os << LogIO::SEVERE << "Warning: Unknown stokes types in feed table: "
555 0 : << polType(0) << endl
556 0 : << "Results open to question!" << LogIO::POST;
557 : }
558 14 : numMS_p=1;
559 :
560 14 : this->unlock();
561 :
562 14 : return true;
563 14 : } catch (AipsError x) {
564 0 : this->unlock();
565 0 : os << LogIO::SEVERE << "Caught Exception: "<< x.getMesg() << LogIO::EXCEPTION;
566 :
567 0 : return false;
568 0 : }
569 :
570 : return true;
571 14 : }
572 :
573 0 : Bool Imager::close()
574 : {
575 0 : if(!valid()) return false;
576 0 : if (detached()) return true;
577 0 : LogIO os(LogOrigin("imager", "close()", WHERE));
578 : os << LogIO::NORMAL // Loglevel PROGRESS
579 : << "Closing MeasurementSet and detaching from imager"
580 0 : << LogIO::POST;
581 0 : this->unlock();
582 0 : if(ft_p) delete ft_p; ft_p = 0;
583 0 : if(cft_p) delete cft_p; cft_p = 0;
584 0 : if(vs_p) delete vs_p; vs_p = 0;
585 0 : if(rvi_p) delete rvi_p;
586 0 : rvi_p=0;
587 0 : wvi_p=0;
588 : //if(mssel_p) delete mssel_p;
589 0 : mssel_p = 0;
590 : //if(ms_p) delete ms_p;
591 0 : ms_p = 0;
592 :
593 0 : if(se_p) delete se_p; se_p = 0;
594 :
595 0 : if(vp_p) delete vp_p; vp_p = 0;
596 0 : if(gvp_p) delete gvp_p; gvp_p = 0;
597 :
598 0 : destroySkyEquation();
599 :
600 0 : return true;
601 0 : }
602 :
603 0 : String Imager::name() const
604 : {
605 0 : if (detached()) {
606 0 : return "none";
607 : }
608 0 : return msname_p;
609 : }
610 :
611 :
612 :
613 :
614 0 : IPosition Imager::imageshape() const
615 : {
616 0 : return IPosition(4, nx_p, ny_p, npol_p, imageNchan_p);
617 : }
618 :
619 0 : Bool Imager::summary()
620 : {
621 0 : if(!valid()) return false;
622 0 : LogOrigin OR("imager", "Imager::summary()", WHERE);
623 :
624 0 : LogIO los(OR);
625 :
626 0 : los << "Logging summary" << LogIO::POST;
627 : try {
628 :
629 0 : this->lock();
630 0 : MSSummary mss(*ms_p);
631 0 : mss.list(los, true);
632 :
633 0 : los << endl << state() << LogIO::POST;
634 0 : this->unlock();
635 0 : return true;
636 0 : } catch (AipsError x) {
637 0 : this->unlock();
638 : los << LogIO::SEVERE << "Caught Exception: " << x.getMesg()
639 0 : << LogIO::EXCEPTION;
640 0 : return false;
641 0 : }
642 :
643 : return true;
644 0 : }
645 :
646 :
647 0 : Bool Imager::setimage(const Int nx, const Int ny,
648 : const Quantity& cellx, const Quantity& celly,
649 : const String& stokes,
650 : Bool doShift,
651 : const MDirection& phaseCenter,
652 : const Quantity& shiftx, const Quantity& shifty,
653 : const String& mode, const Int nchan,
654 : const Int start, const Int step,
655 : const MRadialVelocity& mStart, const MRadialVelocity& mStep,
656 : const Vector<Int>& spectralwindowids,
657 : const Int fieldid,
658 : const Int facets,
659 : const Quantity& distance)
660 : {
661 :
662 0 : if(!valid())
663 : {
664 0 : return false;
665 : }
666 :
667 : //Clear the sink
668 0 : logSink_p.clearLocally();
669 0 : LogIO os(LogOrigin("imager", "setimage()"), logSink_p);
670 :
671 : os << "nx=" << nx << " ny=" << ny
672 0 : << " cellx='" << cellx.getValue() << cellx.getUnit()
673 0 : << "' celly='" << celly.getValue() << celly.getUnit()
674 : << "' stokes=" << stokes << " doShift=" << doShift
675 0 : << " shiftx='" << shiftx.getValue() << shiftx.getUnit()
676 0 : << "' shifty='" << shifty.getValue() << shifty.getUnit()
677 : << "' mode=" << mode << " nchan=" << nchan
678 : << " start=" << start << " step=" << step
679 : << " spwids=" << spectralwindowids
680 : << " fieldid=" << fieldid << " facets=" << facets
681 0 : << " distance='" << distance.getValue() << distance.getUnit() <<"'";
682 0 : ostringstream clicom;
683 0 : clicom << " phaseCenter='" << phaseCenter;
684 0 : clicom << "' mStart='" << mStart << "' mStep='" << mStep << "'";
685 0 : os << String(clicom);
686 :
687 : try {
688 :
689 0 : this->lock();
690 0 : this->writeCommand(os);
691 :
692 0 : os << LogIO::NORMAL << "Defining image properties" << LogIO::POST; // Loglevel INFO
693 :
694 : /**** this check is not really needed here especially for SD imaging
695 : if(2*Int(nx/2)!=nx) {
696 : this->unlock();
697 : os << LogIO::SEVERE << "nx must be even" << LogIO::POST;
698 : return false;
699 : }
700 : if(2*Int(ny/2)!=ny) {
701 : this->unlock();
702 : os << LogIO::SEVERE << "ny must be even" << LogIO::POST;
703 : return false;
704 : }
705 :
706 : */
707 : {
708 0 : CompositeNumber cn(nx);
709 0 : if (! cn.isComposite(nx)) {
710 0 : Int nxc = (Int)cn.nextLargerEven(nx);
711 0 : Int nnxc = (Int)cn.nearestEven(nx);
712 0 : if (nxc == nnxc) {
713 : os << LogIO::WARN << "nx = " << nx << " is not composite; nx = "
714 0 : << nxc << " will be more efficient" << LogIO::POST;
715 : } else {
716 : os << LogIO::WARN << "nx = " << nx << " is not composite; nx = "
717 0 : << nxc << " or " << nnxc << " will be more efficient for FFTs" << LogIO::POST;
718 : }
719 : }
720 0 : if (! cn.isComposite(ny)) {
721 0 : Int nyc = (Int)cn.nextLargerEven(ny);
722 0 : Int nnyc = (Int)cn.nearestEven(ny);
723 0 : if (nyc == nnyc) {
724 : os << LogIO::WARN << "ny = " << ny << " is not composite; ny = "
725 0 : << nyc << " will be more efficient" << LogIO::POST;
726 : } else {
727 : os << LogIO::WARN << "ny = " << ny << " is not composite ; ny = " << nyc <<
728 0 : " or " << nnyc << " will be more efficient for FFTs" << LogIO::POST;
729 : }
730 : os << LogIO::WARN
731 : << "You may safely ignore this message for single dish imaging"
732 0 : << LogIO::POST;
733 :
734 : }
735 :
736 0 : }
737 :
738 :
739 0 : nx_p=nx;
740 0 : ny_p=ny;
741 0 : mcellx_p=cellx;
742 0 : mcelly_p=celly;
743 0 : distance_p=distance;
744 0 : stokes_p=stokes;
745 0 : imageMode_p=mode;
746 0 : imageMode_p.upcase();
747 0 : imageNchan_p=nchan;
748 0 : imageStart_p=start;
749 0 : imageStep_p=step;
750 0 : mImageStart_p=mStart;
751 0 : mImageStep_p=mStep;
752 0 : spectralwindowids_p.resize(spectralwindowids.nelements());
753 0 : spectralwindowids_p=spectralwindowids;
754 0 : fieldid_p=fieldid;
755 0 : facets_p=facets;
756 0 : redoSkyModel_p=true;
757 0 : destroySkyEquation();
758 :
759 0 : Vector<Int> whichStokes = decideNPolPlanes(false);
760 0 : if( whichStokes.nelements()==1 && whichStokes[0]==0 )
761 : {
762 0 : this->unlock();
763 0 : os << LogIO::SEVERE << "Stokes selection " << stokes_p << " is currently not supported." << LogIO::EXCEPTION;
764 0 : return false;
765 : }
766 :
767 :
768 :
769 : //THIS NEEDS TO GO
770 : ////this->setImageParam(nx_p, ny_p, npol_p, imageNchan_p);
771 0 : nchan_p = imageNchan_p; // check if this is needed.... it's the only non-redundant thing in setImageParam.
772 :
773 : // Now do the shifts
774 : // MSColumns msc(*ms_p);
775 :
776 0 : doShift_p=doShift;
777 0 : if(doShift_p) {
778 0 : phaseCenter_p=phaseCenter;
779 : }
780 : else {
781 :
782 0 : MSFieldColumns msfield(ms_p->field());
783 0 : phaseCenter_p=msfield.phaseDirMeas(fieldid_p);
784 : // phaseCenter_p=msc.field().phaseDirMeas(fieldid_p);
785 0 : }
786 :
787 : // Now add the optional shifts
788 0 : shiftx_p=shiftx;
789 0 : shifty_p=shifty;
790 0 : if(shiftx_p.get().getValue()!=0.0||shifty_p.get().getValue()!=0.0) {
791 0 : Vector<Double> vPhaseCenter(phaseCenter_p.getAngle().getValue());
792 0 : if(cos(vPhaseCenter(1))!=0.0) {
793 0 : vPhaseCenter(0)+=shiftx_p.get().getValue()/cos(vPhaseCenter(1));
794 : }
795 0 : vPhaseCenter(1)+=shifty_p.get().getValue();
796 0 : phaseCenter_p.set(MVDirection(vPhaseCenter));
797 0 : }
798 :
799 : // Now we have set the image parameters
800 0 : setimaged_p=true;
801 0 : beamValid_p=false;
802 :
803 0 : this->unlock();
804 :
805 0 : return true;
806 0 : } catch (AipsError x) {
807 :
808 0 : this->unlock();
809 :
810 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
811 0 : << LogIO::EXCEPTION;
812 0 : return false;
813 0 : }
814 :
815 : return true;
816 0 : }
817 :
818 :
819 14 : Bool Imager::defineImage(const Int nx, const Int ny,
820 : const Quantity& cellx, const Quantity& celly,
821 : const String& stokes,
822 : const MDirection& phaseCenter, const Int fieldid,
823 : const String& mode, const Int nchan,
824 : const Int start, const Int step,
825 : const MFrequency& mFreqStart,
826 : const MRadialVelocity& mStart,
827 : const Quantity& qStep,
828 : const Vector<Int>& spectralwindowids,
829 : const Int facets,
830 : const Quantity& restFreq,
831 : const MFrequency::Types& mFreqFrame,
832 : const Quantity& distance, const Bool dotrackDir,
833 : const MDirection& trackDir,
834 : const String& projection)
835 : {
836 :
837 :
838 :
839 :
840 : //Clear the sink
841 14 : logSink_p.clearLocally();
842 28 : LogIO os(LogOrigin("imager", "defineimage()"), logSink_p);
843 14 : if(cellx.getValue() == 0.0 || celly.getValue()==0.0)
844 0 : throw(AipsError("Infinite resolution not possible... please do let us know what you are drinking"));
845 14 : os << LogIO::NORMAL << "Defining image properties:"; // Loglevel INFO
846 : os << "nx=" << nx << " ny=" << ny
847 28 : << " cellx='" << cellx.getValue() << cellx.getUnit()
848 28 : << "' celly='" << celly.getValue() << celly.getUnit()
849 : << "' stokes=" << stokes
850 : << "' mode=" << mode << " nchan=" << nchan
851 : << " start=" << start << " step=" << step
852 : << " spwids=" << spectralwindowids
853 : << " fieldid=" << fieldid << " facets=" << facets
854 14 : << " frame=" << mFreqFrame
855 14 : << " distance='" << distance.getValue() << distance.getUnit() <<"'";
856 14 : os << LogIO::POST;
857 14 : ostringstream clicom;
858 14 : clicom << " phaseCenter='" ;
859 14 : if(fieldid < 0){
860 0 : MVAngle mvRA=phaseCenter.getAngle().getValue()(0);
861 0 : MVAngle mvDEC=phaseCenter.getAngle().getValue()(1);
862 0 : clicom << mvRA(0.0).string(MVAngle::TIME,8) << ", ";
863 0 : clicom << mvDEC(0.0).string(MVAngle::ANGLE_CLEAN,8) << ", ";
864 0 : }
865 : else{
866 14 : clicom << "field-" << fieldid<< " ";
867 : }
868 14 : clicom << "' mStart='" << mStart << "' qStep='" << qStep << "'";
869 14 : clicom << "' mFreqStart='" << mFreqStart;
870 14 : os << String(clicom);
871 14 : os << LogIO::POST;
872 :
873 : try {
874 :
875 14 : this->lock();
876 14 : this->writeCommand(os);
877 :
878 14 : doTrackSource_p=dotrackDir;
879 14 : trackDir_p=trackDir;
880 :
881 :
882 : /**** this check is not really needed here especially for SD imaging
883 : if(2*Int(nx/2)!=nx) {
884 : this->unlock();
885 : os << LogIO::SEVERE << "nx must be even" << LogIO::POST;
886 : return false;
887 : }
888 : if(2*Int(ny/2)!=ny) {
889 : this->unlock();
890 : os << LogIO::SEVERE << "ny must be even" << LogIO::POST;
891 : return false;
892 : }
893 :
894 : */
895 : // RVU : Disabling this Composite Number check, because image sizes are
896 : // anyway being re-calculated inside the FTMachines (accounding for padding too).
897 : if(0)
898 : {
899 : CompositeNumber cn(nx);
900 : if (! cn.isComposite(nx)) {
901 : Int nxc = (Int)cn.nextLargerEven(nx);
902 : Int nnxc = (Int)cn.nearestEven(nx);
903 : if (nxc == nnxc) {
904 : os << LogIO::POST << "nx = " << nx << " is not composite; nx = "
905 : << nxc << " will be more efficient" << LogIO::POST;
906 : } else {
907 : os << LogIO::POST << "nx = " << nx << " is not composite; nx = "
908 : << nxc << " or " << nnxc << " will be more efficient" << LogIO::POST;
909 : }
910 : }
911 : if (! cn.isComposite(ny)) {
912 : Int nyc = (Int)cn.nextLargerEven(ny);
913 : Int nnyc = (Int)cn.nearestEven(ny);
914 : if (nyc == nnyc) {
915 : os << LogIO::POST << "ny = " << ny << " is not composite; ny = "
916 : << nyc << " will be more efficient" << LogIO::POST;
917 : } else {
918 : os << LogIO::POST << "ny = " << ny << " is not composite; ny = " << nyc <<
919 : " or " << nnyc << " will be more efficient" << LogIO::POST;
920 : }
921 : os << LogIO::POST
922 : << "You may safely ignore this message for single dish imaging"
923 : << LogIO::POST;
924 :
925 : }
926 :
927 : }
928 :
929 :
930 14 : if((abs(Double(nx)*cellx.getValue("rad")) > C::pi) || (abs(Double(ny)*celly.getValue("rad")) > C::pi))
931 0 : throw(AipsError("Cannot image the extent requested for this image; more that PI ialong one or both of the axes " ));
932 :
933 :
934 :
935 14 : nx_p=nx;
936 14 : ny_p=ny;
937 14 : mcellx_p=cellx;
938 14 : mcelly_p=celly;
939 14 : distance_p=distance;
940 14 : stokes_p=stokes;
941 14 : imageMode_p=mode;
942 14 : imageMode_p.upcase();
943 14 : imageNchan_p=nchan;
944 14 : imageStart_p=start;
945 14 : imageStep_p=step;
946 14 : if(mode.contains("VEL")){
947 0 : mImageStart_p=mStart;
948 0 : mImageStep_p=MRadialVelocity(qStep);
949 : }
950 14 : if(mode.contains("FREQ")){
951 0 : mfImageStart_p=mFreqStart;
952 0 : mfImageStep_p=MFrequency(qStep);
953 : }
954 14 : restFreq_p=restFreq;
955 14 : freqFrame_p=mFreqFrame;
956 14 : spectralwindowids_p.resize(spectralwindowids.nelements());
957 14 : spectralwindowids_p=spectralwindowids;
958 14 : fieldid_p=fieldid;
959 14 : facets_p=facets;
960 14 : redoSkyModel_p=true;
961 14 : destroySkyEquation();
962 :
963 : // Now make the derived quantities
964 14 : Vector<Int> whichStokes = decideNPolPlanes(false);
965 14 : if( whichStokes.nelements()==1 && whichStokes[0]==0 )
966 : {
967 0 : this->unlock();
968 0 : os << LogIO::SEVERE << "Stokes selection " << stokes_p << " is currently not supported." << LogIO::EXCEPTION;
969 0 : return false;
970 : }
971 :
972 : // nchan we need to get rid of one of these variables
973 14 : nchan_p=imageNchan_p;
974 :
975 14 : if(fieldid < 0){
976 0 : doShift_p=true;
977 0 : phaseCenter_p=phaseCenter;
978 : }
979 : else {
980 14 : MSFieldColumns msfield(ms_p->field());
981 14 : phaseCenter_p=msfield.phaseDirMeas(fieldid_p);
982 14 : }
983 :
984 : // we only support projections SIN, CAR, TAN, and SFL
985 14 : Projection::Type const ptype = Projection::type(projection);
986 14 : if (ptype != Projection::SIN && ptype != Projection::CAR
987 0 : && ptype != Projection::TAN && ptype != Projection::SFL) {
988 0 : this->unlock();
989 0 : os << LogIO::SEVERE << "Projection " << projection << " is currently not supported." << LogIO::EXCEPTION;
990 0 : return false;
991 : } else {
992 14 : projection_p = projection;
993 : }
994 :
995 :
996 : // Now we have set the image parameters
997 14 : setimaged_p=true;
998 14 : beamValid_p=false;
999 :
1000 14 : this->unlock();
1001 :
1002 :
1003 14 : return true;
1004 14 : } catch (AipsError x) {
1005 0 : this->unlock();
1006 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1007 0 : << LogIO::EXCEPTION;
1008 0 : return false;
1009 0 : }
1010 : return true;
1011 14 : }
1012 :
1013 :
1014 0 : Bool Imager::advise(const Bool takeAdvice, const Float amplitudeLoss,
1015 : const Quantity& fieldOfView, Quantity& cell,
1016 : Int& pixels, Int& facets, MDirection& phaseCenter)
1017 : {
1018 0 : if(!valid()) return false;
1019 :
1020 0 : LogIO os(LogOrigin("imager", "advise()", WHERE));
1021 :
1022 : try {
1023 :
1024 0 : os << "Advising image properties" << LogIO::POST;
1025 :
1026 0 : Float maxAbsUV=0.0;
1027 0 : Float maxWtAbsUV=0.0;
1028 : // To determine the number of facets, we need to fit w to
1029 : // a.u + b.v. The misfit from this (i.e. the dispersion
1030 : // will determine the error beam due to the non-coplanar
1031 : // baselines. We'll do both cases: where the position
1032 : // errors are important and where they are not. We'll use
1033 : // the latter.
1034 0 : Double sumWt = 0.0;
1035 :
1036 0 : Double sumUU=0.0;
1037 0 : Double sumUV=0.0;
1038 0 : Double sumUW=0.0;
1039 0 : Double sumVV=0.0;
1040 0 : Double sumVW=0.0;
1041 0 : Double sumWW=0.0;
1042 :
1043 0 : Double sumWtUU=0.0;
1044 0 : Double sumWtUV=0.0;
1045 0 : Double sumWtUW=0.0;
1046 0 : Double sumWtVV=0.0;
1047 0 : Double sumWtVW=0.0;
1048 0 : Double sumWtWW=0.0;
1049 :
1050 0 : Double sum = 0.0;
1051 :
1052 0 : this->lock();
1053 0 : ROVisIter& vi(*rvi_p);
1054 0 : VisBuffer vb(vi);
1055 :
1056 0 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
1057 0 : for (vi.origin();vi.more();vi++) {
1058 0 : Int nRow=vb.nRow();
1059 0 : Int nChan=vb.nChannel();
1060 0 : for (Int row=0; row<nRow; ++row) {
1061 0 : for (Int chn=0; chn<nChan; ++chn) {
1062 0 : if(!vb.flag()(chn,row)) {
1063 0 : Float f=vb.frequency()(chn)/C::c;
1064 0 : Float u=vb.uvw()(row)(0)*f;
1065 0 : Float v=vb.uvw()(row)(1)*f;
1066 0 : Float w=vb.uvw()(row)(2)*f;
1067 0 : Double wt=vb.imagingWeight()(chn,row);
1068 0 : if(wt>0.0) {
1069 0 : if(abs(u)>maxWtAbsUV) maxWtAbsUV=abs(u);
1070 0 : if(abs(v)>maxWtAbsUV) maxWtAbsUV=abs(v);
1071 0 : sumWt += wt;
1072 0 : sumWtUU += wt * u * u;
1073 0 : sumWtUV += wt * u * v;
1074 0 : sumWtUW += wt * u * w;
1075 0 : sumWtVV += wt * v * v;
1076 0 : sumWtVW += wt * v * w;
1077 0 : sumWtWW += wt * w * w;
1078 : }
1079 0 : sum += 1;
1080 0 : if(abs(u)>maxAbsUV) maxAbsUV=abs(u);
1081 0 : if(abs(v)>maxAbsUV) maxAbsUV=abs(v);
1082 0 : sumUU += u * u;
1083 0 : sumUV += u * v;
1084 0 : sumUW += u * w;
1085 0 : sumVV += v * v;
1086 0 : sumVW += v * w;
1087 0 : sumWW += w * w;
1088 : }
1089 : }
1090 : }
1091 : }
1092 : }
1093 :
1094 :
1095 0 : if(sumWt==0.0) {
1096 0 : os << LogIO::WARN << "Visibility data are not yet weighted: using unweighted values" << LogIO::POST;
1097 0 : sumWt = sum;
1098 : }
1099 : else {
1100 0 : sumUU = sumWtUU;
1101 0 : sumUV = sumWtUV;
1102 0 : sumUW = sumWtUW;
1103 0 : sumVV = sumWtVV;
1104 0 : sumVW = sumWtVW;
1105 0 : sumWW = sumWtWW;
1106 0 : maxAbsUV = maxWtAbsUV;
1107 : }
1108 :
1109 : // First find the cell size
1110 0 : if(maxAbsUV==0.0) {
1111 0 : this->unlock();
1112 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
1113 0 : return false;
1114 : }
1115 : else {
1116 0 : cell=Quantity(0.5/maxAbsUV, "rad").get("arcsec");
1117 0 : os << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
1118 0 : os << "Recommended cell size < " << cell.get("arcsec").getValue()
1119 0 : << " arcsec" << LogIO::POST;
1120 : }
1121 :
1122 : // Now we can find the number of pixels for the specified field of view
1123 0 : pixels = 2*Int((fieldOfView.get("rad").getValue()/cell.get("rad").getValue())/2.0);
1124 : {
1125 0 : CompositeNumber cn(pixels);
1126 0 : pixels = (Int) (cn.nextLargerEven(pixels));
1127 0 : }
1128 0 : if(pixels < 64) pixels = 64;
1129 0 : os << "Recommended number of pixels = " << pixels << endl;
1130 :
1131 : // Rough rule for number of facets:
1132 : // For the specified facet size, the loss in amplitude
1133 : // due to the peeling of facets from the sphere should
1134 : // be equal to the amplitude error.
1135 0 : Int worstCaseFacets=1;
1136 0 : if(sumWt<=0.0||sumUU<=0.0||(sumUU+sumVV)<=0.0) {
1137 0 : this->unlock();
1138 0 : os << LogIO::SEVERE << "Sum of imaging weights is zero" << LogIO::POST;
1139 0 : return false;
1140 : }
1141 : else {
1142 0 : Double rmsUV = sqrt((sumUU + sumVV)/sumWt);
1143 0 : Double rmsW = sqrt(sumWW/sumWt);
1144 : os << "Dispersion in uv, w distance = " << rmsUV << ", "<< rmsW
1145 0 : << " wavelengths" << endl;
1146 0 : if(rmsW>0.0&&rmsUV>0.0&&litudeLoss>0.0) {
1147 0 : worstCaseFacets =
1148 0 : Int (pixels * (abs(cell.get("rad").getValue())*
1149 0 : sqrt(C::pi*rmsW/(sqrt(32.0*amplitudeLoss)))));
1150 : }
1151 : else {
1152 : os << LogIO::WARN << "Cannot calculate number of facets: using 1"
1153 0 : << LogIO::POST;
1154 0 : worstCaseFacets = 1;
1155 : }
1156 : // Solve for the parameters:
1157 0 : Double Determinant = sumUU * sumVV - square(sumUV);
1158 0 : Double rmsFittedW = rmsW;
1159 0 : if(Determinant > 0.0) {
1160 0 : Double a = ( sumVV * sumUW - sumUV * sumVW)/Determinant;
1161 0 : Double b = (-sumUV * sumUW + sumUU * sumVW)/Determinant;
1162 : os << "Best fitting plane is w = " << a << " * u + "
1163 0 : << b << " * v" << endl;
1164 : Double FittedWW =
1165 0 : sumWW + square(a) * sumUU + square(b) * sumVV +
1166 0 : + 2.0 * a * b * sumUV - 2.0 * (a * sumUW + b * sumVW);
1167 0 : rmsFittedW = sqrt(FittedWW/sumWt);
1168 : os << "Dispersion in fitted w = " << rmsFittedW
1169 0 : << " wavelengths" << endl;
1170 0 : facets = Int (pixels * (abs(cell.get("rad").getValue())*
1171 0 : sqrt(C::pi*rmsFittedW/(sqrt(32.0*amplitudeLoss)))));
1172 0 : if (facets<1) facets = 1;
1173 : }
1174 : else {
1175 0 : os << "Error in fitting plane to uvw data" << LogIO::POST;
1176 : }
1177 0 : if(worstCaseFacets<1) worstCaseFacets=1;
1178 0 : if(worstCaseFacets>1) {
1179 : os << "imager recommends that you use the wide field clean" << endl
1180 : << "For accurate positions, use " << worstCaseFacets
1181 : << " facets on each axis" << endl
1182 : << "For accurate removal of sources, you only need "
1183 0 : << facets << " facets on each axis" << LogIO::POST;
1184 : }
1185 : else {
1186 : os << "Wide field cleaning is not necessary"
1187 0 : << LogIO::POST;
1188 : }
1189 : }
1190 :
1191 0 : MSColumns msc(*mssel_p);
1192 0 : if(datafieldids_p.shape()!=0){
1193 : //If setdata has been used prior to this
1194 0 : phaseCenter=msc.field().phaseDirMeas(datafieldids_p(0));
1195 : }
1196 : else{
1197 0 : phaseCenter=msc.field().phaseDirMeas(fieldid_p);
1198 : }
1199 :
1200 :
1201 : // Now we have set the image parameters
1202 0 : if(takeAdvice) {
1203 0 : os << "Using advised image properties" << LogIO::POST;
1204 0 : mcellx_p=cell;
1205 0 : mcelly_p=cell;
1206 0 : phaseCenter_p=phaseCenter;
1207 0 : setimaged_p=true;
1208 0 : beamValid_p=false;
1209 0 : facets_p=facets;
1210 0 : nx_p=ny_p=pixels;
1211 : }
1212 :
1213 0 : this->unlock();
1214 0 : return true;
1215 0 : } catch (AipsError x) {
1216 0 : this->unlock();
1217 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1218 0 : << LogIO::EXCEPTION;
1219 0 : return false;
1220 0 : }
1221 :
1222 : return true;
1223 0 : }
1224 :
1225 :
1226 :
1227 0 : Bool Imager::setDataPerMS(const String& msname, const String& mode,
1228 : const Vector<Int>& nchan,
1229 : const Vector<Int>& start,
1230 : const Vector<Int>& step,
1231 : const Vector<Int>& spectralwindowids,
1232 : const Vector<Int>& fieldids,
1233 : const String& msSelect, const String& timerng,
1234 : const String& fieldnames,
1235 : const Vector<Int>& antIndex,
1236 : const String& antnames,
1237 : const String& spwstring,
1238 : const String& uvdist, const String& scan,
1239 : const String& intent, const String& obs,
1240 : const Bool useModelCol, const Bool /*readonly*/)
1241 : {
1242 0 : LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
1243 0 : if(msname != ""){
1244 :
1245 0 : LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
1246 : os << LogIO::WARN
1247 : << "Ignoring that ms" << msname << "specified here"
1248 0 : << LogIO::POST;
1249 : os << LogIO::WARN
1250 : << "Imager was constructed with an ms "
1251 0 : << LogIO::POST;
1252 : os << LogIO::WARN
1253 : << "if multi-ms are to be used please construct imager without parameters and use setdata to specify the ms's and selection"
1254 0 : << LogIO::POST;
1255 :
1256 0 : }
1257 0 : MRadialVelocity dummy;
1258 : //Calling the old setdata
1259 0 : return setdata(mode, nchan, start, step, dummy, dummy, spectralwindowids,
1260 : fieldids, msSelect, timerng, fieldnames, antIndex,
1261 0 : antnames, spwstring, uvdist, scan, intent, obs, useModelCol);
1262 :
1263 0 : }
1264 :
1265 :
1266 0 : Bool Imager::setdata(const String& mode, const Vector<Int>& nchan,
1267 : const Vector<Int>& start, const Vector<Int>& step,
1268 : const MRadialVelocity& mStart,
1269 : const MRadialVelocity& mStep,
1270 : const Vector<Int>& spectralwindowids,
1271 : const Vector<Int>& fieldids,
1272 : const String& msSelect, const String& timerng,
1273 : const String& fieldnames, const Vector<Int>& antIndex,
1274 : const String& antnames, const String& spwstring,
1275 : const String& uvdist, const String& scan,
1276 : const String& intent,
1277 : const String& obs,
1278 : const Bool /*useModelCol*/,
1279 : const Bool be_calm)
1280 : {
1281 0 : logSink_p.clearLocally();
1282 0 : LogIO os(LogOrigin("imager", "data selection"), logSink_p);
1283 :
1284 0 : if(ms_p.null()) {
1285 : os << LogIO::SEVERE << "Program logic error: MeasurementSet pointer ms_p not yet set"
1286 0 : << LogIO::EXCEPTION;
1287 0 : nullSelect_p=true;
1288 0 : return false;
1289 : }
1290 :
1291 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1292 : << "mode=" << mode << " nchan=" << nchan
1293 0 : << " start=" << start << " step=" << step;
1294 0 : ostringstream clicom;
1295 0 : clicom << " mstart='" << mStart << "' mstep='" << mStep;
1296 0 : os << String(clicom) ;
1297 : os << "' spectralwindowids=" << spectralwindowids
1298 0 : << " fieldids=" << fieldids << " msselect=" << msSelect;
1299 :
1300 0 : nullSelect_p=false;
1301 0 : String local_spwstring(spwstring);
1302 0 : if (local_spwstring == "") local_spwstring="*";
1303 : try {
1304 :
1305 0 : this->lock();
1306 0 : this->writeCommand(os);
1307 :
1308 : os << (be_calm ? LogIO::NORMAL2 : LogIO::NORMAL)
1309 0 : << "Performing selection on MeasurementSet : " << ms_p->tableName()
1310 0 : << LogIO::POST; // Loglevel PROGRESS
1311 : //Some MSSelection
1312 0 : MSSelection thisSelection;
1313 :
1314 : // check that sorted table exists (it should), if not, make it now.
1315 : //this->makeVisSet(*ms_p);
1316 :
1317 : //MeasurementSet sorted=ms_p->keywordSet().asTable("SORTED_TABLE");
1318 : //MSSelection thisSelection (sorted, MSSelection::PARSE_NOW,timerng,antnames,
1319 : // fieldnames, local_spwstring,uvdist, msSelect,"",
1320 : // scan, obs);
1321 :
1322 0 : datafieldids_p.resize(fieldids.nelements());
1323 0 : datafieldids_p = fieldids;
1324 0 : if(datafieldids_p.nelements() > 0){
1325 0 : thisSelection.setFieldExpr(MSSelection::indexExprStr(datafieldids_p));
1326 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1327 0 : << "Selecting on field ids : " << datafieldids_p << LogIO::POST;
1328 : }
1329 0 : if(fieldnames != ""){
1330 0 : thisSelection.setFieldExpr(fieldnames);
1331 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1332 0 : << "Selecting on fields : " << fieldnames << LogIO::POST;
1333 : }
1334 :
1335 0 : dataspectralwindowids_p.resize(spectralwindowids.nelements());
1336 0 : dataspectralwindowids_p = spectralwindowids;
1337 0 : if(dataspectralwindowids_p.nelements() > 0){
1338 0 : thisSelection.setSpwExpr(MSSelection::indexExprStr(dataspectralwindowids_p));
1339 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1340 0 : << "Selecting on spectral windows" << LogIO::POST;
1341 : }
1342 0 : else if(local_spwstring != ""){
1343 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1344 : << "Selecting on spectral windows expression : " << local_spwstring
1345 0 : << LogIO::POST;
1346 0 : thisSelection.setSpwExpr(local_spwstring);
1347 : }
1348 :
1349 0 : if(antIndex.nelements() >0){
1350 0 : thisSelection.setAntennaExpr( MSSelection::indexExprStr(antIndex));
1351 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1352 0 : << "Selecting on antenna ids : " << antIndex << LogIO::POST;
1353 : }
1354 0 : if(antnames != ""){
1355 0 : Vector<String>antNames(1, antnames);
1356 : // thisSelection.setAntennaExpr(MSSelection::nameExprStr(antNames));
1357 0 : thisSelection.setAntennaExpr(antnames);
1358 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1359 0 : << "Selecting on antenna names : " << antnames << LogIO::POST;
1360 0 : }
1361 :
1362 0 : if(timerng != ""){
1363 : // Vector<String>timerange(1, timerng);
1364 0 : thisSelection.setTimeExpr(timerng);
1365 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1366 0 : << "Selecting on time range : " << timerng << LogIO::POST;
1367 : }
1368 :
1369 0 : if(uvdist != ""){
1370 0 : thisSelection.setUvDistExpr(uvdist);
1371 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1372 0 : << "Selecting on uvdist : " << uvdist << LogIO::POST;
1373 : }
1374 :
1375 0 : if(scan != ""){
1376 0 : thisSelection.setScanExpr(scan);
1377 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1378 0 : << "Selecting on scan : " << scan << LogIO::POST;
1379 : }
1380 0 : if(intent != "") {
1381 0 : thisSelection.setStateExpr(intent);
1382 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1383 0 : << "Selecting on State Expr : " << intent << LogIO::POST;
1384 : }
1385 0 : if(obs != ""){
1386 0 : thisSelection.setObservationExpr(obs);
1387 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1388 0 : << "Selecting on Observation Expr : " << obs << LogIO::POST;
1389 : }
1390 0 : if(msSelect != ""){
1391 0 : thisSelection.setTaQLExpr(msSelect);
1392 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1393 0 : << "Selecting via TaQL : " << msSelect << LogIO::POST;
1394 : }
1395 :
1396 : //***************
1397 0 : TableExprNode exprNode;
1398 : try{
1399 0 : exprNode = thisSelection.toTableExprNode(&(*ms_p));
1400 : }
1401 0 : catch(...){
1402 0 : nullSelect_p = true;
1403 0 : this->unlock();
1404 : // A "bad selection" warning message could be sent to the logger here,
1405 : // but it should be left to the calling function to do that. For
1406 : // example, this function is called by setjy, and it would be a mistake
1407 : // to print a logger message for every spw that was not observed for the
1408 : // given field.
1409 0 : return false;
1410 0 : }
1411 : //TableExprNode exprNode=thisSelection.getTEN();
1412 : //if(exprNode.isNull()){
1413 : // throw(AipsError("Selection failed...review ms and selection parameters"));
1414 : //}
1415 :
1416 : // Need to delete the ft machine as the channel flag may change
1417 0 : if(ft_p)
1418 0 : delete ft_p;
1419 0 : ft_p=0;
1420 0 : dataMode_p=mode;
1421 0 : dataNchan_p.resize();
1422 0 : dataStart_p.resize();
1423 0 : dataStep_p.resize();
1424 0 : dataNchan_p=nchan;
1425 0 : dataStart_p=start;
1426 0 : dataStep_p=step;
1427 0 : mDataStart_p=mStart;
1428 0 : mDataStep_p=mStep;
1429 : // useModelCol_p=useModelCol;
1430 :
1431 0 : if(rvi_p)
1432 0 : delete rvi_p;
1433 0 : rvi_p=0;
1434 0 : wvi_p=0;
1435 : // if(mssel_p) delete mssel_p;
1436 0 : mssel_p=0;
1437 :
1438 0 : datafieldids_p.resize();
1439 0 : datafieldids_p=thisSelection.getFieldList();
1440 0 : if(datafieldids_p.nelements()==0){
1441 0 : Int nf=ms_p->field().nrow();
1442 0 : datafieldids_p.resize(nf);
1443 0 : indgen(datafieldids_p);
1444 : }
1445 : //Now lets see what was selected as spw and match it with datadesc
1446 : //
1447 : // getSpwList could return duplicated spw ids
1448 : // when multiple channel ranges are specified.
1449 : //dataspectralwindowids_p.resize();
1450 : //dataspectralwindowids_p=thisSelection.getSpwList();
1451 : //get channel selection in spw
1452 : // TT: Added sorting option in getChanList call
1453 : // to accomodate changes related CAS-2521
1454 0 : Matrix<Int> chansels=thisSelection.getChanList(NULL, 1, true);
1455 0 : mssChanSel_p.assign(chansels);
1456 0 : mssFreqSel_p.resize();
1457 0 : mssFreqSel_p=thisSelection.getChanFreqList(NULL, true);
1458 :
1459 : //cout<<"chansels="<<chansels<<endl;
1460 : //convert the selection into flag
1461 0 : uInt nms = 1;
1462 0 : uInt nrow = chansels.nrow();
1463 0 : dataspectralwindowids_p.resize();
1464 0 : const MSSpWindowColumns spwc(ms_p->spectralWindow());
1465 0 : uInt nspw = spwc.nrow();
1466 0 : const ScalarColumn<Int> spwNchans(spwc.numChan());
1467 0 : Vector<Int> nchanvec = spwNchans.getColumn();
1468 0 : Int maxnchan = 0;
1469 0 : for (uInt i=0;i<nchanvec.nelements();i++) {
1470 0 : maxnchan=max(nchanvec[i],maxnchan);
1471 : }
1472 :
1473 0 : spwchansels_p.resize(nms,nspw,maxnchan);
1474 0 : spwchansels_p.set(0);
1475 0 : uInt nselspw=0;
1476 0 : if (nrow==0) {
1477 : //no channel selection, select all channels
1478 0 : spwchansels_p=1;
1479 0 : dataspectralwindowids_p=thisSelection.getSpwList();
1480 : }
1481 : else {
1482 0 : spwchansels_p=0; //deselect
1483 0 : Int prvspwid=-1;
1484 0 : Vector<Int> selspw;
1485 0 : for (uInt i=0;i<nrow;i++) {
1486 0 : Vector<Int> sel = chansels.row(i);
1487 0 : Int spwid = sel[0];
1488 0 : if((sel[1] >= nchanvec[spwid]) || (sel[2] >=nchanvec[spwid]))
1489 0 : throw(AipsError("Unexpected selection in spw selection of spwid "+String::toString(spwid)));
1490 0 : if (spwid != prvspwid){
1491 0 : nselspw++;
1492 0 : selspw.resize(nselspw,true);
1493 0 : selspw[nselspw-1]=spwid;
1494 : }
1495 0 : uInt minc= sel[1];
1496 0 : uInt maxc = sel[2];
1497 0 : uInt step = sel[3];
1498 : // step as the same context as in im.selectvis
1499 : // select channels
1500 0 : for (uInt k=minc;k<(maxc+1);k+=step) {
1501 0 : spwchansels_p(0,spwid,k)=1;
1502 : }
1503 0 : prvspwid=spwid;
1504 0 : }
1505 0 : dataspectralwindowids_p=selspw;
1506 0 : }
1507 :
1508 : // Map the selected spectral window ids to data description ids
1509 0 : if(dataspectralwindowids_p.nelements()==0){
1510 0 : Int nspwinms=ms_p->spectralWindow().nrow();
1511 0 : dataspectralwindowids_p.resize(nspwinms);
1512 0 : indgen(dataspectralwindowids_p);
1513 : }
1514 0 : MSDataDescIndex msDatIndex(ms_p->dataDescription());
1515 0 : datadescids_p.resize(0);
1516 0 : datadescids_p=msDatIndex.matchSpwId(dataspectralwindowids_p);
1517 :
1518 0 : if (datafieldids_p.nelements() > 1) {
1519 0 : os << LogIO::NORMAL4<< "Multiple fields specified" << LogIO::POST;
1520 0 : multiFields_p = true;
1521 : }
1522 :
1523 :
1524 0 : if(mode=="none"){
1525 : // Now channel selection from spw already stored in chansel,
1526 : // no need for this- TT
1527 : //check if we can find channel selection in the spw string
1528 : //Matrix<Int> chanselmat=thisSelection.getChanList();
1529 : //
1530 : // This not correct for multiple channel ranges TT
1531 : //if(chanselmat.nrow()==dataspectralwindowids_p.nelements()){
1532 0 : if(nselspw==dataspectralwindowids_p.nelements()){
1533 :
1534 0 : dataMode_p="channel";
1535 0 : dataStep_p.resize(dataspectralwindowids_p.nelements());
1536 0 : dataStart_p.resize(dataspectralwindowids_p.nelements());
1537 0 : dataNchan_p.resize(dataspectralwindowids_p.nelements());
1538 0 : Cube<Int> spwchansels_tmp=spwchansels_p;
1539 :
1540 0 : for (uInt k =0 ; k < dataspectralwindowids_p.nelements(); ++k){
1541 0 : uInt curspwid=dataspectralwindowids_p[k];
1542 : //dataStep_p[k]=1;
1543 0 : if (nrow > 0) {
1544 0 : dataStep_p[k]=chansels.row(k)(3);
1545 : }
1546 : else {
1547 0 : dataStep_p[k]=1;
1548 : }
1549 : //dataStart_p[k]=chanselmat.row(k)(1);
1550 0 : dataStart_p[k]=0;
1551 0 : dataNchan_p[k]=nchanvec(curspwid);
1552 : //find start
1553 0 : Bool first =true;
1554 0 : uInt nchn = 0;
1555 0 : uInt lastchan = 0;
1556 0 : for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++) {
1557 0 : if (spwchansels_p(0,curspwid,j)==1) {
1558 0 : if (first) {
1559 0 : dataStart_p[k]=j;
1560 0 : first = false;
1561 : }
1562 0 : lastchan=j;
1563 0 : nchn++;
1564 : }
1565 : }
1566 0 : dataNchan_p[k]=Int(ceil(Double(lastchan-dataStart_p[k])/Double(dataStep_p[k])))+1;
1567 : //dataNchan_p[k]=Int(ceil(Double(chanselmat.row(k)(2)-dataStart_p[k])/Double(dataStep_p[k])))+1;
1568 :
1569 : //if(dataNchan_p[k]<1)
1570 : // dataNchan_p[k]=1;
1571 :
1572 : //cout<<"modified start="<<dataStart_p[k]<<endl;
1573 : //cout<<"modified nchan="<<dataNchan_p[k]<<endl;
1574 : //
1575 : //Since msselet will be applied to the data before flags from spwchansels_p
1576 : //are applied to the data in FTMachine, shift spwchansels_p by dataStart_p
1577 : //for (uInt j=0 ; j < nchanvec(k)-dataStart_p[k]; j++){
1578 0 : for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++){
1579 0 : if ( Int(j) < nchanvec(curspwid)-dataStart_p[k]) {
1580 0 : spwchansels_tmp(0,curspwid,j) = spwchansels_p(0,curspwid,j+dataStart_p[k]);
1581 : }
1582 : else {
1583 0 : spwchansels_tmp(0,curspwid,j) = 0;
1584 : }
1585 : }
1586 : }
1587 0 : spwchansels_p = spwchansels_tmp;
1588 0 : }
1589 : }
1590 0 : if(!(exprNode.isNull())){
1591 0 : mssel_p = new MeasurementSet((*ms_p)(exprNode), &* ms_p);
1592 : }
1593 : else{
1594 : // Null take all the ms ...setdata() blank means that
1595 0 : mssel_p = new MeasurementSet(*ms_p);
1596 : }
1597 :
1598 0 : AlwaysAssert(!mssel_p.null(), AipsError);
1599 0 : if(mssel_p->nrow()==0) {
1600 : //delete mssel_p;
1601 0 : mssel_p=0;
1602 : os << (be_calm ? LogIO::NORMAL4 : LogIO::WARN)
1603 : << "Selection is empty: reverting to sorted MeasurementSet"
1604 0 : << LogIO::POST;
1605 0 : mssel_p=new MeasurementSet(*ms_p);
1606 0 : nullSelect_p=true;
1607 : }
1608 : else {
1609 0 : mssel_p->flush();
1610 0 : nullSelect_p=false;
1611 : }
1612 0 : if (nullSelect_p) {
1613 0 : if ((mssel_p->field()).nrow() > 1) {
1614 0 : os << LogIO::NORMAL4 << "Multiple fields selected" << LogIO::POST;
1615 0 : multiFields_p = true;
1616 : } else {
1617 0 : os << LogIO::NORMAL4 << "Single field selected" << LogIO::POST;
1618 0 : multiFields_p = false;
1619 : }
1620 : }
1621 :
1622 0 : uInt nvis_all = ms_p->nrow();
1623 :
1624 : // Now create the VisSet
1625 0 : this->makeVisSet(*mssel_p);
1626 0 : AlwaysAssert(rvi_p, AipsError);
1627 0 : uInt nvis_sel = mssel_p->nrow();
1628 :
1629 0 : if(nvis_sel != nvis_all) {
1630 : os << LogIO::NORMAL // Loglevel INFO
1631 : << "Selected " << nvis_sel << " out of "
1632 : << nvis_all << " rows."
1633 0 : << LogIO::POST;
1634 : }
1635 : else {
1636 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1637 0 : << "Selected all " << nvis_sel << " rows" << LogIO::POST; // Loglevel INFO
1638 : }
1639 : // }
1640 :
1641 : // Tell the user how many channels have been selected.
1642 : // NOTE : This code is replicated in ImagerMultiMS.cc.
1643 0 : Vector<Int> chancounts(dataspectralwindowids_p.nelements());
1644 0 : chancounts=0;
1645 : // if( local_spwstring == "" ) os << "Selected all spws and channels" << LogIO::POST;
1646 : //else os << "Channel selection : " << local_spwstring << LogIO::POST;
1647 0 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL) << "Selected:";
1648 0 : for(uInt k=0;k<dataspectralwindowids_p.nelements();k++)
1649 : {
1650 0 : for(uInt ch=0;ch<uInt(nchanvec(dataspectralwindowids_p[k]));ch++)
1651 0 : {if(spwchansels_p(0,dataspectralwindowids_p[k],ch)) chancounts[k]++; }
1652 0 : os << " [" << chancounts[k] << " chans in spw " << dataspectralwindowids_p[k] << "]";
1653 : // os << "Selected " << chancounts[k] << " channels in spw "
1654 : // << dataspectralwindowids_p[k] << LogIO::POST;
1655 : }
1656 0 : os << LogIO::POST;
1657 :
1658 : // Now we do a selection to cut down the amount of information
1659 : // passed around.
1660 :
1661 0 : this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
1662 0 : dataNchan_p, dataStart_p, dataStep_p,
1663 0 : mDataStart_p, mDataStep_p);
1664 : ///Tell iterator to use on the fly imaging weights if scratch columns is
1665 : ///not in use
1666 0 : imwgt_p=VisImagingWeight("natural");
1667 0 : rvi_p->useImagingWeight(imwgt_p);
1668 :
1669 : // Guess that the beam is no longer valid
1670 0 : beamValid_p=false;
1671 0 : destroySkyEquation();
1672 0 : if(!valid()){
1673 0 : this->unlock();
1674 : os << LogIO::SEVERE << "Check your data selection or Measurement set "
1675 0 : << LogIO::EXCEPTION;
1676 0 : return false;
1677 : }
1678 0 : this->unlock();
1679 0 : return !nullSelect_p;
1680 0 : } catch (AipsError x) {
1681 0 : this->unlock();
1682 0 : throw(x);
1683 :
1684 : return false;
1685 0 : }
1686 : return !nullSelect_p;
1687 0 : }
1688 :
1689 :
1690 0 : Bool Imager::setmfcontrol(const Float cyclefactor,
1691 : const Float cyclespeedup,
1692 : const Float cyclemaxpsffraction,
1693 : const Int stoplargenegatives,
1694 : const Int stoppointmode,
1695 : const String& scaleType,
1696 : const Float minPB,
1697 : const Float constPB,
1698 : const Vector<String>& fluxscale,
1699 : const Bool flatnoise)
1700 : {
1701 0 : cyclefactor_p = cyclefactor;
1702 0 : cyclespeedup_p = cyclespeedup;
1703 0 : cyclemaxpsffraction_p = cyclemaxpsffraction;
1704 0 : stoplargenegatives_p = stoplargenegatives;
1705 0 : stoppointmode_p = stoppointmode;
1706 0 : fluxscale_p.resize( fluxscale.nelements() );
1707 0 : fluxscale_p = fluxscale;
1708 0 : scaleType_p = scaleType;
1709 0 : minPB_p = minPB;
1710 0 : flatnoise_p=flatnoise;
1711 :
1712 0 : constPB_p = constPB;
1713 0 : return true;
1714 : }
1715 :
1716 :
1717 0 : Bool Imager::setvp(const Bool dovp,
1718 : const Bool doDefaultVPs,
1719 : const String& vpTable,
1720 : const Bool doSquint,
1721 : const Quantity &parAngleInc,
1722 : const Quantity &skyPosThreshold,
1723 : String defaultTel,
1724 : const Bool verbose)
1725 : {
1726 :
1727 0 : LogIO os(LogOrigin("Imager", "setvp()", WHERE));
1728 :
1729 0 : os << LogIO::NORMAL << "Setting voltage pattern parameters" << LogIO::POST; // Loglevel PROGRESS
1730 :
1731 0 : if(!dovp && !vp_p)
1732 0 : delete vp_p;
1733 0 : vp_p=0;
1734 0 : doVP_p=dovp;
1735 0 : doDefaultVP_p = doDefaultVPs;
1736 0 : vpTableStr_p = vpTable;
1737 0 : telescope_p= defaultTel;
1738 0 : if (doSquint) {
1739 0 : squintType_p = BeamSquint::GOFIGURE;
1740 : } else {
1741 0 : squintType_p = BeamSquint::NONE;
1742 : }
1743 :
1744 0 : parAngleInc_p = parAngleInc;
1745 :
1746 0 : skyPosThreshold_p = skyPosThreshold;
1747 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1748 : <<"Sky position tolerance is "<<skyPosThreshold_p.getValue("deg")
1749 0 : << " degrees" << LogIO::POST;
1750 :
1751 0 : if (doDefaultVP_p) {
1752 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1753 0 : << "Using system default voltage patterns for each telescope" << LogIO::POST;
1754 : } else {
1755 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1756 : << "Using user defined voltage patterns in Table "
1757 0 : << vpTableStr_p << LogIO::POST;
1758 : }
1759 0 : if (doSquint) {
1760 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1761 0 : << "Beam Squint will be included in the VP model" << LogIO::POST;
1762 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3)
1763 : << "and the Parallactic Angle increment is " // Loglevel INFO
1764 0 : << parAngleInc_p.getValue("deg") << " degrees" << LogIO::POST;
1765 : }
1766 :
1767 : // muddled with the state of SkyEquation..so redo it
1768 0 : destroySkyEquation();
1769 0 : return true;
1770 0 : }
1771 :
1772 0 : Bool Imager::setoptions(const String& ftmachine, const Long cache, const Int tile,
1773 : const String& gridfunction, const MPosition& mLocation,
1774 : const Float padding,
1775 : const Int wprojplanes,
1776 : const String& epJTableName,
1777 : const Bool applyPointingOffsets,
1778 : const Bool doPointingCorrection,
1779 : const String& cfCacheDirName,
1780 : const Float& rotPAStep,
1781 : const Float& computePAStep,
1782 : const Float& pbLimit, const String& interpMeth, const Int imageTileVol,
1783 : const Bool singprec,
1784 : const Int numthreads,
1785 : const Bool psTermOn,
1786 : const Bool aTermOn,
1787 : const Bool mTermOn,
1788 : const Bool wbawp,
1789 : const Bool conjBeams)
1790 : {
1791 0 : if(!valid())
1792 : {
1793 0 : return false;
1794 : }
1795 0 : if(!assertDefinedImageParameters())
1796 : {
1797 0 : return false;
1798 : }
1799 0 : LogIO os(LogOrigin("imager", "setoptions()", WHERE));
1800 :
1801 0 : os << LogIO::NORMAL << "Setting processing options" << LogIO::POST; // Loglevel PROGRESS
1802 :
1803 0 : ftmachine_p=downcase(ftmachine);
1804 0 : if(ftmachine_p=="gridft") {
1805 : os << LogIO::WARN
1806 : << "FT machine gridft is now called ft - please use the new name in future"
1807 0 : << LogIO::POST;
1808 0 : ftmachine_p="ft";
1809 : }
1810 :
1811 0 : if(ftmachine_p=="wfmemoryft"){
1812 0 : wfGridding_p=true;
1813 0 : ftmachine_p="ft";
1814 : }
1815 :
1816 0 : wprojPlanes_p=wprojplanes;
1817 0 : epJTableName_p = epJTableName;
1818 0 : cfCacheDirName_p = cfCacheDirName;
1819 0 : rotPAStep_p = rotPAStep;
1820 0 : computePAStep_p = computePAStep;
1821 0 : pbLimit_p = pbLimit;
1822 0 : psTermOn_p=psTermOn;
1823 0 : aTermOn_p=aTermOn;
1824 0 : mTermOn_p=mTermOn;
1825 0 : wbAWP_p=wbawp;
1826 0 : conjBeams_p=conjBeams;
1827 0 : freqInterpMethod_p=interpMeth;
1828 0 : imageTileVol_p=imageTileVol;
1829 0 : if(imageTileVol_p <= 0){
1830 0 : avoidTempLatt_p=true;
1831 0 : imageTileVol_p=-1*imageTileVol_p;
1832 : }
1833 :
1834 :
1835 0 : singlePrec_p=singprec;
1836 :
1837 0 : if(cache>0) cache_p=cache;
1838 0 : if(tile>0) tile_p=tile;
1839 0 : gridfunction_p=downcase(gridfunction);
1840 0 : mLocation_p=mLocation;
1841 0 : if(padding>=1.0) {
1842 0 : padding_p=padding;
1843 : }
1844 :
1845 : // Check if gridfunction is set to gauss or gjinc for non single dish imaging
1846 0 : if (ftmachine_p!="sd"
1847 0 : && (gridfunction_p=="gauss" || gridfunction_p=="gjinc")) {
1848 : os << LogIO::SEVERE
1849 0 : << "Grid function " << gridfunction << " is available only for single dish imaging" << LogIO::EXCEPTION;
1850 : }
1851 :
1852 : // Destroy the FTMachine
1853 0 : if(ft_p) {delete ft_p; ft_p=0;}
1854 0 : if(gvp_p) {delete gvp_p; gvp_p=0;}
1855 0 : if(cft_p) {delete cft_p; cft_p=0;}
1856 :
1857 0 : doPointing = applyPointingOffsets;
1858 0 : doPBCorr = doPointingCorrection;
1859 : ////The set below does not seemed to be remembered later in the process it
1860 : /// under some compiler version so setting a private variable to be used
1861 : /// a negative number means use all that is available
1862 0 : numthreads_p= numthreads;
1863 : #ifdef _OPENMP
1864 0 : if(numthreads > 0){
1865 0 : if(numthreads <= omp_get_max_threads()){
1866 0 : omp_set_num_threads(numthreads);
1867 : }
1868 : }
1869 : #endif
1870 0 : return true;
1871 0 : }
1872 :
1873 0 : Bool Imager::setsdoptions(const Float scale, const Float weight,
1874 : const Int convsupport, String pointCol,
1875 : const Quantity truncate,
1876 : const Quantity gwidth, const Quantity jwidth,
1877 : const Float minweight, const Bool clipminmax,
1878 : const Bool enablecache,
1879 : const String & convertfirst)
1880 : {
1881 0 : LogIO os(LogOrigin("imager", "setsdoptions()", WHERE));
1882 :
1883 0 : os << LogIO::NORMAL << "Setting single dish processing options" << LogIO::POST; // Loglevel PROGRESS
1884 :
1885 0 : sdScale_p=scale;
1886 0 : sdWeight_p=weight;
1887 :
1888 :
1889 0 : sdConvSupport_p=convsupport;
1890 0 : pointingDirCol_p=pointCol;
1891 0 : pointingDirCol_p.upcase();
1892 0 : if( (pointingDirCol_p != "DIRECTION") &&(pointingDirCol_p != "TARGET") && (pointingDirCol_p != "ENCODER") && (pointingDirCol_p != "POINTING_OFFSET") && (pointingDirCol_p != "SOURCE_OFFSET")){
1893 : os << LogIO::SEVERE
1894 0 : << "No such direction column as "<< pointingDirCol_p
1895 0 : << " in pointing table "<< LogIO::EXCEPTION;
1896 : }
1897 0 : qtruncate_p=truncate;
1898 0 : qgwidth_p=gwidth;
1899 0 : qjwidth_p=jwidth;
1900 0 : minWeight_p = minweight;
1901 0 : clipminmax_p = clipminmax;
1902 0 : enablecache_p = enablecache;
1903 0 : convertfirst_p = convertfirst;
1904 0 : convertfirst_p.upcase();
1905 :
1906 :
1907 : // Destroy the FTMachine
1908 0 : if(ft_p) {delete ft_p; ft_p=0;}
1909 0 : if(gvp_p) {delete gvp_p; gvp_p=0;}
1910 0 : if(cft_p) {delete cft_p; cft_p=0;}
1911 :
1912 0 : return true;
1913 0 : }
1914 :
1915 0 : Bool Imager::mask(const String& mask, const String& image,
1916 : const Quantity& threshold)
1917 : {
1918 : //if(!valid()) return false;
1919 0 : LogIO os(LogOrigin("imager", "mask()", WHERE));
1920 : //if(!assertDefinedImageParameters()) return false;
1921 :
1922 : try {
1923 : //this->lock();
1924 0 : if(image=="") {
1925 : //this->unlock();
1926 0 : os << LogIO::SEVERE << "Need name for template image" << LogIO::EXCEPTION;
1927 0 : return false;
1928 : }
1929 0 : String maskName(mask);
1930 0 : if(maskName=="") {
1931 0 : maskName=image+".mask";
1932 : }
1933 0 : if(!clone(image, maskName)) return false;
1934 0 : PagedImage<Float> maskImage(maskName);
1935 0 : maskImage.table().markForDelete();
1936 0 : PagedImage<Float> imageImage(image);
1937 :
1938 0 : if(threshold.check(UnitVal(1.0, "Jy"))){
1939 : os << LogIO::NORMAL // Loglevel INFO
1940 : << "Making mask image " << maskName << ", applying threshold "
1941 0 : << threshold.get("Jy").getValue() << "Jy, " << endl
1942 0 : << "to template image " << image << LogIO::POST;
1943 :
1944 0 : StokesImageUtil::MaskFrom(maskImage, imageImage, threshold);
1945 : }
1946 : else{
1947 : os << LogIO::NORMAL // Loglevel INFO
1948 : << "Making mask image " << maskName << ", applying threshold "
1949 0 : << threshold.getValue() << " " << threshold.getUnit() << endl
1950 0 : << "to template image " << image << LogIO::POST;
1951 :
1952 0 : StokesImageUtil::MaskFrom(maskImage, imageImage, threshold.getValue());
1953 : }
1954 0 : maskImage.table().unmarkForDelete();
1955 :
1956 : //this->lock();
1957 0 : return true;
1958 0 : } catch (AipsError x) {
1959 : //this->unlock();
1960 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1961 0 : << LogIO::EXCEPTION;
1962 0 : return false;
1963 0 : }
1964 : //this->unlock();
1965 : return true;
1966 0 : }
1967 :
1968 0 : Bool Imager::boxmask(const String& mask, const Vector<Int>& blc,
1969 : const Vector<Int>& trc, const Float value)
1970 : {
1971 0 : if(!valid()) return false;
1972 :
1973 0 : LogIO os(LogOrigin("imager", "boxmask()", WHERE));
1974 :
1975 : try {
1976 :
1977 0 : if(!assertDefinedImageParameters()) return false;
1978 :
1979 0 : if(mask=="") {
1980 0 : os << LogIO::SEVERE << "Need name for mask image" << LogIO::EXCEPTION;
1981 0 : return false;
1982 : }
1983 0 : if(!Table::isWritable(mask)) {
1984 0 : make(mask);
1985 0 : this->lock();
1986 : }
1987 0 : PagedImage<Float> maskImage(mask);
1988 0 : maskImage.table().markForDelete();
1989 :
1990 :
1991 0 : IPosition iblc(blc);
1992 0 : IPosition itrc(trc);
1993 0 : IPosition iinc(iblc.nelements(), 1);
1994 0 : LCBox::verify(iblc, itrc, iinc, maskImage.shape());
1995 :
1996 : os << LogIO::DEBUG1
1997 : << "Setting '" << mask << "' blc=" << iblc
1998 0 : << " trc=" << itrc << " to " << value << LogIO::POST;
1999 :
2000 0 : StokesImageUtil::BoxMask(maskImage, iblc, itrc, value);
2001 :
2002 0 : maskImage.table().unmarkForDelete();
2003 :
2004 0 : this->unlock();
2005 0 : return true;
2006 0 : } catch (AipsError x) {
2007 0 : this->unlock();
2008 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2009 0 : << LogIO::EXCEPTION;
2010 0 : return false;
2011 0 : }
2012 : return true;
2013 0 : }
2014 :
2015 0 : Bool Imager::regionmask(const String& maskimage, Record* imageRegRec,
2016 : Matrix<Quantity>& blctrcs, Matrix<Float>& circles,
2017 : const Float& value){
2018 :
2019 : //This function does not modify ms(s) so no need of lock
2020 0 : LogIO os(LogOrigin("imager", "regionmask()", WHERE));
2021 0 : if(!Table::isWritable(maskimage)) {
2022 0 : make(maskimage);
2023 : }
2024 0 : return Imager::regionToImageMask(maskimage, imageRegRec, blctrcs, circles, value);
2025 :
2026 0 : }
2027 :
2028 0 : Bool Imager::regionToImageMask(const String& maskimage, Record* imageRegRec, Matrix<Quantity>& blctrcs, Matrix<Float>& circles, const Float& value){
2029 0 : PagedImage<Float> maskImage(maskimage);
2030 0 : CoordinateSystem cSys=maskImage.coordinates();
2031 0 : maskImage.table().markForDelete();
2032 0 : ImageRegion *boxregions=0;
2033 0 : ImageRegion *circleregions=0;
2034 0 : RegionManager regMan;
2035 0 : regMan.setcoordsys(cSys);
2036 0 : Vector<Quantum<Double> > blc(2);
2037 0 : Vector<Quantum<Double> > trc(2);
2038 0 : if(blctrcs.nelements() !=0){
2039 0 : if(blctrcs.shape()(1) != 4)
2040 0 : throw(AipsError("Need a list of 4 elements to define a box"));
2041 0 : Int nrow=blctrcs.shape()(0);
2042 0 : Vector<Int> absRel(2, RegionType::Abs);
2043 0 : PtrBlock<const WCRegion *> lesbox(nrow);
2044 0 : for (Int k=0; k < nrow; ++k){
2045 0 : blc(0) = blctrcs(k,0);
2046 0 : blc(1) = blctrcs(k,1);
2047 0 : trc(0) = blctrcs(k,2);
2048 0 : trc(1) = blctrcs(k,3);
2049 0 : lesbox[k]= new WCBox (blc, trc, cSys, absRel);
2050 : }
2051 0 : boxregions=regMan.doUnion(lesbox);
2052 0 : for (Int k=0; k < nrow; ++k){
2053 0 : delete lesbox[k];
2054 : }
2055 0 : }
2056 0 : if((circles.nelements()) > 0){
2057 0 : if(circles.shape()(1) != 3)
2058 0 : throw(AipsError("Need a list of 3 elements to define a circle"));
2059 0 : Int nrow=circles.shape()(0);
2060 0 : Vector<Float> cent(2);
2061 0 : cent(0)=circles(0,1); cent(1)=circles(0,2);
2062 0 : Float radius=circles(0,0);
2063 0 : IPosition xyshape(2,maskImage.shape()(0),maskImage.shape()(1));
2064 0 : LCEllipsoid *circ= new LCEllipsoid(cent, radius, xyshape);
2065 : //Tell LCUnion to delete the pointers
2066 0 : LCUnion *elunion= new LCUnion(true, circ);
2067 : //now lets do the remainder
2068 0 : for (Int k=1; k < nrow; ++k){
2069 0 : cent(0)=circles(k,1); cent(1)=circles(k,2);
2070 0 : radius=circles(k,0);
2071 0 : circ= new LCEllipsoid(cent, radius, xyshape);
2072 0 : elunion=new LCUnion(true, elunion, circ);
2073 : }
2074 : //now lets extend that to the whole image
2075 0 : IPosition trc(2);
2076 0 : trc(0)=maskImage.shape()(2)-1;
2077 0 : trc(1)=maskImage.shape()(3)-1;
2078 0 : LCBox lbox(IPosition(2,0,0), trc,
2079 0 : IPosition(2,maskImage.shape()(2),maskImage.shape()(3)) );
2080 0 : LCExtension linter(*elunion, IPosition(2,2,3),lbox);
2081 0 : circleregions=new ImageRegion(linter);
2082 0 : delete elunion;
2083 0 : }
2084 :
2085 :
2086 0 : ImageRegion* recordRegion=0;
2087 0 : if(imageRegRec !=0){
2088 0 : TableRecord rec1;
2089 0 : rec1.assign(*imageRegRec);
2090 0 : recordRegion=ImageRegion::fromRecord(rec1,"");
2091 0 : }
2092 0 : ImageRegion *unionReg=0;
2093 0 : if(boxregions!=0 && recordRegion!=0){
2094 0 : unionReg=regMan.doUnion(*boxregions, *recordRegion);
2095 0 : delete boxregions; boxregions=0;
2096 0 : delete recordRegion; recordRegion=0;
2097 : }
2098 0 : else if(boxregions !=0){
2099 0 : unionReg=boxregions;
2100 : }
2101 0 : else if(recordRegion !=0){
2102 0 : unionReg=recordRegion;
2103 : }
2104 :
2105 :
2106 :
2107 :
2108 0 : if(unionReg !=0){
2109 0 : regionToMask(maskImage, *unionReg, value);
2110 0 : delete unionReg; unionReg=0;
2111 : }
2112 : //As i can't unionize LCRegions and WCRegions; do circles seperately
2113 0 : if(circleregions !=0){
2114 0 : regionToMask(maskImage, *circleregions, value);
2115 0 : delete circleregions;
2116 0 : circleregions=0;
2117 : }
2118 0 : maskImage.table().unmarkForDelete();
2119 0 : return true;
2120 :
2121 0 : }
2122 :
2123 :
2124 0 : Bool Imager::regionToMask(ImageInterface<Float>& maskImage, ImageRegion& imagreg, const Float& value){
2125 :
2126 :
2127 0 : SubImage<Float> partToMask(maskImage, imagreg, true);
2128 0 : LatticeRegion latReg=imagreg.toLatticeRegion(maskImage.coordinates(), maskImage.shape());
2129 0 : ArrayLattice<Bool> pixmask(latReg.get());
2130 0 : LatticeExpr<Float> myexpr(iif(pixmask, value, partToMask) );
2131 0 : partToMask.copyData(myexpr);
2132 :
2133 0 : return true;
2134 0 : }
2135 :
2136 :
2137 0 : Bool Imager::clipimage(const String& image, const Quantity& threshold)
2138 : {
2139 0 : if(!valid()) return false;
2140 :
2141 0 : LogIO os(LogOrigin("imager", "clipimage()", WHERE));
2142 :
2143 0 : this->lock();
2144 : try {
2145 :
2146 0 : if(!assertDefinedImageParameters()) return false;
2147 :
2148 0 : if(image=="") {
2149 0 : this->unlock();
2150 0 : os << LogIO::SEVERE << "Need name for image" << LogIO::EXCEPTION;
2151 0 : return false;
2152 : }
2153 0 : PagedImage<Float> imageImage(image);
2154 : os << LogIO::NORMAL // Loglevel PROGRESS
2155 : << "Zeroing " << image << ", for all pixels where Stokes I < threshold "
2156 0 : << threshold.get("Jy").getValue() << "Jy " << LogIO::POST;
2157 :
2158 0 : StokesImageUtil::MaskOnStokesI(imageImage, threshold);
2159 0 : this->unlock();
2160 0 : return true;
2161 0 : } catch (AipsError x) {
2162 0 : this->unlock();
2163 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2164 0 : << LogIO::EXCEPTION;
2165 0 : return false;
2166 0 : }
2167 :
2168 : return true;
2169 0 : }
2170 :
2171 : // Add together low and high resolution images in the Fourier plane
2172 0 : Bool Imager::feather(const String& image, const String& highRes,
2173 : const String& lowRes, const String& lowPSF, const Float effDishDiam, const Bool lowPassFilterSD)
2174 : {
2175 :
2176 0 : Float effDiam=effDishDiam;
2177 0 : LoggerHolder lh (false);
2178 0 : LogIO os = lh.logio();
2179 0 : os << LogOrigin("imager", "feather()");
2180 :
2181 : try {
2182 0 : Bool noStokes=false;
2183 0 : String outLowRes=lowRes;
2184 0 : String outHighRes=highRes;
2185 : {
2186 0 : if ( ! doVP_p ) {
2187 0 : this->unlock();
2188 : os << LogIO::SEVERE <<
2189 : "Must invoke setvp() first in order to apply the primary beam"
2190 0 : << LogIO::EXCEPTION;
2191 0 : return false;
2192 : }
2193 :
2194 : os << LogIO::NORMAL // Loglevel PROGRESS
2195 0 : << "\nFeathering together high and low resolution images.\n" << LogIO::POST;
2196 :
2197 :
2198 : // Get initial images
2199 : /*{ //Drat lets deal with images that don't have stokes.
2200 : PagedImage<Float> hightemp(highRes);
2201 : PagedImage<Float> lowtemp(lowRes);
2202 : if(hightemp.shape().nelements() != lowtemp.shape().nelements()){
2203 : this->unlock();
2204 : os << LogIO::SEVERE <<
2205 : "High res. image and low res. image donot have same number of axes"
2206 : << LogIO::EXCEPTION;
2207 : return false;
2208 :
2209 : }
2210 : if ( (hightemp.coordinates().findCoordinate(Coordinate::STOKES) < 0) &&
2211 : (lowtemp.coordinates().findCoordinate(Coordinate::STOKES) < 0)){
2212 : noStokes=true;
2213 : os << LogIO::NORMAL // Loglevel PROGRESS
2214 : << "Making some temporary images as the inputs have no Stokes axis.\n"
2215 : << LogIO::POST;
2216 : std::unique_ptr<ImageInterface<Float> > outImage1;
2217 : outHighRes= highRes+"_stokes";
2218 : ImageUtilities::addDegenerateAxes (os, outImage1, hightemp, outHighRes,
2219 : false, false,
2220 : "I", false, false,
2221 : false);
2222 :
2223 : std::unique_ptr<ImageInterface<Float> > outImage2;
2224 : outLowRes= lowRes+"_stokes";
2225 : ImageUtilities::addDegenerateAxes (os, outImage2, lowtemp, outLowRes,
2226 : false, false,
2227 : "I", false, false,
2228 : false);
2229 :
2230 : }
2231 : }*/
2232 0 : PagedImage<Float> high(outHighRes);
2233 0 : PagedImage<Float> low0(outLowRes);
2234 :
2235 0 : Feather::feather(image, high, low0, sdScale_p, lowPSF, doDefaultVP_p, vpTableStr_p, effDiam, lowPassFilterSD);
2236 0 : }
2237 :
2238 0 : if(noStokes){
2239 0 : TableUtil::deleteTable(outHighRes);
2240 0 : TableUtil::deleteTable(outLowRes);
2241 : }
2242 0 : return true;
2243 0 : } catch (AipsError x) {
2244 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2245 0 : << LogIO::EXCEPTION;
2246 0 : return false;
2247 0 : }
2248 :
2249 : return true;
2250 0 : }
2251 :
2252 :
2253 :
2254 0 : Bool Imager::linearmosaic(const String& mosaic,
2255 : const String& fluxscale,
2256 : const String& sensitivity,
2257 : const Vector<String>& images,
2258 : const Vector<Int>& fieldids)
2259 :
2260 : {
2261 0 : if(!valid()) return false;
2262 0 : LogIO os(LogOrigin("imager", "linearmosaic()", WHERE));
2263 : try{
2264 0 : if(mosaic=="") {
2265 0 : os << LogIO::SEVERE << "Need name for mosaic image" << LogIO::POST;
2266 0 : return false;
2267 : }
2268 0 : if(!Table::isWritable( mosaic )) {
2269 0 : make( mosaic );
2270 : }
2271 0 : if (images.nelements() == 0) {
2272 0 : os << LogIO::SEVERE << "Need names of images to mosaic" << LogIO::POST;
2273 0 : return false;
2274 : }
2275 0 : if (images.nelements() != fieldids.nelements()) {
2276 : os << LogIO::SEVERE << "number of fieldids doesn\'t match the"
2277 0 : << " number of images" << LogIO::POST;
2278 0 : return false;
2279 : }
2280 :
2281 0 : Double meminMB=Double(HostInfo::memoryTotal(true))/1024.0;
2282 0 : PagedImage<Float> mosaicImage( mosaic );
2283 0 : CoordinateSystem cs=mosaicImage.coordinates();
2284 0 : String err;
2285 : //for some reason subimages below fail if they are in some frames like BARY
2286 0 : if(cs.setSpectralConversion(err, "LSRK")){
2287 0 : mosaicImage.setCoordinateInfo(cs);
2288 : }
2289 0 : mosaicImage.set(0.0);
2290 0 : TempImage<Float> numerator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
2291 0 : numerator.set(0.0);
2292 0 : TempImage<Float> denominator( TiledShape(mosaicImage.shape(), mosaicImage.niceCursorShape()), mosaicImage.coordinates(), meminMB/2.0);
2293 0 : denominator.set(0.0);
2294 0 : ImageRegrid<Float> regridder;
2295 :
2296 0 : MSColumns msc(*ms_p);
2297 0 : for (uInt i=0; i < images.nelements(); ++i) {
2298 0 : if(!Table::isReadable(images(i))) {
2299 : os << LogIO::SEVERE << "Image " << images(i) <<
2300 0 : " is not readable" << LogIO::POST;
2301 0 : return false;
2302 : }
2303 :
2304 0 : PagedImage<Float> smallImagedisk( images(i) );
2305 0 : cs=smallImagedisk.coordinates();
2306 : //for some reason subimages below fail if they are in some frames like BARY
2307 0 : if(!cs.setSpectralConversion(err, "LSRK")){
2308 0 : cs=smallImagedisk.coordinates();
2309 : }
2310 :
2311 0 : TempImage<Float> smallImage(smallImagedisk.shape(), cs, meminMB/8.0);
2312 0 : smallImage.copyData(smallImagedisk);
2313 0 : IPosition iblc(smallImage.shape().nelements(),0);
2314 0 : IPosition itrc(smallImage.shape());
2315 0 : itrc=itrc-Int(1);
2316 :
2317 0 : LCBox lbox(iblc, itrc, smallImage.shape());
2318 0 : ImageRegion imagreg(WCBox(lbox, cs) );
2319 : try{
2320 : // accumulate the images
2321 0 : SubImage<Float> subNum;
2322 0 : SubImage<Float> subDen;
2323 : try{
2324 0 : subNum=SubImage<Float>(numerator, imagreg, true);
2325 0 : subDen=SubImage<Float>(denominator, imagreg, true);
2326 : }
2327 0 : catch(...){
2328 : //Failed to make a subimage let us use the full image
2329 0 : subNum=SubImage<Float>(numerator, true);
2330 0 : subDen=SubImage<Float>(denominator, true);
2331 :
2332 0 : }
2333 :
2334 :
2335 :
2336 0 : TempImage<Float> fullImage(subNum.shape(), subNum.coordinates(), meminMB/8.0);
2337 :
2338 0 : os << "Processing Image " << images(i) << LogIO::POST;
2339 :
2340 0 : regridder.regrid( fullImage, Interpolate2D::LINEAR,
2341 0 : IPosition(2,0,1), smallImage );
2342 :
2343 0 : TempImage<Float> PB( subNum.shape(), subNum.coordinates(), meminMB/8.0);
2344 0 : PB.set(1.0);
2345 :
2346 0 : MDirection pointingDirection = msc.field().phaseDirMeas( fieldids(i) );
2347 :
2348 0 : Quantity pa(0.0, "deg");
2349 0 : pbguts ( PB, PB, pointingDirection, pa);
2350 :
2351 0 : fullImage.copyData( (LatticeExpr<Float>) (fullImage * PB ) );
2352 0 : subNum.copyData( (LatticeExpr<Float>) (subNum + fullImage) );
2353 0 : subDen.copyData( (LatticeExpr<Float>) (subDen + (PB*PB)) );
2354 :
2355 0 : }
2356 0 : catch (AipsError x) {
2357 : os << LogIO::WARN<< "Caught exception while processing " << images(i)
2358 : << "\n"<< x.getMesg()
2359 0 : << LogIO::POST;
2360 0 : continue;
2361 0 : }
2362 0 : catch(...){
2363 0 : os << LogIO::WARN << "Unknown error processing " << images(i) << LogIO::POST;
2364 0 : continue;
2365 0 : }
2366 0 : }
2367 :
2368 0 : LatticeExprNode LEN = max( denominator );
2369 0 : Float dMax = LEN.getFloat();
2370 :
2371 :
2372 0 : if (scaleType_p == "SAULT") {
2373 :
2374 : // truncate denominator at ggSMin1
2375 0 : denominator.copyData( (LatticeExpr<Float>)
2376 0 : (iif(denominator < (dMax * constPB_p), dMax,
2377 : denominator) ) );
2378 :
2379 0 : if (fluxscale != "") {
2380 0 : clone( mosaic, fluxscale );
2381 :
2382 0 : PagedImage<Float> fluxscaleImage( fluxscale );
2383 0 : fluxscaleImage.copyData( (LatticeExpr<Float>)
2384 0 : (iif(denominator < (dMax*minPB_p), 0.0,
2385 0 : (dMax*minPB_p)/(denominator) )) );
2386 0 : fluxscaleImage.copyData( (LatticeExpr<Float>)
2387 0 : (iif(denominator > (dMax*constPB_p), 1.0,
2388 : (fluxscaleImage) )) );
2389 0 : mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
2390 0 : (numerator/denominator), 0)) );
2391 0 : }
2392 : } else {
2393 0 : mosaicImage.copyData( (LatticeExpr<Float>)(iif(denominator > (dMax*minPB_p),
2394 0 : (numerator/denominator), 0)) );
2395 0 : if (fluxscale != "") {
2396 0 : clone(mosaic, fluxscale );
2397 0 : PagedImage<Float> fluxscaleImage( fluxscale );
2398 0 : fluxscaleImage.copyData( (LatticeExpr<Float>)( 1.0 ) );
2399 0 : }
2400 : }
2401 0 : if (sensitivity != "") {
2402 0 : clone(mosaic, sensitivity);
2403 0 : PagedImage<Float> sensitivityImage( sensitivity );
2404 0 : sensitivityImage.copyData( (LatticeExpr<Float>)( denominator/dMax ));
2405 0 : }
2406 0 : }
2407 0 : catch (AipsError x) {
2408 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2409 0 : << LogIO::POST;
2410 0 : return false;
2411 0 : }
2412 0 : return true;
2413 0 : }
2414 :
2415 : // Weight the MeasurementSet
2416 0 : Bool Imager::weight(const String& type, const String& crmode,
2417 : const Quantity& noise, const Double robust,
2418 : const Quantity& fieldofview,
2419 : const Int npixels, const Bool multiField)
2420 : {
2421 0 : if(!valid()) return false;
2422 0 : logSink_p.clearLocally();
2423 0 : LogIO os(LogOrigin("imager", "weight()"),logSink_p);
2424 :
2425 0 : this->lock();
2426 : try {
2427 :
2428 0 : String rmode=crmode; // can change it
2429 :
2430 :
2431 : os << LogIO::NORMAL // Loglevel INFO
2432 0 : << "Weighting MS: Imaging weights will be changed" << LogIO::POST;
2433 :
2434 0 : if (type=="natural") {
2435 : os << LogIO::NORMAL // Loglevel INFO
2436 0 : << "Natural weighting" << LogIO::POST;
2437 0 : imwgt_p=VisImagingWeight("natural");
2438 : }
2439 0 : else if(type=="superuniform"){
2440 0 : if(!assertDefinedImageParameters()) return false;
2441 : ///making usage of npixels consistent with uniform, briggs
2442 : /// don't know why this was done seperately which is kind of redundant in the code
2443 : /// one achieves superuniform with just uniform with npixels or fieldofview
2444 : /// set to non-defaults in the section below
2445 0 : Int actualNpix=npixels/2;
2446 0 : if(actualNpix <=0)
2447 0 : actualNpix=3;
2448 : os << LogIO::NORMAL // Loglevel INFO
2449 : << "SuperUniform weighting over a square cell spanning ["
2450 : << -actualNpix
2451 0 : << ", " << actualNpix << "] in the uv plane" << LogIO::POST;
2452 0 : imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust, nx_p,
2453 0 : ny_p, mcellx_p, mcelly_p, actualNpix,
2454 0 : actualNpix, multiField);
2455 : }
2456 0 : else if ((type=="robust")||(type=="uniform")||(type=="briggs")) {
2457 0 : if(!assertDefinedImageParameters()) return false;
2458 0 : Quantity actualFieldOfView(fieldofview);
2459 0 : Int actualNPixels(npixels);
2460 0 : String wtype;
2461 0 : if(type=="briggs") {
2462 : //The user really meant to use Brigg's weighting and forgot to set norm or abs
2463 : // guessing it should be norm
2464 0 : if(rmode=="none")
2465 0 : rmode="norm";
2466 0 : wtype = "Briggs";
2467 : }
2468 : else {
2469 0 : wtype = "Uniform";
2470 : }
2471 0 : if(actualFieldOfView.get().getValue()==0.0&&actualNPixels==0) {
2472 0 : actualNPixels=nx_p;
2473 0 : actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
2474 0 : "rad");
2475 : os << LogIO::NORMAL // Loglevel INFO
2476 : << wtype
2477 : << " weighting: sidelobes will be suppressed over full image"
2478 0 : << LogIO::POST;
2479 : }
2480 0 : else if(actualFieldOfView.get().getValue()>0.0&&actualNPixels==0) {
2481 0 : actualNPixels=Int(actualFieldOfView.get("rad").getValue()/mcellx_p.get("rad").getValue());
2482 : os << LogIO::NORMAL // Loglevel INFO
2483 : << wtype
2484 : << " weighting: sidelobes will be suppressed over specified field of view: "
2485 0 : << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
2486 : }
2487 0 : else if(actualFieldOfView.get().getValue()==0.0&&actualNPixels>0) {
2488 0 : actualFieldOfView=Quantity(actualNPixels*mcellx_p.get("rad").getValue(),
2489 0 : "rad");
2490 : os << LogIO::NORMAL // Loglevel INFO
2491 : << wtype
2492 : << " weighting: sidelobes will be suppressed over full image field of view: "
2493 0 : << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
2494 : }
2495 : else {
2496 : os << LogIO::NORMAL // Loglevel INFO
2497 : << wtype
2498 : << " weighting: sidelobes will be suppressed over specified field of view: "
2499 0 : << actualFieldOfView.get("arcsec").getValue() << " arcsec" << LogIO::POST;
2500 : }
2501 : os << LogIO::DEBUG1
2502 : << "Weighting used " << actualNPixels << " uv pixels."
2503 0 : << LogIO::POST;
2504 0 : Quantity actualCellSize(actualFieldOfView.get("rad").getValue()/actualNPixels, "rad");
2505 :
2506 0 : imwgt_p=VisImagingWeight(*rvi_p, rmode, noise, robust,
2507 : actualNPixels, actualNPixels, actualCellSize,
2508 0 : actualCellSize, 0, 0, multiField);
2509 :
2510 0 : }
2511 0 : else if (type=="radial") {
2512 0 : os << "Radial weighting" << LogIO::POST;
2513 0 : imwgt_p=VisImagingWeight("radial");
2514 : }
2515 : else {
2516 0 : this->unlock();
2517 : os << LogIO::SEVERE << "Unknown weighting " << type
2518 0 : << LogIO::EXCEPTION;
2519 0 : return false;
2520 : }
2521 :
2522 0 : rvi_p->useImagingWeight(imwgt_p);
2523 :
2524 : // Beam is no longer valid
2525 0 : beamValid_p=false;
2526 0 : destroySkyEquation();
2527 0 : this->writeHistory(os);
2528 0 : this->unlock();
2529 0 : return true;
2530 0 : } catch (AipsError x) {
2531 0 : this->unlock();
2532 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2533 0 : << LogIO::EXCEPTION;
2534 0 : return false;
2535 0 : }
2536 :
2537 : return true;
2538 0 : }
2539 :
2540 :
2541 0 : Bool Imager::getWeightGrid(Block<Matrix<Float> >&weightgrid, const String& type, const Vector<String>&imagenames){
2542 :
2543 0 : if(type=="imaging"){
2544 0 : weightgrid.resize(0, true, false);
2545 0 : if(imwgt_p.getType()!="uniform")
2546 0 : return false;
2547 0 : imwgt_p.getWeightDensity(weightgrid);
2548 0 : return true;
2549 : }
2550 0 : if((type=="ftweight") && (sm_p) && (Int(imagenames.nelements())== sm_p->numberOfModels())){
2551 0 : for (Int model=0; model < sm_p->numberOfModels(); ++model){
2552 0 : PagedImage<Float> wgtImage(sm_p->image(model).shape(),
2553 0 : (sm_p->image(model)).coordinates(),
2554 0 : imagenames(model));
2555 0 : se_p->getWeightImage(model, wgtImage);
2556 :
2557 :
2558 0 : }
2559 0 : return true;
2560 : }
2561 :
2562 0 : return false;
2563 : }
2564 :
2565 0 : Bool Imager::setWeightGrid(const Block<Matrix<Float> >& weightgrid, const String& type){
2566 :
2567 0 : if(type=="imaging"){
2568 0 : if(imwgt_p.getType()!="uniform")
2569 0 : return false;
2570 0 : imwgt_p.setWeightDensity(weightgrid);
2571 0 : rvi_p->useImagingWeight(imwgt_p);
2572 : }
2573 :
2574 0 : return true;
2575 : }
2576 :
2577 : // Filter the MeasurementSet
2578 0 : Bool Imager::filter(const String& type, const Quantity& bmaj,
2579 : const Quantity& bmin, const Quantity& bpa)
2580 : {
2581 0 : if(!valid()) return false;
2582 0 : logSink_p.clearLocally();
2583 0 : LogIO os(LogOrigin("imager", "filter()"),logSink_p);
2584 :
2585 0 : this->lock();
2586 : try {
2587 :
2588 : os << LogIO::NORMAL // Loglevel INFO
2589 0 : << "Imaging weights will be tapered" << LogIO::POST;
2590 0 : imwgt_p.setFilter(type, bmaj, bmin, bpa);
2591 0 : rvi_p->useImagingWeight(imwgt_p);
2592 :
2593 : // Beam is no longer valid
2594 0 : beamValid_p=false;
2595 0 : destroySkyEquation();
2596 0 : this->writeHistory(os);
2597 0 : this->unlock();
2598 0 : return true;
2599 0 : } catch (AipsError x) {
2600 0 : this->unlock();
2601 0 : throw(x);
2602 : return false;
2603 0 : }
2604 :
2605 : return true;
2606 0 : }
2607 :
2608 :
2609 : // Implement a uv range
2610 0 : Bool Imager::uvrange(const Double& uvmin, const Double& uvmax)
2611 : {
2612 0 : if(!valid()) return false;
2613 0 : logSink_p.clearLocally();
2614 0 : LogIO os(LogOrigin("imager", "uvrange()"),logSink_p);
2615 :
2616 : try {
2617 : os << LogIO::NORMAL // Loglevel INFO
2618 : << "Selecting data according to uvrange: setdata will reset this selection"
2619 0 : << LogIO::POST;
2620 :
2621 0 : Double auvmin(uvmin);
2622 0 : Double auvmax(uvmax);
2623 :
2624 0 : if(auvmax<=0.0) auvmax=1e10;
2625 0 : if(auvmax>auvmin&&(auvmin>=0.0)) {
2626 : os << LogIO::NORMAL // Loglevel INFO
2627 : << "Allowed uv range: " << auvmin << " to " << auvmax
2628 0 : << " wavelengths" << LogIO::POST;
2629 : }
2630 : else {
2631 : os << LogIO::SEVERE << "Invalid uvmin and uvmax: "
2632 : << auvmin << ", " << auvmax
2633 0 : << LogIO::EXCEPTION;
2634 0 : return false;
2635 : }
2636 0 : Vector<Double> freq;
2637 0 : ostringstream strUVmax, strUVmin, ostrInvLambda;
2638 :
2639 0 : this->lock();
2640 :
2641 0 : if(mssel_p.null()){ os << "Please setdata first before using uvrange " << LogIO::POST; return false; }
2642 :
2643 :
2644 : // use the average wavelength for the selected windows to convert
2645 : // uv-distance from lambda to meters
2646 0 : ostringstream spwsel;
2647 0 : spwsel << "select from $1 where ROWID() IN [";
2648 0 : for(uInt i=0; i < dataspectralwindowids_p.nelements(); ++i) {
2649 0 : if (i > 0) spwsel << ", ";
2650 0 : spwsel << dataspectralwindowids_p(i);
2651 : }
2652 0 : spwsel << "]";
2653 :
2654 0 : MSSpectralWindow msspw(tableCommand(spwsel.str(),
2655 0 : mssel_p->spectralWindow()).table());
2656 0 : MSSpWindowColumns spwc(msspw);
2657 :
2658 : // This averaging scheme will work even if the spectral windows are
2659 : // of different sizes. Note, however, that using an average wavelength
2660 : // may not be a good choice when the total range in frequency is
2661 : // large (e.g. mfs across double sidebands).
2662 0 : uInt nrows = msspw.nrow();
2663 0 : Double ftot = 0.0;
2664 0 : Int nchan = 0;
2665 0 : for(uInt i=0; i < nrows; ++i) {
2666 0 : nchan += (spwc.numChan())(i);
2667 0 : ftot += sum((spwc.chanFreq())(i));
2668 : }
2669 0 : Double invLambda=ftot/(nchan*C::c);
2670 :
2671 : // This is message may not be helpful as mfs is set with setimage()
2672 : // which may sometimes get called after uvrange()
2673 0 : if (nrows > 1 && imageMode_p=="MFS") {
2674 : os << LogIO::WARN
2675 : << "When using mfs over a broad range of frequencies, It is more "
2676 : << "accurate to " << endl
2677 : << "constrain uv-ranges using setdata(); try: " << endl
2678 : << " msselect='(SQUARE(UVW[1]) + SQUARE(UVW[2])) > uvmin && "
2679 : << "(SQUARE(UVW[1]) + SQUARE(UVW[2])) < uvmax'" << endl
2680 : << "where [uvmin, uvmax] is the range given in meters."
2681 0 : << LogIO::POST;
2682 : }
2683 :
2684 0 : invLambda=invLambda*invLambda;
2685 0 : auvmax=auvmax*auvmax;
2686 0 : auvmin=auvmin*auvmin;
2687 0 : strUVmax << auvmax;
2688 0 : strUVmin << auvmin;
2689 0 : ostrInvLambda << invLambda;
2690 0 : String strInvLambda=ostrInvLambda;
2691 : MeasurementSet* mssel_p2;
2692 :
2693 : // Apply the TAQL selection string, to remake the selected MS
2694 0 : String parseString="select from $1 where (SQUARE(UVW[1]) + SQUARE(UVW[2]))*" + (string) strInvLambda + " > " + strUVmin.str( ) + " && (SQUARE(UVW[1]) + SQUARE(UVW[2]))*" + (string) strInvLambda + " < " + strUVmax.str( );
2695 :
2696 0 : mssel_p2=new MeasurementSet(tableCommand(parseString,*mssel_p).table());
2697 0 : AlwaysAssert(mssel_p2, AipsError);
2698 : // Rename the selected MS as */SELECTED_UVRANGE
2699 : //mssel_p2->rename(msname_p+"/SELECTED_UVRANGE", Table::Scratch);
2700 :
2701 0 : if (mssel_p2->nrow()==0) {
2702 : os << LogIO::WARN
2703 : << "Selection string results in empty MS: "
2704 : << "reverting to sorted MeasurementSet"
2705 0 : << LogIO::POST;
2706 0 : delete mssel_p2;
2707 : } else {
2708 0 : if (!mssel_p.null()) {
2709 : os << LogIO::NORMAL // Loglevel INFO
2710 : << "By UVRANGE selection previously selected number of rows "
2711 0 : << mssel_p->nrow() << " are now reduced to "
2712 0 : << mssel_p2->nrow() << LogIO::POST;
2713 : //delete mssel_p;
2714 0 : mssel_p=mssel_p2;
2715 0 : mssel_p->flush();
2716 : }
2717 : }
2718 :
2719 :
2720 0 : this->makeVisSet(*mssel_p);
2721 0 : AlwaysAssert(rvi_p, AipsError);
2722 :
2723 : // NOW WE HAVE TO REDO THE VELOCITY INFO FOR visiter AS IN SETDATA
2724 :
2725 0 : this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
2726 0 : dataNchan_p, dataStart_p, dataStep_p,
2727 0 : mDataStart_p, mDataStep_p);
2728 :
2729 0 : this->writeHistory(os);
2730 0 : this->unlock();
2731 :
2732 : // Beam is no longer valid
2733 0 : beamValid_p=false;
2734 0 : return true;
2735 0 : } catch (AipsError x) {
2736 0 : this->unlock();
2737 0 : throw(x);
2738 : return false;
2739 0 : }
2740 : return true;
2741 0 : }
2742 :
2743 : // Find the sensitivity
2744 0 : Bool Imager::sensitivity(Quantity& pointsourcesens, Double& relativesens,
2745 : Double& sumwt,
2746 : Double& effectiveBandwidth,
2747 : Double& effectiveIntegration,
2748 : Int& nBaselines,
2749 : Matrix<Int>& mssChanSel,
2750 : Vector<Vector<Int> >& nData,
2751 : Vector<Vector<Double> >& sumwtChan,
2752 : Vector<Vector<Double> >& sumwtsqChan,
2753 : Vector<Vector<Double> >& sumInverseVarianceChan)
2754 : {
2755 0 : if(!valid()) return false;
2756 0 : LogIO os(LogOrigin("imager", "sensitivity()", WHERE));
2757 :
2758 : try {
2759 :
2760 : os << LogIO::NORMAL // Loglevel INFO
2761 : << "Calculating sensitivity from imaging weights and from effective bandwidth and integration time"
2762 0 : << LogIO::POST;
2763 :
2764 0 : this->lock();
2765 0 : mssChanSel.assign(mssChanSel_p);
2766 :
2767 0 : VisSetUtil::Sensitivity(*rvi_p, mssFreqSel_p, mssChanSel, pointsourcesens, relativesens, sumwt,
2768 : effectiveBandwidth, effectiveIntegration, nBaselines,nData, sumwtChan,
2769 : sumwtsqChan, sumInverseVarianceChan);
2770 : os << LogIO::NORMAL << "RMS Point source sensitivity : " // Loglevel INFO
2771 0 : << pointsourcesens.get("Jy").getValue() << " Jy.m2/K"
2772 0 : << LogIO::POST;
2773 : os << LogIO::NORMAL // Loglevel INFO
2774 0 : << "Relative to natural weighting : " << relativesens << LogIO::POST;
2775 : os << LogIO::NORMAL // Loglevel INFO
2776 0 : << "Sum of weights : " << sumwt << LogIO::POST;
2777 0 : this->unlock();
2778 0 : return true;
2779 0 : } catch (AipsError x) {
2780 0 : this->unlock();
2781 0 : throw(x);
2782 : return false;
2783 0 : }
2784 : return true;
2785 0 : }
2786 :
2787 0 : Bool Imager::apparentSensitivity(Double& effSensitivity,
2788 : Double& relToNat) {
2789 0 : if(!valid()) return false;
2790 0 : LogIO os(LogOrigin("imager", "apparentSensitivity()", WHERE));
2791 :
2792 : try {
2793 :
2794 : os << LogIO::NORMAL // Loglevel INFO
2795 : << "Calculating apparent sensitivity from MS weights, as modified by gridding weight function"
2796 0 : << LogIO::POST;
2797 : os << LogIO::NORMAL // Loglevel INFO
2798 : << "(assuming that MS weights have correct scale and units)"
2799 0 : << LogIO::POST;
2800 :
2801 0 : this->lock();
2802 :
2803 0 : Double sumNatWt=0.0;
2804 0 : Double sumGridWt=0.0;
2805 0 : Double sumGridWt2OverNatWt=0.0;
2806 :
2807 0 : Float iNatWt(0.0),iGridWt(0.0);
2808 :
2809 0 : ROVisibilityIterator& vi(*rvi_p);
2810 0 : VisBuffer vb(vi);
2811 : //Bool doWtSp=vb.existsWeightSpectrum();
2812 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
2813 0 : for (vi.origin();vi.more();vi++) {
2814 0 : Int nRow=vb.nRow();
2815 0 : Vector<Bool> rowFlags=vb.flagRow();
2816 0 : Matrix<Bool> flag = vb.flag();
2817 :
2818 0 : Vector<Int>& a1(vb.antenna1()), a2(vb.antenna2());
2819 :
2820 0 : for (Int row=0; row<nRow; row++) {
2821 0 : if (!rowFlags(row) && a1(row)!=a2(row)) { // exclude ACs
2822 0 : iNatWt=2.0f*vb.weight()(row);
2823 0 : for (Int ich=0;ich<vb.nChannel();++ich) {
2824 0 : if(!flag(ich,row)&&(iNatWt>0.0)) {
2825 0 : iGridWt=2.0f*vb.imagingWeight()(ich,row);
2826 0 : sumNatWt+=(iNatWt);
2827 0 : sumGridWt+=(iGridWt);
2828 0 : sumGridWt2OverNatWt+=(iGridWt*iGridWt/iNatWt);
2829 : }
2830 : }
2831 : }
2832 : }
2833 0 : }
2834 : }
2835 :
2836 0 : if (sumNatWt==0.0) {
2837 0 : os << "Cannot calculate sensitivity: sum of selected natural weights is zero" << LogIO::EXCEPTION;
2838 : }
2839 0 : if (sumGridWt==0.0) {
2840 0 : os << "Cannot calculate sensitivity: sum of gridded weights is zero" << LogIO::EXCEPTION;
2841 : }
2842 :
2843 0 : effSensitivity = sqrt(sumGridWt2OverNatWt)/sumGridWt;
2844 0 : Double natSensitivity = 1.0/sqrt(sumNatWt);
2845 0 : relToNat=effSensitivity/natSensitivity;
2846 :
2847 : os << LogIO::NORMAL << "RMS Point source sensitivity : " // Loglevel INFO
2848 : << effSensitivity // << " Jy/beam" // actually, units are arbitrary
2849 0 : << LogIO::POST;
2850 : os << LogIO::NORMAL // Loglevel INFO
2851 0 : << "Relative to natural weighting : " << relToNat << LogIO::POST;
2852 :
2853 0 : this->unlock();
2854 0 : return true;
2855 0 : } catch (AipsError x) {
2856 0 : this->unlock();
2857 0 : throw(x);
2858 : return false;
2859 0 : }
2860 : return true;
2861 :
2862 0 : }
2863 :
2864 :
2865 :
2866 :
2867 :
2868 : // Calculate various sorts of image. Only one image
2869 : // can be calculated at a time. The complex Image make
2870 : // be retained if a name is given. This does not use
2871 : // the SkyEquation.
2872 0 : Bool Imager::makeimage(const String& type, const String& image,
2873 : const String& compleximage, const Bool verbose)
2874 : {
2875 0 : if(!valid())
2876 : {
2877 0 : return false;
2878 : }
2879 0 : LogIO os(LogOrigin("imager", "makeimage()", WHERE));
2880 :
2881 0 : this->lock();
2882 : try {
2883 0 : if(!assertDefinedImageParameters())
2884 : {
2885 0 : return false;
2886 : }
2887 :
2888 : os << LogIO::NORMAL // Loglevel INFO
2889 0 : << "Calculating image (without full skyequation)" << LogIO::POST;
2890 :
2891 0 : FTMachine::Type seType(FTMachine::OBSERVED);
2892 0 : Bool doSD(false);
2893 :
2894 0 : if(type=="observed") {
2895 0 : seType=FTMachine::OBSERVED;
2896 : os << LogIO::NORMAL // Loglevel INFO
2897 : << "Making dirty image from " << type << " data "
2898 0 : << LogIO::POST;
2899 : }
2900 0 : else if (type=="model") {
2901 0 : seType=FTMachine::MODEL;
2902 : os << LogIO::NORMAL // Loglevel INFO
2903 : << "Making dirty image from " << type << " data "
2904 0 : << LogIO::POST;
2905 : }
2906 0 : else if (type=="corrected") {
2907 0 : seType=FTMachine::CORRECTED;
2908 : os << LogIO::NORMAL // Loglevel INFO
2909 : << "Making dirty image from " << type << " data "
2910 0 : << LogIO::POST;
2911 : }
2912 0 : else if (type=="psf") {
2913 0 : seType=FTMachine::PSF;
2914 : os << "Making point spread function "
2915 0 : << LogIO::POST;
2916 : }
2917 0 : else if (type=="residual") {
2918 0 : seType=FTMachine::RESIDUAL;
2919 : os << LogIO::NORMAL // Loglevel INFO
2920 : << "Making dirty image from " << type << " data "
2921 0 : << LogIO::POST;
2922 : }
2923 0 : else if (type=="singledish-observed") {
2924 0 : doSD = true;
2925 0 : seType=FTMachine::OBSERVED;
2926 : os << LogIO::NORMAL // Loglevel INFO
2927 0 : << "Making single dish image from observed data" << LogIO::POST;
2928 : }
2929 0 : else if (type=="singledish") {
2930 0 : doSD = true;
2931 0 : seType=FTMachine::CORRECTED;
2932 : os << LogIO::NORMAL // Loglevel INFO
2933 0 : << "Making single dish image from corrected data" << LogIO::POST;
2934 : }
2935 0 : else if (type=="coverage") {
2936 0 : doSD = true;
2937 0 : seType=FTMachine::COVERAGE;
2938 : os << LogIO::NORMAL // Loglevel PROGRESS
2939 : << "Making single dish coverage function "
2940 0 : << LogIO::POST;
2941 : }
2942 0 : else if (type=="holography") {
2943 0 : doSD = true;
2944 0 : seType=FTMachine::CORRECTED;
2945 : os << LogIO::NORMAL // Loglevel INFO
2946 : << "Making complex holographic image from corrected data "
2947 0 : << LogIO::POST;
2948 : }
2949 0 : else if (type=="holography-observed") {
2950 0 : doSD = true;
2951 0 : seType=FTMachine::OBSERVED;
2952 : os << LogIO::NORMAL // Loglevel INFO
2953 : << "Making complex holographic image from observed data "
2954 0 : << LogIO::POST;
2955 : }
2956 0 : else if (type=="pb"){
2957 0 : if ( ! doVP_p ) {
2958 0 : if( ftmachine_p == "pbwproject" ){
2959 0 : os << LogIO::WARN << "Using pb from ft-machines" << LogIO::POST;
2960 : }
2961 : else{
2962 0 : this->unlock();
2963 : os << LogIO::SEVERE <<
2964 : "Must invoke setvp() first in order to make its image"
2965 0 : << LogIO::EXCEPTION;
2966 0 : return false;
2967 : }
2968 : }
2969 0 : CoordinateSystem coordsys;
2970 : //imagecoordinates(coordsys, verbose);
2971 0 : imagecoordinates2(coordsys, verbose);
2972 0 : if (doDefaultVP_p) {
2973 0 : if(telescope_p!=""){
2974 0 : ObsInfo myobsinfo=this->latestObsInfo();
2975 0 : myobsinfo.setTelescope(telescope_p);
2976 0 : coordsys.setObsInfo(myobsinfo);
2977 :
2978 0 : }
2979 : else{
2980 0 : telescope_p=coordsys.obsInfo().telescope();
2981 : }
2982 0 : this->unlock();
2983 0 : MSAntennaColumns ac(ms_p->antenna());
2984 0 : Double dishDiam=ac.dishDiameter()(0);
2985 0 : if(!allEQ(ac.dishDiameter().getColumn(), dishDiam))
2986 : os << LogIO::WARN
2987 : << "The MS has multiple antenna diameters ..PB could be wrong "
2988 0 : << LogIO::POST;
2989 0 : return this->makePBImage(coordsys, telescope_p, image, false, dishDiam);
2990 0 : }
2991 : else{
2992 0 : Table vpTable(vpTableStr_p);
2993 0 : this->unlock();
2994 0 : return this->makePBImage(coordsys, vpTable, image);
2995 0 : }
2996 :
2997 0 : }
2998 : else {
2999 0 : this->unlock();
3000 0 : os << LogIO::SEVERE << "Unknown image type " << type << LogIO::EXCEPTION;
3001 :
3002 0 : return false;
3003 : }
3004 :
3005 0 : if(doSD && (ftmachine_p == "ft")){
3006 : os << LogIO::SEVERE
3007 : << "To make single dish images, ftmachine in setoptions must be set to either sd or both"
3008 0 : << LogIO::EXCEPTION;
3009 : }
3010 :
3011 : // Now make the images. If we didn't specify the names then
3012 : // delete on exit.
3013 0 : String imageName(image);
3014 0 : if(image=="") {
3015 0 : imageName=Imager::imageName()+".image";
3016 : }
3017 0 : os << LogIO::NORMAL << "Image is : " << imageName << LogIO::POST; // Loglevel INFO
3018 0 : Bool keepImage=(image!="");
3019 0 : Bool keepComplexImage=(compleximage!="")||(type=="holography")||(type=="holography-observed");
3020 0 : String cImageName(compleximage);
3021 :
3022 0 : if(compleximage=="") {
3023 0 : cImageName=imageName+".compleximage";
3024 : }
3025 :
3026 0 : if(keepComplexImage) {
3027 0 : os << "Retaining complex image: " << compleximage << LogIO::POST;
3028 : }
3029 :
3030 0 : CoordinateSystem imagecoords;
3031 : //if(!imagecoordinates(imagecoords, false))
3032 0 : if(!imagecoordinates2(imagecoords, false))
3033 : {
3034 0 : return false;
3035 : }
3036 0 : make(imageName);
3037 0 : PagedImage<Float> imageImage(imageName);
3038 0 : imageImage.set(0.0);
3039 0 : imageImage.table().markForDelete();
3040 :
3041 : // Now set up the tile size, here we guess only
3042 0 : IPosition cimageShape(imageshape());
3043 0 : Int tilex=32;
3044 0 : if(imageTileVol_p >0){
3045 0 : tilex=static_cast<Int>(ceil(sqrt(imageTileVol_p/min(4,
3046 0 : cimageShape(2))/min(32,
3047 0 : cimageShape(3)))));
3048 0 : if(tilex >0){
3049 0 : if(tilex > min(Int(cimageShape(0)), Int(cimageShape(1))))
3050 0 : tilex=min(Int(cimageShape(0)), Int(cimageShape(1)));
3051 : else
3052 0 : tilex=cimageShape(0)/Int(cimageShape(0)/tilex);
3053 : }
3054 : //Not too small in x-y tile
3055 0 : if(tilex < 10)
3056 0 : tilex=10;
3057 :
3058 : }
3059 0 : IPosition tileShape(4, min(tilex, cimageShape(0)), min(tilex, cimageShape(1)),
3060 0 : min(4, cimageShape(2)), min(32, cimageShape(3)));
3061 0 : CoordinateSystem cimagecoords;
3062 : //if(!imagecoordinates(cimagecoords, false))
3063 0 : if(!imagecoordinates2(cimagecoords, false))
3064 : {
3065 0 : return false;
3066 : }
3067 :
3068 :
3069 :
3070 0 : PagedImage<Complex> cImageImage(TiledShape(cimageShape, tileShape),
3071 : cimagecoords,
3072 0 : cImageName);
3073 0 : cImageImage.set(Complex(0.0));
3074 0 : cImageImage.setMaximumCacheSize(cache_p/2);
3075 0 : cImageImage.table().markForDelete();
3076 : //
3077 : // Add the distance to the object: this is not nice. We should define the
3078 : // coordinates properly.
3079 : //
3080 0 : Record info(imageImage.miscInfo());
3081 0 : info.define("distance", distance_p.get("m").getValue());
3082 0 : cImageImage.setMiscInfo(info);
3083 :
3084 :
3085 0 : String ftmachine(ftmachine_p);
3086 0 : if (!ft_p)
3087 0 : createFTMachine();
3088 :
3089 : os << LogIO::DEBUG1 << "FTMachine is : " << ftmachine
3090 0 : << " (" << ft_p << ")" << LogIO::POST;
3091 :
3092 :
3093 : // Now make the required image
3094 0 : Matrix<Float> weight;
3095 0 : ft_p->makeImage(seType, *rvi_p, cImageImage, weight);
3096 0 : StokesImageUtil::To(imageImage, cImageImage);
3097 : //
3098 : // Dirty way to set the proper unit to SD image
3099 : //
3100 0 : String msunit("");
3101 0 : String imunit;
3102 0 : if ( ms_p->tableDesc().isColumn("DATA") ){
3103 0 : msunit = ms_p->columnUnit(MS::DATA);
3104 0 : if (msunit == String("")) {
3105 0 : ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("DATA"));
3106 0 : if (dataColDesc.keywordSet().isDefined("UNIT"))
3107 0 : msunit = dataColDesc.keywordSet().asString("UNIT");
3108 0 : }
3109 0 : } else if ( ms_p->tableDesc().isColumn("FLOAT_DATA")) {
3110 0 : msunit = ms_p->columnUnit(MS::FLOAT_DATA);
3111 0 : if (msunit == String("")) {
3112 0 : ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("FLOAT_DATA"));
3113 0 : if (dataColDesc.keywordSet().isDefined("UNIT"))
3114 0 : msunit = dataColDesc.keywordSet().asString("UNIT");
3115 0 : }
3116 : }
3117 0 : msunit.upcase();
3118 0 : if (msunit == String("K"))
3119 0 : imunit = "K";
3120 : else
3121 0 : imunit = "Jy/beam";
3122 0 : imageImage.setUnits(Unit(imunit));
3123 0 : cImageImage.setUnits(Unit(imunit));
3124 : // imageImage.setUnits(Unit("Jy/beam"));
3125 : // cImageImage.setUnits(Unit("Jy/beam"));
3126 :
3127 0 : if(keepImage) {
3128 0 : imageImage.table().unmarkForDelete();
3129 : }
3130 0 : if(keepComplexImage) {
3131 0 : cImageImage.table().unmarkForDelete();
3132 : }
3133 0 : this->unlock();
3134 0 : return true;
3135 0 : } catch (AipsError x) {
3136 0 : this->unlock();
3137 0 : throw(x);
3138 : return false;
3139 0 : }
3140 0 : catch(...){
3141 : //Unknown exception...
3142 0 : throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
3143 0 : }
3144 : this->unlock();
3145 :
3146 : return true;
3147 0 : }
3148 :
3149 : // Restore: at least one model must be supplied
3150 0 : Bool Imager::restore(const Vector<String>& model,
3151 : const String& complist,
3152 : const Vector<String>& image,
3153 : const Vector<String>& residual)
3154 : {
3155 :
3156 0 : if(!valid()) return false;
3157 0 : LogIO os(LogOrigin("imager", "restore()", WHERE));
3158 :
3159 0 : this->lock();
3160 : try {
3161 0 : if(!assertDefinedImageParameters()) return false;
3162 :
3163 0 : if(image.nelements()>model.nelements()) {
3164 0 : this->unlock();
3165 : os << LogIO::SEVERE << "Cannot specify more output images than models"
3166 0 : << LogIO::EXCEPTION;
3167 0 : return false;
3168 : }
3169 : else {
3170 : os << LogIO::NORMAL // Loglevel PROGRESS
3171 0 : << "Restoring " << model.nelements() << " models" << LogIO::POST;
3172 : }
3173 :
3174 : ///if the skymodel is already set...no need to get rid of the psf and ftmachine state
3175 : //as long as the images match
3176 0 : if(!redoSkyModel_p){
3177 0 : Bool coordMatch=true;
3178 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
3179 0 : CoordinateSystem cs=(sm_p->image(thismodel)).coordinates();
3180 0 : coordMatch= coordMatch || checkCoord(cs, model(thismodel));
3181 0 : }
3182 0 : if(!coordMatch)
3183 0 : destroySkyEquation();
3184 : }
3185 :
3186 0 : if(redoSkyModel_p){
3187 0 : Vector<String> imageNames(image);
3188 0 : if(image.nelements()<model.nelements()) {
3189 0 : imageNames.resize(model.nelements());
3190 0 : for(Int i=0;i<Int(model.nelements()); ++i) {
3191 0 : imageNames(i)="";
3192 : }
3193 : }
3194 :
3195 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
3196 0 : if(imageNames(thismodel)=="") {
3197 0 : imageNames(thismodel)=model(thismodel)+".restored";
3198 : }
3199 0 : removeTable(imageNames(thismodel));
3200 0 : if(imageNames(thismodel)=="") {
3201 0 : this->unlock();
3202 : os << LogIO::SEVERE << "Illegal name for output image "
3203 0 : << imageNames(thismodel) << LogIO::EXCEPTION;
3204 0 : return false;
3205 : }
3206 0 : if(!clone(model(thismodel), imageNames(thismodel))) return false;
3207 : }
3208 :
3209 0 : Vector<String> residualNames(residual);
3210 0 : if(residual.nelements()<model.nelements()) {
3211 0 : residualNames.resize(model.nelements());
3212 0 : for(Int i=0;i<Int(model.nelements());++i) {
3213 0 : residualNames(i)="";
3214 : }
3215 : }
3216 :
3217 0 : for (Int thismodel=0;thismodel<Int(model.nelements()); ++thismodel) {
3218 0 : if(residualNames(thismodel)=="")
3219 0 : residualNames(thismodel)=model(thismodel)+".residual";
3220 0 : removeTable(residualNames(thismodel));
3221 0 : if(residualNames(thismodel)=="") {
3222 0 : this->unlock();
3223 : os << LogIO::SEVERE << "Illegal name for output residual "
3224 0 : << residualNames(thismodel) << LogIO::EXCEPTION;
3225 0 : return false;
3226 : }
3227 0 : if(!clone(model(thismodel), residualNames(thismodel))) return false;
3228 : }
3229 :
3230 0 : if(beamValid_p) {
3231 0 : os << LogIO::NORMAL << "Using previous beam fit" << LogIO::POST; // Loglevel INFO
3232 : }
3233 : else {
3234 : os << LogIO::NORMAL // Loglevel INFO
3235 0 : << "Calculating PSF using current parameters" << LogIO::POST;
3236 0 : String psf;
3237 0 : psf=imageNames(0)+".psf";
3238 0 : if(!clone(imageNames(0), psf)) return false;
3239 0 : Imager::makeimage("psf", psf);
3240 0 : fitpsf(psf, beam_p);
3241 0 : beamValid_p=true;
3242 0 : }
3243 :
3244 : // if (!se_p)
3245 0 : if(!createSkyEquation(model, complist)) return false;
3246 :
3247 0 : addResiduals(residualNames);
3248 0 : }
3249 0 : sm_p->solveResiduals(*se_p);
3250 0 : for (uInt k=0 ; k < residuals_p.nelements(); ++k){
3251 0 : residuals_p[k]->copyData(sm_p->getResidual(k));
3252 : }
3253 0 : restoreImages(image);
3254 :
3255 0 : this->unlock();
3256 0 : return true;
3257 0 : } catch (AipsError x) {
3258 0 : this->unlock();
3259 0 : throw(x);
3260 : return false;
3261 0 : }
3262 : this->unlock();
3263 : return true;
3264 0 : }
3265 :
3266 0 : Bool Imager::updateresidual(const Vector<String>& model,
3267 : const String& complist,
3268 : const Vector<String>& image,
3269 : const Vector<String>& residual)
3270 : {
3271 :
3272 0 : if(!valid()) return false;
3273 0 : LogIO os(LogOrigin("imager", "updateresidual()", WHERE));
3274 :
3275 0 : this->lock();
3276 : try {
3277 0 : if(!assertDefinedImageParameters()) return false;
3278 :
3279 0 : if(image.nelements()>model.nelements()) {
3280 0 : this->unlock();
3281 : os << LogIO::SEVERE << "Cannot specify more output images than models"
3282 0 : << LogIO::EXCEPTION;
3283 0 : return false;
3284 : }
3285 : else {
3286 : os << LogIO::NORMAL // Loglevel PROGRESS
3287 0 : << "updating and restoring " << model.nelements() << " models" << LogIO::POST;
3288 : }
3289 :
3290 0 : if(redoSkyModel_p)
3291 0 : throw(AipsError("use restore instead of updateresidual"));
3292 0 : if(!updateSkyModel(model, complist))
3293 0 : throw(AipsError("Could not do an updateresidual please use restore"));
3294 0 : addResiduals(residual);
3295 0 : for (Int thismodel=0;thismodel<Int(residuals_p.nelements());++thismodel) {
3296 0 : if(!residuals_p[thismodel].null())
3297 0 : sm_p->addResidual(thismodel, *residuals_p[thismodel]);
3298 : }
3299 0 : sm_p->solveResiduals(*se_p);
3300 : /*for (uInt k=0 ; k < residuals_p.nelements(); ++k){
3301 : residuals_p[k]->copyData(sm_p->getResidual(k));
3302 : }
3303 : */
3304 0 : restoreImages(image);
3305 :
3306 :
3307 0 : this->unlock();
3308 0 : return true;
3309 0 : } catch (AipsError x) {
3310 0 : this->unlock();
3311 0 : throw(x);
3312 : return false;
3313 0 : }
3314 : this->unlock();
3315 : return true;
3316 0 : }
3317 :
3318 : // Residual
3319 0 : Bool Imager::residual(const Vector<String>& model,
3320 : const String& complist,
3321 : const Vector<String>& image)
3322 : {
3323 :
3324 0 : if(!valid()) return false;
3325 0 : LogIO os(LogOrigin("imager", "residual()", WHERE));
3326 :
3327 0 : this->lock();
3328 : try {
3329 0 : if(!assertDefinedImageParameters()) return false;
3330 : os << LogIO::NORMAL // Loglevel INFO
3331 0 : << "Calculating residual image using full sky equation" << LogIO::POST;
3332 0 : Vector<String> theModels=model;
3333 :
3334 0 : Bool deleteModel=false;
3335 :
3336 0 : if(model.nelements()==1 && model[0]=="" && complist != ""
3337 0 : && image.nelements()==1){
3338 :
3339 : // A component list with no model passed...
3340 0 : theModels.resize(1);
3341 0 : theModels[0]="Imager_Scratch_model";
3342 0 : make(theModels[0]);
3343 0 : deleteModel=true;
3344 : }
3345 :
3346 0 : if(image.nelements()>theModels.nelements()) {
3347 0 : this->unlock();
3348 : os << LogIO::SEVERE << "Cannot specify more output images than models"
3349 0 : << LogIO::EXCEPTION;
3350 0 : return false;
3351 : }
3352 : else {
3353 : os << LogIO::NORMAL << "Finding residuals for " << theModels.nelements() // Loglevel INFO
3354 0 : << " models" << LogIO::POST;
3355 : }
3356 :
3357 0 : Vector<String> imageNames(image);
3358 0 : if(image.nelements()<theModels.nelements()) {
3359 0 : imageNames.resize(model.nelements());
3360 0 : for(Int i=Int(image.nelements());i<Int(theModels.nelements());++i) {
3361 0 : imageNames(i)="";
3362 : }
3363 : }
3364 :
3365 0 : for (Int thismodel=0;thismodel<Int(theModels.nelements()); ++thismodel) {
3366 0 : if(imageNames(thismodel)=="")
3367 0 : imageNames(thismodel)=model(thismodel)+".residual";
3368 0 : removeTable(imageNames(thismodel));
3369 0 : if(imageNames(thismodel)=="") {
3370 0 : this->unlock();
3371 : os << LogIO::SEVERE << "Illegal name for output image "
3372 0 : << imageNames(thismodel) << LogIO::EXCEPTION;
3373 0 : return false;
3374 : }
3375 0 : if(!clone(theModels(thismodel), imageNames(thismodel))) return false;
3376 : }
3377 0 : destroySkyEquation();
3378 0 : if(!createSkyEquation(theModels, complist)) return false;
3379 :
3380 0 : addResidualsToSkyEquation(imageNames);
3381 :
3382 0 : sm_p->solveResiduals(*se_p);
3383 0 : destroySkyEquation();
3384 0 : if(deleteModel)
3385 0 : removeTable(theModels[0]);
3386 0 : this->unlock();
3387 0 : return true;
3388 0 : } catch (AipsError x) {
3389 0 : this->unlock();
3390 0 : throw(x);
3391 : return false;
3392 0 : }
3393 : this->unlock();
3394 : return true;
3395 0 : }
3396 :
3397 : // Residual
3398 14 : Bool Imager::approximatepsf(const String& psf)
3399 : {
3400 :
3401 14 : if(!valid()) return false;
3402 28 : LogIO os(LogOrigin("imager", "approximatepsfs()", WHERE));
3403 :
3404 14 : this->lock();
3405 : try {
3406 14 : if(!assertDefinedImageParameters()) return false;
3407 : os << LogIO::NORMAL // Loglevel INFO
3408 14 : << "Calculating approximate PSFs using full sky equation" << LogIO::POST;
3409 :
3410 :
3411 14 : if(psf==""){
3412 0 : this->unlock();
3413 : os << LogIO::SEVERE << "Illegal name for output psf "
3414 0 : << psf << LogIO::EXCEPTION;
3415 0 : return false;
3416 : }
3417 14 : removeTable(psf);
3418 14 : make(psf);
3419 :
3420 14 : Vector<String>onepsf(1,psf);
3421 : // Previous SkyEquation if they exist is not useful
3422 14 : destroySkyEquation();
3423 : // if (!se_p)
3424 : // As we are not going to make any use of a useful model and to economize
3425 : // temporary image...using the psf itself as model...
3426 : // need to change this if you donot destroy the skyequation after you're done.
3427 14 : if(!createSkyEquation(onepsf)) return false;
3428 :
3429 14 : sm_p->makeApproxPSFs(*se_p);
3430 :
3431 :
3432 14 : PagedImage<Float> elpsf(psf);
3433 14 : elpsf.copyData(sm_p->PSF(0));
3434 14 : ImageBeamSet mbeam;
3435 14 : StokesImageUtil::FitGaussianPSF(elpsf, mbeam);
3436 14 : LatticeExprNode sumPSF = sum(elpsf);
3437 14 : Float volume=sumPSF.getFloat();
3438 14 : GaussianBeam elbeam=mbeam(0,0);
3439 : os << LogIO::NORMAL << "Approximate PSF " << ": size " // Loglevel INFO
3440 : << elbeam.getMajor("arcsec") << " by "
3441 : << elbeam.getMinor("arcsec") << " (arcsec) at pa "
3442 14 : << elbeam.getPA(Unit("deg")) << " (deg)" << endl
3443 28 : << "and volume = " << volume << " pixels " << LogIO::POST;
3444 :
3445 :
3446 14 : destroySkyEquation();
3447 14 : if(ft_p)
3448 14 : delete ft_p;
3449 14 : ft_p=0;
3450 :
3451 14 : this->unlock();
3452 14 : return true;
3453 14 : } catch (AipsError x) {
3454 0 : this->unlock();
3455 0 : throw(x);
3456 : return false;
3457 0 : }
3458 : this->unlock();
3459 : return true;
3460 14 : }
3461 :
3462 0 : Bool Imager::smooth(const Vector<String>& model,
3463 : const Vector<String>& image, Bool usefit,
3464 : ImageBeamSet& mbeam,
3465 : Bool normalizeVolume)
3466 : {
3467 0 : if(!valid()) return false;
3468 0 : LogIO os(LogOrigin("imager", "smooth()", WHERE));
3469 :
3470 0 : this->lock();
3471 : try {
3472 0 : if(!assertDefinedImageParameters()) return false;
3473 :
3474 0 : os << LogIO::NORMAL << "Smoothing image" << LogIO::POST; // Loglevel PROGRESS
3475 :
3476 0 : if(model.nelements()>0) {
3477 0 : for ( uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
3478 0 : if(model(thismodel)=="") {
3479 0 : this->unlock();
3480 0 : os << LogIO::SEVERE << "Need a name for model " << thismodel << LogIO::POST;
3481 0 : return false;
3482 : }
3483 : }
3484 : }
3485 :
3486 0 : if(image.nelements()>model.nelements()) {
3487 0 : this->unlock();
3488 0 : os << LogIO::SEVERE << "Cannot specify more output images than models" << LogIO::POST;
3489 0 : return false;
3490 : }
3491 :
3492 0 : if(usefit) {
3493 0 : if(beamValid_p) {
3494 0 : os << LogIO::NORMAL << "Using previous beam" << LogIO::POST; // Loglevel INFO
3495 0 : mbeam = beam_p;
3496 :
3497 : }
3498 : else {
3499 : os << LogIO::NORMAL // Loglevel INFO
3500 0 : << "Calculating PSF using current parameters" << LogIO::POST;
3501 0 : String psf;
3502 0 : psf=model(0)+".psf";
3503 0 : if(!clone(model(0), psf)) return false;
3504 0 : Imager::makeimage("psf", psf);
3505 0 : fitpsf(psf, mbeam);
3506 0 : beam_p = mbeam;
3507 0 : beamValid_p=true;
3508 0 : }
3509 : }
3510 :
3511 : // Smooth all the images
3512 0 : Vector<String> imageNames(image);
3513 0 : for (Int thismodel=0;thismodel<Int(image.nelements()); ++thismodel) {
3514 0 : if(imageNames(thismodel)=="") {
3515 0 : imageNames(thismodel)=model(thismodel)+".smoothed";
3516 : }
3517 0 : PagedImage<Float> modelImage(model(thismodel));
3518 0 : PagedImage<Float> imageImage(TiledShape(modelImage.shape(),
3519 0 : modelImage.niceCursorShape()),
3520 : modelImage.coordinates(),
3521 0 : imageNames(thismodel));
3522 0 : imageImage.table().markForDelete();
3523 0 : imageImage.copyData(modelImage);
3524 0 : StokesImageUtil::Convolve(imageImage, mbeam,
3525 : normalizeVolume);
3526 :
3527 0 : ImageInfo ii = imageImage.imageInfo();
3528 : //ii.setRestoringBeam(mbeam);
3529 0 : ii.setBeams(mbeam);
3530 0 : imageImage.setImageInfo(ii);
3531 0 : imageImage.setUnits(Unit("Jy/beam"));
3532 0 : imageImage.table().unmarkForDelete();
3533 0 : }
3534 :
3535 0 : this->unlock();
3536 0 : return true;
3537 0 : } catch (AipsError x) {
3538 0 : this->unlock();
3539 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
3540 0 : return false;
3541 0 : }
3542 : this->unlock();
3543 : return true;
3544 0 : }
3545 :
3546 : // Clean algorithm
3547 0 : Record Imager::clean(const String& algorithm,
3548 : const Int niter,
3549 : const Float gain,
3550 : const Quantity& threshold,
3551 : const Bool /*displayProgress*/,
3552 : const Vector<String>& model, const Vector<Bool>& fixed,
3553 : const String& complist,
3554 : const Vector<String>& mask,
3555 : const Vector<String>& image,
3556 : const Vector<String>& residual,
3557 : const Vector<String>& psfnames,
3558 : const Bool firstrun)
3559 : {
3560 : ////////////////////////
3561 : //Double wtime0=omp_get_wtime();
3562 : //////////////////////
3563 :
3564 :
3565 0 : Record retval;
3566 0 : Bool converged=true;
3567 0 : retval.define("converged", false);
3568 0 : retval.define("iterations", Int(0));
3569 0 : retval.define("maxresidual", Float(0.0));
3570 :
3571 :
3572 :
3573 : //ROVisibilityIterator::AsyncEnabler enabler (rvi_p);
3574 :
3575 0 : if(!valid())
3576 : {
3577 0 : return retval;
3578 : }
3579 0 : logSink_p.clearLocally();
3580 0 : LogIO os(LogOrigin("imager", "clean()"),logSink_p);
3581 :
3582 0 : this->lock();
3583 : try {
3584 0 : if(!assertDefinedImageParameters())
3585 : {
3586 0 : return retval;
3587 : }
3588 :
3589 0 : Int nmodels=model.nelements();
3590 : os << LogIO::DEBUG1
3591 0 : << "Found " << nmodels << " specified model images" << LogIO::POST;
3592 :
3593 0 : if(model.nelements()>0) {
3594 0 : for (uInt thismodel=0;thismodel<model.nelements(); ++thismodel) {
3595 0 : if(model(thismodel)=="") {
3596 0 : this->unlock();
3597 : os << LogIO::SEVERE << "Need a name for model "
3598 0 : << thismodel << LogIO::POST;
3599 :
3600 0 : return retval;
3601 : }
3602 : }
3603 : }
3604 :
3605 0 : Vector<String> modelNames=model;
3606 : // Make first image with the required shape and coordinates only if
3607 : // it doesn't exist yet. Otherwise we'll throw an exception later
3608 0 : if(modelNames(0)=="") modelNames(0)=imageName()+".clean";
3609 0 : if(!Table::isWritable(modelNames(0))) {
3610 0 : make(modelNames(0));
3611 : }
3612 : else{
3613 0 : Bool coordMatch=false;
3614 0 : CoordinateSystem coordsys;
3615 : //imagecoordinates(coordsys, firstrun);
3616 0 : imagecoordinates2(coordsys, firstrun);
3617 0 : for (uInt modelNum=0; modelNum < modelNames.nelements(); ++modelNum){
3618 0 : if(Table::isWritable(modelNames(modelNum))){
3619 0 : coordMatch= coordMatch ||
3620 0 : (this->checkCoord(coordsys, modelNames(modelNum)));
3621 :
3622 : }
3623 :
3624 : }
3625 0 : if(!coordMatch){
3626 : os << LogIO::WARN << "The model(s) image exists on disk "
3627 0 : << LogIO::POST;
3628 : os << LogIO::WARN
3629 : << "The coordinates or shape were found not to match the one "
3630 : << "defined by setimage "
3631 0 : << LogIO::POST;
3632 :
3633 : os << LogIO::WARN
3634 : << "Cleaning process is going to ignore setimage parameters and "
3635 : << "continue cleaning from from model on disk "
3636 0 : << LogIO::POST;
3637 : }
3638 0 : }
3639 0 : Vector<String> maskNames(nmodels);
3640 0 : if(Int(mask.nelements())==nmodels) {
3641 0 : maskNames=mask;
3642 : }
3643 : else {
3644 : /* For msmfs, the one input mask PER FIELD must be replicated for all
3645 : Taylor-planes PER FIELD */
3646 0 : if(algorithm=="msmfs" && (Int(mask.nelements())>=(nmodels/ntaylor_p)) ){
3647 0 : for(Int tay=0;tay<nmodels;tay++)
3648 : {
3649 0 : maskNames[tay] = mask[ tay%(nmodels/ntaylor_p) ];
3650 : }
3651 : }
3652 : else {
3653 : /* No mask */
3654 0 : maskNames="";
3655 : }
3656 : }
3657 :
3658 0 : if(sm_p){
3659 0 : if( sm_p->getAlgorithm() != "clean") destroySkyEquation();
3660 0 : if(images_p.nelements() != uInt(nmodels)){
3661 0 : destroySkyEquation();
3662 : }
3663 : else{
3664 0 : for (Int k=0; k < nmodels ; ++k){
3665 0 : if(!(images_p[k]->name().contains(modelNames[k]))) destroySkyEquation();
3666 : }
3667 : }
3668 : }
3669 :
3670 : // Always fill in the residual images
3671 0 : Vector<String> residualNames(nmodels);
3672 0 : if(Int(residual.nelements())==nmodels) {
3673 0 : residualNames=residual;
3674 : }
3675 : else {
3676 0 : residualNames="";
3677 : }
3678 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
3679 0 : if(residualNames[thismodel]=="")
3680 0 : residualNames(thismodel)=modelNames(thismodel)+".residual";
3681 : }
3682 0 : if(redoSkyModel_p){
3683 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
3684 0 : removeTable(residualNames(thismodel));
3685 0 : if(!clone(model(thismodel), residualNames(thismodel)))
3686 : {
3687 0 : return retval;
3688 : }
3689 : }
3690 : }
3691 :
3692 :
3693 : // Make an ImageSkyModel with the specified polarization representation
3694 : // (i.e. circular or linear)
3695 :
3696 0 : if( redoSkyModel_p || !sm_p){
3697 0 : if(sm_p) delete sm_p;
3698 0 : if(algorithm.substr(0,5)=="clark") {
3699 : // Support serial and parallel specializations
3700 0 : setClarkCleanImageSkyModel();
3701 0 : if(algorithm.contains("stokes"))
3702 0 : sm_p->setJointStokesClean(false);
3703 : os << LogIO::NORMAL // Loglevel INFO. Stating the algo is more for
3704 0 : << "Using Clark clean" << LogIO::POST; // the logfile than the window.
3705 : }
3706 0 : else if (algorithm=="hogbom") {
3707 0 : sm_p = new HogbomCleanImageSkyModel();
3708 : os << LogIO::NORMAL // Loglevel INFO. Stating the algo is more for
3709 0 : << "Using Hogbom clean" << LogIO::POST; // the logfile than the window.
3710 : }
3711 0 : else if (algorithm=="wfhogbom") {
3712 0 : setWFCleanImageSkyModel();
3713 0 : sm_p->setSubAlgorithm("hogbom");
3714 0 : doMultiFields_p = true;
3715 0 : doMultiFields_p = false;
3716 : os << LogIO::NORMAL // Loglevel INFO
3717 0 : << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
3718 : }
3719 0 : else if (algorithm=="multiscale") {
3720 0 : if (!scaleInfoValid_p) {
3721 0 : this->unlock();
3722 0 : os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
3723 0 : return retval;
3724 : }
3725 0 : if (scaleMethod_p=="uservector") {
3726 0 : sm_p = new MSCleanImageSkyModel(userScaleSizes_p, stoplargenegatives_p,
3727 0 : stoppointmode_p, smallScaleBias_p);
3728 : } else {
3729 0 : sm_p = new MSCleanImageSkyModel(nscales_p, stoplargenegatives_p,
3730 0 : stoppointmode_p, smallScaleBias_p);
3731 : }
3732 0 : if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
3733 0 : sm_p->setSubAlgorithm("full");
3734 : os << LogIO::NORMAL // Loglevel INFO. Stating the algo is more for
3735 0 : << "Using multiscale clean" << LogIO::POST; // the logfile than the window.
3736 : }
3737 0 : else if (algorithm.substr(0,7)=="mfclark" || algorithm=="mf") {
3738 0 : sm_p = new MFCleanImageSkyModel();
3739 0 : sm_p->setSubAlgorithm("clark");
3740 0 : if(algorithm.contains("stokes"))
3741 0 : sm_p->setJointStokesClean(false);
3742 :
3743 0 : doMultiFields_p = true;
3744 0 : os << LogIO::NORMAL << "Using multifield Clark clean" << LogIO::POST; // Loglevel INFO
3745 : }
3746 0 : else if (algorithm=="csclean" || algorithm=="cs") {
3747 0 : sm_p = new CSCleanImageSkyModel();
3748 0 : doMultiFields_p = true;
3749 0 : os << LogIO::NORMAL << "Using Cotton-Schwab Clean" << LogIO::POST; // Loglevel INFO
3750 : }
3751 0 : else if (algorithm=="csfast" || algorithm=="csf") {
3752 0 : sm_p = new CSCleanImageSkyModel();
3753 0 : sm_p->setSubAlgorithm("fast");
3754 0 : doMultiFields_p = true;
3755 : os << LogIO::NORMAL // Loglevel INFO
3756 0 : << "Using Cotton-Schwab Clean (optimized)" << LogIO::POST;
3757 : }
3758 0 : else if (algorithm=="mfhogbom") {
3759 0 : sm_p = new MFCleanImageSkyModel();
3760 0 : sm_p->setSubAlgorithm("hogbom");
3761 0 : doMultiFields_p = true;
3762 0 : os << LogIO::NORMAL << "Using multifield Hogbom clean" << LogIO::POST; // Loglevel INFO
3763 : }
3764 0 : else if (algorithm=="mfmultiscale") {
3765 0 : if (!scaleInfoValid_p) {
3766 0 : this->unlock();
3767 0 : os << LogIO::SEVERE << "Scales not yet set" << LogIO::POST;
3768 0 : return retval;
3769 : }
3770 0 : if (scaleMethod_p=="uservector") {
3771 0 : sm_p = new MFMSCleanImageSkyModel(userScaleSizes_p,
3772 : stoplargenegatives_p,
3773 : stoppointmode_p,
3774 0 : smallScaleBias_p);
3775 : } else {
3776 0 : sm_p = new MFMSCleanImageSkyModel(nscales_p,
3777 : stoplargenegatives_p,
3778 : stoppointmode_p,
3779 0 : smallScaleBias_p);
3780 : }
3781 : // if(ftmachine_p=="mosaic"|| ftmachine_p=="wproject")
3782 : // For some reason this does not seem to work without full
3783 0 : sm_p->setSubAlgorithm("full");
3784 :
3785 0 : doMultiFields_p = true;
3786 : os << LogIO::NORMAL << "Using multifield multi-scale clean" // Loglevel INFO
3787 0 : << LogIO::POST;
3788 : }
3789 0 : else if (algorithm=="wfclark" || algorithm=="wf") {
3790 : // Support serial and parallel specializations
3791 0 : setWFCleanImageSkyModel();
3792 0 : sm_p->setSubAlgorithm("clark");
3793 0 : doMultiFields_p = false;
3794 : os << LogIO::NORMAL // Loglevel INFO
3795 0 : << "Using wide-field algorithm with Clark clean" << LogIO::POST;
3796 : }
3797 0 : else if (algorithm=="wfhogbom") {
3798 : // Support serial and parallel specializations
3799 0 : setWFCleanImageSkyModel();
3800 0 : sm_p->setSubAlgorithm("hogbom");
3801 0 : doMultiFields_p = false;
3802 : os << LogIO::NORMAL // Loglevel INFO
3803 0 : << "Using wide-field algorithm with Hogbom clean" << LogIO::POST;
3804 : }
3805 0 : else if (algorithm=="msmfs") {
3806 0 : doMultiFields_p = false;
3807 0 : doWideBand_p = true;
3808 :
3809 : // check for wrong ftmachine specs.
3810 0 : if ( (ftmachine_p != "ft") && (ftmachine_p != "wproject") &&
3811 0 : (ftmachine_p != "wbawp") && (ftmachine_p != "nift") &&
3812 0 : (ftmachine_p != "mosaic") && (ftmachine_p != "awproject") ) {
3813 : os << LogIO::SEVERE
3814 : << "Multi-scale Multi-frequency Clean currently works only with ft, wproject and mosaic (and wbawp,nift,awproject)"
3815 0 : << LogIO::POST;
3816 0 : return retval;
3817 : }
3818 :
3819 0 : useNewMTFT_p=false;
3820 0 : if( ftmachine_p == "awproject" ) { useNewMTFT_p=true; }
3821 :
3822 :
3823 0 : if (!scaleInfoValid_p) {
3824 0 : this->unlock();
3825 0 : os << LogIO::WARN << "Scales not yet set, using power law" << LogIO::POST;
3826 0 : sm_p = new WBCleanImageSkyModel(ntaylor_p, 1 ,reffreq_p);
3827 : }
3828 0 : if (scaleMethod_p=="uservector") {
3829 0 : sm_p = new WBCleanImageSkyModel(ntaylor_p,userScaleSizes_p,reffreq_p);
3830 : } else {
3831 0 : sm_p = new WBCleanImageSkyModel(ntaylor_p,nscales_p,reffreq_p);
3832 : }
3833 : os << LogIO::NORMAL // Loglevel INFO
3834 0 : << "Using multi frequency synthesis algorithm" << LogIO::POST;
3835 0 : ((WBCleanImageSkyModel*)sm_p)->imageNames = Vector<String>(image);
3836 : /* Check masks. Should be only one per field. Duplicate the name ntaylor_p times
3837 : Note : To store taylor-coefficients, msmfs uses the same data structure as for
3838 : multi-field imaging. In the case of multifield and msmfs, the list of
3839 : images is nested and follows a field-major ordering.
3840 : All taylor-coeffs for a single field should have the same mask (for now).
3841 : For now, since only single-field is allowed for msmfs, we have the following.*/
3842 : }
3843 : else {
3844 0 : this->unlock();
3845 : os << LogIO::SEVERE << "Unknown algorithm: " << algorithm
3846 0 : << LogIO::POST;
3847 :
3848 0 : return retval;
3849 : }
3850 :
3851 0 : AlwaysAssert(sm_p, AipsError);
3852 0 : sm_p->setAlgorithm("clean");
3853 :
3854 : // if (!se_p)
3855 0 : if(!createSkyEquation(modelNames, fixed, maskNames, complist))
3856 : {
3857 :
3858 0 : return retval;
3859 : }
3860 0 : os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
3861 0 : }
3862 : else{
3863 : //adding or modifying mask associated with skyModel
3864 0 : addMasksToSkyEquation(maskNames,fixed);
3865 : }
3866 : //No need to add residuals will let sm_p use tmpimage ones and we'll copy them in restore
3867 0 : if(!addResiduals(residualNames))
3868 0 : throw(AipsError("Problem in attaching to residual images"));
3869 : // The old plot that showed how much flux was being incorporated in each
3870 : // scale. No longer available, slated for removal.
3871 : // if (displayProgress) {
3872 : // sm_p->setDisplayProgress(true);
3873 : // sm_p->setPGPlotter( getPGPlotter() );
3874 : // }
3875 :
3876 :
3877 :
3878 0 : sm_p->setGain(gain);
3879 0 : sm_p->setNumberIterations(niter);
3880 0 : sm_p->setThreshold(threshold.get("Jy").getValue());
3881 0 : sm_p->setCycleFactor(cyclefactor_p);
3882 0 : sm_p->setCycleSpeedup(cyclespeedup_p);
3883 0 : sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p);
3884 : {
3885 0 : ostringstream oos;
3886 0 : oos << "Clean gain = " <<gain<<", Niter = "<<niter<<", Threshold = "
3887 0 : << threshold;
3888 0 : os << LogIO::NORMAL << String(oos) << LogIO::POST; // More for the
3889 : // logfile than the
3890 : // log window.
3891 0 : }
3892 :
3893 : os << LogIO::NORMAL << (firstrun ? "Start" : "Continu")
3894 0 : << "ing deconvolution" << LogIO::POST; // Loglevel PROGRESS
3895 0 : if(se_p->solveSkyModel()) {
3896 : os << LogIO::NORMAL
3897 : << (niter == 0 ? "Image OK" : "Successfully deconvolved image")
3898 0 : << LogIO::POST; // Loglevel PROGRESS
3899 : }
3900 : else {
3901 0 : converged=false;
3902 0 : os << LogIO::NORMAL << "Threshhold not reached yet." << LogIO::POST; // Loglevel PROGRESS
3903 : }
3904 :
3905 :
3906 0 : printbeam(sm_p, os, firstrun);
3907 :
3908 0 : if(((algorithm.substr(0,5)=="clark") || algorithm=="hogbom" ||
3909 0 : algorithm=="multiscale") && (niter != 0))
3910 : //write the model visibility to ms for now
3911 0 : sm_p->solveResiduals(*se_p, true);
3912 :
3913 0 : for (uInt k=0 ; k < residuals_p.nelements(); ++k){
3914 0 : (residuals_p[k])->copyData(sm_p->getResidual(k));
3915 : }
3916 : /////////////
3917 :
3918 : //cerr << "Time taken " << omp_get_wtime()-wtime0 << endl;
3919 : ////////////
3920 0 : retval.define("maxresidual", (sm_p->threshold()));
3921 0 : retval.define("iterations", (sm_p->numberIterations()));
3922 0 : retval.define("converged", converged);
3923 0 : savePSF(psfnames);
3924 0 : redoSkyModel_p=false;
3925 0 : writeFluxScales(fluxscale_p);
3926 : // restoreImages(image); // Moved to iClean so that it happens only once.
3927 :
3928 :
3929 0 : this->unlock();
3930 :
3931 0 : return retval;
3932 0 : }
3933 0 : catch (PSFZero& x)
3934 : {
3935 : //os << LogIO::WARN << x.what() << LogIO::POST;
3936 0 : savePSF(psfnames);
3937 0 : this->unlock();
3938 0 : throw(AipsError(String("PSFZero ")+ x.getMesg() + String(" : Please check that the required data exists and is not flagged.")));
3939 : return retval;
3940 0 : }
3941 0 : catch (exception &x) {
3942 0 : this->unlock();
3943 0 : destroySkyEquation();
3944 0 : throw(AipsError(x.what()));
3945 :
3946 : return retval;
3947 0 : }
3948 :
3949 0 : catch(...){
3950 0 : this->unlock();
3951 0 : destroySkyEquation();
3952 : //Unknown exception...
3953 0 : throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
3954 0 : }
3955 : this->unlock();
3956 :
3957 : os << LogIO::NORMAL << "Exiting Imager::clean" << LogIO::POST; // Loglevel PROGRESS
3958 : return retval;
3959 0 : }
3960 :
3961 : // Mem algorithm
3962 0 : Bool Imager::mem(const String& algorithm,
3963 : const Int niter,
3964 : const Quantity& sigma,
3965 : const Quantity& targetFlux,
3966 : const Bool constrainFlux,
3967 : const Bool displayProgress,
3968 : const Vector<String>& model,
3969 : const Vector<Bool>& fixed,
3970 : const String& complist,
3971 : const Vector<String>& prior,
3972 : const Vector<String>& mask,
3973 : const Vector<String>& image,
3974 : const Vector<String>& residual)
3975 : {
3976 0 : if(!valid())
3977 : {
3978 0 : return false;
3979 : }
3980 0 : logSink_p.clearLocally();
3981 0 : LogIO os(LogOrigin("imager", "mem()"), logSink_p);
3982 :
3983 0 : this->lock();
3984 : try {
3985 0 : if(!assertDefinedImageParameters())
3986 : {
3987 0 : return false;
3988 : }
3989 0 : os << LogIO::NORMAL << "Deconvolving images with MEM" << LogIO::POST; // Loglevel PROGRESS
3990 :
3991 0 : Int nmodels=model.nelements();
3992 : os << LogIO::NORMAL // Loglevel INFO
3993 0 : << "Found " << nmodels << " specified model images" << LogIO::POST;
3994 :
3995 0 : if(model.nelements()>0) {
3996 0 : for (uInt thismodel=0;thismodel<model.nelements();++thismodel) {
3997 0 : if(model(thismodel)=="") {
3998 0 : this->unlock();
3999 : os << LogIO::SEVERE << "Need a name for model "
4000 0 : << thismodel << LogIO::POST;
4001 0 : return false;
4002 : }
4003 : }
4004 : }
4005 :
4006 0 : Vector<String> modelNames=model;
4007 : // Make first image with the required shape and coordinates only if
4008 : // it doesn't exist yet. Otherwise we'll throw an exception later
4009 0 : if(modelNames(0)=="") modelNames(0)=imageName()+".mem";
4010 0 : if(!Table::isWritable(modelNames(0))) {
4011 0 : make(modelNames(0));
4012 : }
4013 :
4014 0 : Vector<String> maskNames(nmodels);
4015 0 : if(Int(mask.nelements())==nmodels) {
4016 0 : maskNames=mask;
4017 0 : for(Int k=0; k < nmodels; ++k){
4018 0 : if(mask(k)!=""&& !Table::isReadable(mask(k))) {
4019 : os << LogIO::WARN
4020 : << "Mask" << mask(k)
4021 : << " is unreadable; ignoring masks altogether "
4022 0 : << LogIO::POST;
4023 0 : maskNames.resize(1);
4024 0 : maskNames(0)="";
4025 : }
4026 : }
4027 : }
4028 : else {
4029 0 : maskNames.resize(1);
4030 0 : maskNames(0)="";
4031 : }
4032 :
4033 : // Always fill in the residual images
4034 0 : Vector<String> residualNames(nmodels);
4035 0 : if(Int(residual.nelements())==nmodels) {
4036 0 : residualNames=residual;
4037 : }
4038 : else {
4039 0 : residualNames="";
4040 : }
4041 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
4042 0 : if(residualNames(thismodel)=="") {
4043 0 : residualNames(thismodel)=modelNames(thismodel)+".residual";
4044 : }
4045 0 : removeTable(residualNames(thismodel));
4046 0 : if(!clone(model(thismodel), residualNames(thismodel)))
4047 : {
4048 0 : return false;
4049 : }
4050 : }
4051 :
4052 : // Make an ImageSkyModel with the specified polarization representation
4053 : // (i.e. circular or linear)
4054 0 : if(algorithm=="entropy") {
4055 0 : sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
4056 0 : targetFlux.get("Jy").getValue(),
4057 : constrainFlux,
4058 : prior,
4059 0 : algorithm);
4060 : os << LogIO::NORMAL // Loglevel INFO
4061 0 : << "Using single-field algorithm with Maximum Entropy" << LogIO::POST;
4062 0 : if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
4063 0 : sm_p->setSubAlgorithm("full");
4064 : }
4065 0 : else if (algorithm=="emptiness") {
4066 0 : sm_p = new CEMemImageSkyModel(sigma.get("Jy").getValue(),
4067 0 : targetFlux.get("Jy").getValue(),
4068 : constrainFlux,
4069 : prior,
4070 0 : algorithm);
4071 : os << LogIO::NORMAL // Loglevel INFO
4072 0 : << "Using single-field algorithm with Maximum Emptiness" << LogIO::POST;
4073 0 : if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
4074 0 : sm_p->setSubAlgorithm("full");
4075 : }
4076 0 : else if (algorithm=="mfentropy") {
4077 0 : sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
4078 0 : targetFlux.get("Jy").getValue(),
4079 : constrainFlux,
4080 : prior,
4081 0 : algorithm);
4082 0 : doMultiFields_p = true;
4083 0 : os << LogIO::NORMAL << "Using Maximum Entropy" << LogIO::POST; // Loglevel INFO
4084 : // if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
4085 0 : sm_p->setSubAlgorithm("full");
4086 0 : } else if (algorithm=="mfemptiness") {
4087 0 : sm_p = new MFCEMemImageSkyModel(sigma.get("Jy").getValue(),
4088 0 : targetFlux.get("Jy").getValue(),
4089 : constrainFlux,
4090 : prior,
4091 0 : algorithm);
4092 0 : doMultiFields_p = true;
4093 0 : os << LogIO::NORMAL << "Using Maximum Emptiness" << LogIO::POST; // Loglevel INFO
4094 : // if(ftmachine_p=="mosaic" ||ftmachine_p=="wproject" )
4095 0 : sm_p->setSubAlgorithm("full");
4096 : } else {
4097 0 : this->unlock();
4098 0 : os << LogIO::SEVERE << "Unknown algorithm: " << algorithm << LogIO::POST;
4099 0 : return false;
4100 : }
4101 0 : AlwaysAssert(sm_p, AipsError);
4102 0 : sm_p->setAlgorithm("mem");
4103 0 : if (displayProgress) {
4104 0 : sm_p->setDisplayProgress(true);
4105 : }
4106 0 : sm_p->setNumberIterations(niter);
4107 0 : sm_p->setCycleFactor(cyclefactor_p); // used by mf algs
4108 0 : sm_p->setCycleSpeedup(cyclespeedup_p); // used by mf algs
4109 0 : sm_p->setCycleMaxPsfFraction(cyclemaxpsffraction_p); // used by mf algs
4110 :
4111 : {
4112 0 : ostringstream oos;
4113 0 : oos << "MEM algorithm = " <<algorithm<<", Niter = "<<niter<<", Sigma = "
4114 0 : <<sigma << ", Target Flux = " << targetFlux;
4115 0 : os << LogIO::DEBUG1 << String(oos) << LogIO::POST;
4116 0 : }
4117 :
4118 : // if (!se_p)
4119 0 : if(!createSkyEquation(modelNames, fixed, maskNames, complist))
4120 : {
4121 0 : return false;
4122 : }
4123 0 : os << LogIO::NORMAL3 << "Created Sky Equation" << LogIO::POST;
4124 :
4125 0 : addResidualsToSkyEquation(residualNames);
4126 :
4127 0 : os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
4128 0 : if(se_p->solveSkyModel()) {
4129 0 : os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
4130 : }
4131 : else {
4132 0 : os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
4133 : }
4134 :
4135 : // Get the PSF fit while we are here
4136 0 : if(!beamValid_p){
4137 0 : ImageBeamSet beam=sm_p->beam(0);
4138 0 : if(beam.nelements() > 0){
4139 : /*beam_p.setMajorMinor(
4140 : Quantity(abs(beam(0)), "arcsec"), Quantity(abs(beam(1)), "arcsec")
4141 : );
4142 : beam_p.setPA(Quantity(beam(2), "deg"));
4143 : */
4144 0 : beam_p=beam;
4145 0 : beamValid_p=true;
4146 : }
4147 0 : }
4148 0 : if(algorithm=="entropy" || algorithm=="emptiness" )
4149 0 : sm_p->solveResiduals(*se_p, true);
4150 0 : writeFluxScales(fluxscale_p);
4151 0 : restoreImages(image);
4152 0 : destroySkyEquation();
4153 0 : this->writeHistory(os);
4154 : try{
4155 : { // write data processing history into image logtable
4156 0 : LoggerHolder imagelog (false);
4157 0 : LogSink& sink = imagelog.sink();
4158 0 : LogOrigin lor( String("imager"), String("mem()") );
4159 0 : LogMessage msg(lor);
4160 0 : sink.postLocally(msg);
4161 0 : MSHistoryColumns msHis(ms_p->history());
4162 0 : transferHistory(imagelog, msHis);
4163 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
4164 : PagedImage<Float> restoredImage(image(thismodel),
4165 0 : TableLock(TableLock::UserLocking));
4166 0 : LoggerHolder& log = restoredImage.logger();
4167 0 : log.append(imagelog);
4168 0 : log.flush();
4169 0 : }
4170 0 : }
4171 : }
4172 0 : catch(exception& x){
4173 :
4174 0 : os << LogIO::WARN << "Caught exception: " << x.what()
4175 0 : << LogIO::POST;
4176 : os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
4177 0 : <<LogIO::POST;
4178 : //continue and wrap up this function as normal
4179 :
4180 0 : }
4181 0 : catch(...){
4182 : //Unknown exception...
4183 0 : throw(AipsError("Unknown exception caught ...imager/casa may need to be exited"));
4184 0 : }
4185 :
4186 0 : this->unlock();
4187 :
4188 0 : return true;
4189 0 : } catch (exception& x) {
4190 0 : this->unlock();
4191 0 : throw(AipsError(x.what()));
4192 :
4193 : return false;
4194 0 : }
4195 : this->unlock();
4196 : return true;
4197 :
4198 0 : }
4199 :
4200 :
4201 : // NNLS algorithm
4202 0 : Bool Imager::nnls(const String&, const Int niter, const Float tolerance,
4203 : const Vector<String>& model, const Vector<Bool>& fixed,
4204 : const String& complist,
4205 : const Vector<String>& fluxMask,
4206 : const Vector<String>& dataMask,
4207 : const Vector<String>& residual,
4208 : const Vector<String>& image)
4209 : {
4210 0 : if(!valid()) return false;
4211 0 : LogIO os(LogOrigin("imager", "nnls()", WHERE));
4212 :
4213 0 : this->lock();
4214 : try {
4215 0 : if(!assertDefinedImageParameters()) return false;
4216 :
4217 0 : os << LogIO::NORMAL << "Performing NNLS deconvolution" << LogIO::POST; // Loglevel PROGRESS
4218 :
4219 0 : if(niter<0) {
4220 0 : this->unlock();
4221 0 : os << LogIO::SEVERE << "Number of iterations must be positive" << LogIO::POST;
4222 0 : return false;
4223 : }
4224 0 : if(tolerance<0.0) {
4225 0 : this->unlock();
4226 0 : os << LogIO::SEVERE << LogIO::SEVERE << "Tolerance must be positive" << LogIO::POST;
4227 0 : return false;
4228 : }
4229 :
4230 : // Add the images to the ImageSkyModel
4231 0 : Int nmodels=model.nelements();
4232 0 : if(nmodels>1) os<< "Can only process one model" << LogIO::POST;
4233 :
4234 0 : if(model(0)=="") {
4235 0 : this->unlock();
4236 0 : os << LogIO::SEVERE << "Need a name for model " << LogIO::POST;
4237 0 : return false;
4238 : }
4239 :
4240 0 : if(!Table::isWritable(model(0))) {
4241 0 : make(model(0));
4242 0 : this->lock();
4243 : }
4244 :
4245 : // Always fill in the residual images
4246 0 : Vector<String> residualNames(nmodels);
4247 0 : if(Int(residual.nelements())==nmodels) {
4248 0 : residualNames=residual;
4249 : }
4250 : else {
4251 0 : residualNames="";
4252 : }
4253 0 : for (Int thismodel=0;thismodel<Int(model.nelements());++thismodel) {
4254 0 : if(residualNames(thismodel)=="") {
4255 0 : residualNames(thismodel)=model(thismodel)+".residual";
4256 : }
4257 0 : removeTable(residualNames(thismodel));
4258 0 : if(!clone(model(thismodel), residualNames(thismodel))) return false;
4259 : }
4260 :
4261 : // Now make the NNLS ImageSkyModel
4262 0 : sm_p= new NNLSImageSkyModel();
4263 0 : sm_p->setNumberIterations(niter);
4264 0 : sm_p->setTolerance(tolerance);
4265 0 : sm_p->setAlgorithm("nnls");
4266 : os << LogIO::DEBUG1
4267 0 : << "NNLS Niter = " << niter << ", Tolerance = " << tolerance << LogIO::POST;
4268 :
4269 : // if (!se_p)
4270 0 : if(!createSkyEquation(model, fixed, dataMask, fluxMask, complist)) return false;
4271 :
4272 0 : addResidualsToSkyEquation(residualNames);
4273 :
4274 0 : os << LogIO::NORMAL << "Starting deconvolution" << LogIO::POST; // Loglevel PROGRESS
4275 :
4276 0 : if(se_p->solveSkyModel()) {
4277 0 : os << LogIO::NORMAL << "Successfully deconvolved image" << LogIO::POST; // Loglevel INFO
4278 : }
4279 : else {
4280 0 : os << LogIO::NORMAL << "Nominally failed deconvolution" << LogIO::POST; // Loglevel INFO
4281 : }
4282 :
4283 : // Get the PSF fit while we are here
4284 0 : StokesImageUtil::FitGaussianPSF(sm_p->PSF(0), beam_p);
4285 0 : beamValid_p=true;
4286 :
4287 :
4288 : // Restore the image
4289 0 : restoreImages(image);
4290 :
4291 0 : destroySkyEquation();
4292 0 : this->unlock();
4293 0 : return true;
4294 0 : } catch (AipsError x) {
4295 0 : this->unlock();
4296 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
4297 0 : return false;
4298 0 : }
4299 : this->unlock();
4300 : return true;
4301 0 : }
4302 :
4303 : // Fourier transform the model and componentlist
4304 0 : Bool Imager::ft(const Vector<String>& model, const String& complist,
4305 : const Bool incremental, const Double phaseCenTime)
4306 : {
4307 0 : if(!valid()) return false;
4308 :
4309 0 : LogIO os(LogOrigin("imager", "ft()", WHERE));
4310 :
4311 0 : if (wvi_p==NULL)
4312 0 : os << LogIO::WARN << "Please make sure MS is writable when using Imager::ft" << LogIO::EXCEPTION;
4313 :
4314 0 : this->lock();
4315 : try {
4316 :
4317 0 : if(!redoSkyModel_p){
4318 : //let us try to update the sm_p then
4319 : //so as to keep the state and psf's etc if they have been calculated
4320 : //useful when cleaning, modify/clip model then predict, selfcal and clean again
4321 0 : if(!updateSkyModel(model, complist))
4322 0 : destroySkyEquation();
4323 : }
4324 :
4325 : os << LogIO::NORMAL // Loglevel INFO
4326 0 : << String("Fourier transforming: ") +
4327 0 : (incremental ? String("adding to "): String("replacing "))+
4328 0 : (useModelCol_p ? String("MODEL_DATA column") : String("visibility model header")) << LogIO::POST;
4329 :
4330 0 : if (redoSkyModel_p){
4331 0 : if(!createSkyEquation(model, complist)) return false;
4332 : }
4333 0 : if(incremental){
4334 0 : for (Int mod=0; mod < (sm_p->numberOfModels()); ++mod){
4335 0 : (sm_p->deltaImage(mod)).copyData(sm_p->image(mod));
4336 : }
4337 : }
4338 0 : se_p->setPhaseCenterTime(phaseCenTime);
4339 0 : se_p->predict(incremental);
4340 :
4341 : // destroySkyEquation();
4342 :
4343 0 : this->unlock();
4344 0 : return true;
4345 0 : } catch (AipsError x) {
4346 0 : this->unlock();
4347 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
4348 0 : return false;
4349 0 : }
4350 : this->unlock();
4351 : return true;
4352 0 : }
4353 :
4354 0 : Bool Imager::setjy(const Int fieldid,
4355 : const Int spectralwindowid,
4356 : const Vector<Double>& fluxDensity, const String& standard)
4357 : {
4358 : // the old interface to new interface
4359 0 : String fieldnames="";
4360 0 : String spwstring="";
4361 0 : Vector<Int>fldids(1,fieldid);
4362 0 : Vector<Int>spwids(1,spectralwindowid);
4363 0 : return setjy(fldids, spwids, fieldnames, spwstring, fluxDensity, standard);
4364 :
4365 0 : }
4366 :
4367 0 : Bool Imager::setjy(const Vector<Int>& /*fieldid*/,
4368 : const Vector<Int>& /*spectralwindowid*/,
4369 : const String& fieldnames, const String& spwstring,
4370 : const Vector<Double>& fluxDensity, const String& standard)
4371 : {
4372 0 : if(!valid()) return false;
4373 0 : logSink_p.clearLocally();
4374 0 : LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
4375 0 : this->lock();
4376 :
4377 0 : String tempCL;
4378 : try {
4379 0 : Bool precompute=(fluxDensity(0) <= 0);
4380 :
4381 : // Figure out which fields/spws to treat
4382 0 : Record selrec=ms_p->msseltoindex(spwstring, fieldnames);
4383 0 : Vector<Int> fldids(selrec.asArrayInt("field"));
4384 0 : Vector<Int> spwids(selrec.asArrayInt("spw"));
4385 :
4386 0 : expand_blank_sel(spwids, ms_p->spectralWindow().nrow());
4387 0 : expand_blank_sel(fldids, ms_p->field().nrow());
4388 :
4389 : // Loop over field id. and spectral window id.
4390 0 : Vector<Double> fluxUsed(4);
4391 0 : String fluxScaleName;
4392 0 : Bool matchedScale=false;
4393 : Int spwid, fldid;
4394 0 : MSColumns msc(*ms_p);
4395 0 : ConstantSpectrum cspectrum;
4396 : // TT
4397 0 : Double meantime = msc.time()(0);
4398 0 : meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
4399 0 : MEpoch mtime(msc.timeMeas()(0));
4400 0 : mtime.set(Quantity(meantime, "s"));
4401 :
4402 :
4403 0 : for (uInt kk=0; kk<fldids.nelements(); ++kk) {
4404 0 : fldid=fldids[kk];
4405 : // Extract field name and field center position
4406 0 : MDirection position=msc.field().phaseDirMeas(fldid, meantime);
4407 0 : String fieldName=msc.field().name()(fldid);
4408 :
4409 0 : for (uInt jj=0; jj< spwids.nelements(); ++jj) {
4410 0 : spwid=spwids[jj];
4411 :
4412 : // Determine spectral window center frequency
4413 0 : IPosition ipos(1,0);
4414 0 : MFrequency mfreq=msc.spectralWindow().chanFreqMeas()(spwid)(ipos);
4415 0 : Array<Double> freqArray;
4416 0 : msc.spectralWindow().chanFreq().get(spwid, freqArray, true);
4417 0 : Double medianFreq=median(freqArray);
4418 0 : mfreq.set(MVFrequency(medianFreq));
4419 :
4420 0 : fluxUsed=fluxDensity;
4421 0 : fluxScaleName="user-specified";
4422 0 : if (precompute) {
4423 : // Pre-compute flux density for standard sources if not specified
4424 : // using the specified flux scale standard or catalog.
4425 :
4426 :
4427 : FluxStandard::FluxScale fluxScaleEnum;
4428 0 : matchedScale=FluxStandard::matchStandard(standard, fluxScaleEnum,
4429 : fluxScaleName);
4430 : (void)matchedScale;
4431 0 : FluxStandard fluxStd(fluxScaleEnum);
4432 0 : Flux<Double> returnFlux, returnFluxErr;
4433 :
4434 0 : if (fluxStd.compute(fieldName, position, mfreq, mtime, returnFlux, returnFluxErr)) {
4435 : // Standard reference source identified
4436 0 : returnFlux.value(fluxUsed);
4437 : }
4438 :
4439 : // dgoscha, NCSA, 02 May, 2002
4440 : // this else condtion is to handle the case where the user
4441 : // specifies standard='SOURCE' in the setjy argument. This will
4442 : // then look into the SOURCE_MODEL column of the SOURCE subtable
4443 : // for a table-record entry that points to a component list with the
4444 : // model information in it.
4445 :
4446 :
4447 0 : else if (standard==String("SOURCE")) {
4448 : // Look in the SOURCE_MODEL column of the SOURCE subtable for
4449 : // the name of the CL which contains the model.
4450 :
4451 : // First test to make sure the SOURCE_MODEL column exists.
4452 0 : if (ms_p->source().tableDesc().isColumn("SOURCE_MODEL")) {
4453 0 : TableRecord modelRecord;
4454 0 : msc.source().sourceModel().get(0, modelRecord);
4455 :
4456 : // Get the name of the model component list from the table record
4457 : Table modelRecordTable =
4458 0 : modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
4459 0 : String modelCLName = modelRecordTable.tableName();
4460 0 : modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
4461 :
4462 : // Now grab the flux from the model component list and use.
4463 0 : ComponentList modelCL = ComponentList(Path(modelCLName), true);
4464 0 : SkyComponent fluxComponent = modelCL.component(fldid);
4465 :
4466 0 : fluxUsed = 0;
4467 0 : fluxUsed = real(fluxComponent.flux().value());
4468 0 : fluxScaleName = modelCLName;
4469 0 : }
4470 : else {
4471 : os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
4472 : << LogIO::SEVERE << "Using default, I=1.0"
4473 0 : << LogIO::POST;
4474 0 : fluxUsed = 0;
4475 0 : fluxUsed(0) = 1.0;
4476 : }
4477 : }
4478 :
4479 : else {
4480 : // Source not found; use Stokes I=1.0 Jy for now
4481 0 : fluxUsed=0;
4482 0 : fluxUsed(0)=1.0;
4483 0 : fluxScaleName="default";
4484 : };
4485 0 : }
4486 :
4487 : // Set the component flux density
4488 0 : Flux<Double> fluxval;
4489 0 : fluxval.setValue(fluxUsed);
4490 :
4491 : // Create a point component at the field center
4492 : // with the specified flux density
4493 0 : PointShape point(position);
4494 0 : SkyComponent skycomp(fluxval, point, cspectrum);
4495 :
4496 : // Create a component list containing this entry
4497 0 : String baseString=msname_p + "." + fieldName + ".spw" +
4498 0 : String::toString(spwid);
4499 0 : tempCL=baseString + ".tempcl";
4500 :
4501 : // Force a call to the ComponentList destructor
4502 : // using scoping rules.
4503 : {
4504 0 : ComponentList cl;
4505 0 : cl.add(skycomp);
4506 0 : cl.rename(tempCL, Table::New);
4507 0 : }
4508 :
4509 : // Select the uv-data for this field and spw. id.;
4510 : // all frequency channels selected.
4511 0 : Vector<Int> selectSpw(1), selectField(1);
4512 0 : selectSpw(0)=spwid;
4513 0 : selectField(0)=fldid;
4514 0 : String msSelectString = "";
4515 0 : Vector<Int> numDeChan(1);
4516 0 : numDeChan[0]=0;
4517 0 : Vector<Int> begin(1);
4518 0 : begin[0]=0;
4519 0 : Vector<Int> stepsize(1);
4520 0 : stepsize[0]=1;
4521 0 : setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(),
4522 0 : MRadialVelocity(),
4523 0 : selectSpw, selectField, msSelectString, "", "", Vector<Int>(),
4524 : "", "", "", "", "", "",true);
4525 :
4526 0 : if (!nullSelect_p) {
4527 :
4528 : // Transform the component model table
4529 0 : Vector<String> model;
4530 0 : ft(model, tempCL, false);
4531 :
4532 : // Log flux density used for this field and spectral window
4533 0 : os.output().width(12);
4534 0 : os << fieldName << " spwid=";
4535 0 : os.output().width(3);
4536 0 : os << (spwid) << " ";
4537 0 : os.output().width(0);
4538 0 : os.output().precision(4);
4539 0 : os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
4540 0 : os << "Q=" << fluxUsed(1) << ", ";
4541 0 : os << "U=" << fluxUsed(2) << ", ";
4542 0 : os << "V=" << fluxUsed(3) << "] Jy, ";
4543 0 : os << ("(" + fluxScaleName + ")") << LogIO::POST;
4544 0 : };
4545 :
4546 : // Delete the temporary component list and image tables
4547 0 : TableUtil::deleteTable(tempCL);
4548 :
4549 0 : }
4550 0 : }
4551 0 : this->writeHistory(os);
4552 0 : this->unlock();
4553 0 : return true;
4554 :
4555 0 : } catch (AipsError x) {
4556 0 : this->unlock();
4557 0 : if(TableUtil::canDeleteTable(tempCL)) TableUtil::deleteTable(tempCL);
4558 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
4559 0 : return false;
4560 0 : }
4561 : return true;
4562 0 : }
4563 :
4564 : // This is the one used by im.setjy() (because it has a model arg).
4565 : // CURRENT SETJY CODE
4566 0 : Record Imager::setjy(const Vector<Int>& /*fieldid*/,
4567 : const Vector<Int>& /*spectralwindowid*/,
4568 : const String& fieldnames, const String& spwstring,
4569 : const String& model,
4570 : const Vector<Double>& fluxDensity,
4571 : const String& standard, const Bool chanDep,
4572 : //const Double spix, const MFrequency& reffreq,
4573 : const Vector<Double>& spix, const MFrequency& reffreq,
4574 : const Vector<Double>& pipars,const Vector<Double>& papars,
4575 : const Double& rotMeas,
4576 : const String& timerange, const String& scanstr,
4577 : const String& intentstr, const String& obsidstr,
4578 : const String& interpolation)
4579 : {
4580 : //if(!valid())
4581 : //return false;
4582 :
4583 : //Bool didAnything = false;
4584 :
4585 0 : Record retval;
4586 0 : if(!valid()) {
4587 0 : retval.define("process",false);
4588 0 : return retval;
4589 : }
4590 :
4591 0 : logSink_p.clearLocally();
4592 0 : LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
4593 0 : this->lock();
4594 :
4595 : // user specified flux densities (IQUV), global to the spws and fields
4596 0 : Vector<Double> fluxdens = fluxDensity;
4597 0 : if(fluxDensity.nelements() < 4){
4598 0 : fluxdens.resize(4,true);
4599 0 : for(Int i = fluxDensity.nelements(); i < 4; ++i)
4600 0 : fluxdens[i] = 0.0;
4601 : }
4602 :
4603 0 : Vector<String> tempCLs;
4604 0 : TempImage<Float> *tmodimage(NULL);
4605 :
4606 : try{
4607 0 : Bool precompute = fluxdens[0] < 0.0;
4608 :
4609 : // Figure out which fields/spws to treat
4610 : // including intent info
4611 0 : MSSelection mssel;
4612 0 : mssel.setFieldExpr(fieldnames);
4613 0 : mssel.setSpwExpr(spwstring);
4614 0 : mssel.setStateExpr(intentstr);
4615 0 : TableExprNode exprNode = mssel.toTableExprNode(&(*ms_p));
4616 : //Vector<Int> fldids;
4617 0 : Vector<Int> fldids(mssel.getFieldList());
4618 0 : Vector<Int> selToRawSpwIds(mssel.getSpwList());
4619 : // if intent is given try to do AND with fieldIds
4620 0 : if (intentstr!="") {
4621 0 : mssel_p = new MeasurementSet((*ms_p)(exprNode), &(*ms_p));
4622 0 : MSColumns tmpmsc(*mssel_p);
4623 0 : Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
4624 0 : if (fldidv.nelements()==0)
4625 0 : throw(AipsError("No field ids were selected, please check input parameters"));
4626 0 : std::set<Int> ufldids(fldidv.begin(),fldidv.end());
4627 0 : std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
4628 0 : fldids.resize(tmpv.size());
4629 0 : uInt count=0;
4630 0 : for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
4631 : {
4632 0 : fldids(count) = *it;
4633 0 : count++;
4634 : }
4635 0 : }
4636 : //else {
4637 : // fldids(mssel.getFieldList());
4638 : //}
4639 : //cerr<<"fldids.nelements()="<<fldids.nelements()<<endl;
4640 : //for (uInt i = 0; i < fldids.nelements(); i++) {
4641 : // cerr<<"fldids="<<fldids(i)<<endl;
4642 : //}
4643 : //Record selrec = ms_p->msseltoindex(spwstring, fieldnames);
4644 : //Vector<Int> fldids(selrec.asArrayInt("field"));
4645 : //Vector<Int> selToRawSpwIds(selrec.asArrayInt("spw"));
4646 :
4647 0 : expand_blank_sel(selToRawSpwIds, ms_p->spectralWindow().nrow());
4648 0 : expand_blank_sel(fldids, ms_p->field().nrow());
4649 :
4650 : // Warn against multiple fields in some circumstances.
4651 0 : if (fldids.nelements() > 1 && (model != "" || !precompute)) {
4652 0 : String errmsg("setjy is applying a single ");
4653 :
4654 0 : if(model != ""){
4655 0 : errmsg += "modimage";
4656 0 : if(!precompute)
4657 0 : errmsg += " or ";
4658 : }
4659 :
4660 0 : if(!precompute)
4661 0 : errmsg += "fluxdensity";
4662 :
4663 0 : errmsg += " to multiple fields!\n";
4664 : os << LogIO::WARN
4665 : << errmsg
4666 : << "This could be a user error, but sometimes a single name will\n"
4667 : << "resolve to > 1 field index.\n"
4668 0 : << LogIO::POST;
4669 : //throw(AipsError(errmsg));
4670 0 : }
4671 :
4672 0 : os << LogIO::NORMAL;
4673 0 : if(precompute || spix[0] != 0.0)
4674 0 : os << "Using " << ((chanDep || (!precompute && spix[0] != 0.0)) ? "channel" :
4675 0 : "spw") << " dependent flux densities";
4676 : else
4677 0 : os << "The applied flux density does not depend on frequency.";
4678 0 : os << LogIO::POST;
4679 :
4680 : // Ignore user polarization if using an image.
4681 0 : if(model != "" &&
4682 0 : (fluxdens[1] != 0.0 || fluxdens[2] != 0.0 || fluxdens[3] != 0.0)){
4683 : os << LogIO::WARN
4684 : << "Using model image, so zeroing user QUV flux densities."
4685 0 : << LogIO::POST;
4686 0 : fluxdens[1] = fluxdens[2] = fluxdens[3] = 0.0;
4687 0 : writeHistory(os);
4688 : }
4689 :
4690 : // Loop over field id. and spectral window id.
4691 : //Vector<Double> fluxUsed(4);
4692 0 : String fluxScaleName("user-specified");
4693 : FluxStandard::FluxScale fluxScaleEnum;
4694 0 : if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
4695 0 : throw(AipsError(standard + " is not a recognized flux density scale"));
4696 :
4697 0 : FluxStandard fluxStd(fluxScaleEnum);
4698 0 : if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 ||
4699 0 : fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017 ) {
4700 0 : fluxStd.setInterpMethod(interpolation);
4701 : }
4702 :
4703 : // Setup the frequency, Flux, and ComponentList arrays.
4704 0 : uInt nspws = selToRawSpwIds.nelements();
4705 0 : Vector<Vector<Flux<Double> > > returnFluxes(nspws), returnFluxErrs(nspws);
4706 0 : Vector<Vector<MFrequency> > mfreqs(nspws);
4707 0 : Vector<Vector<Double> > fluxUsed(nspws); // fluxesUsed(nspws,4)
4708 0 : MSColumns msc(*ms_p);
4709 0 : MEpoch aveEpoch=MEpoch(msc.timeMeas()(0));
4710 : const Unit freqUnit = sjy_setup_arrs(returnFluxes, returnFluxErrs, fluxUsed, tempCLs, mfreqs,
4711 0 : msc.spectralWindow(), nspws, selToRawSpwIds,
4712 0 : chanDep);
4713 : // Processing for each field ***************************************************
4714 0 : for(Int fldInd = fldids.nelements(); fldInd--;){
4715 0 : Int fldid = fldids[fldInd];
4716 : // Extract field name and field center position
4717 0 : MDirection fieldDir = msc.field().phaseDirMeas(fldid, msc.time()(0));
4718 0 : String fieldName = msc.field().name()(fldid);
4719 0 : Bool foundSrc = false;
4720 :
4721 : //for returned flux densities
4722 :
4723 0 : Record retvalperField;
4724 : //
4725 : //fluxUsed = fluxdens;
4726 0 : fluxUsed(0) = fluxdens;
4727 : //if(precompute){
4728 : // Pre-compute flux density for standard sources if not specified
4729 : // using the specified flux scale standard or catalog.
4730 : //
4731 : // The flux densities are calculated for all spws at once to avoid
4732 : // repeatedly digging up the flux model (and possibly the ephemeris).
4733 : //
4734 : // TT: moving this outside of if(precompute) since selected ms (mssel_p)
4735 : // will be needed for other cases to clear the model using
4736 : // VisModelData::ClearModel()
4737 :
4738 0 : Vector<Int> selectField(1);
4739 0 : selectField[0] = fldid;
4740 0 : Vector<Int> numDeChan(1);
4741 0 : numDeChan[0] = 0;
4742 0 : Vector<Int> begin(1);
4743 0 : begin[0] = 0;
4744 0 : Vector<Int> stepsize(1);
4745 0 : stepsize[0] = 1;
4746 0 : String msSelectString = "";
4747 0 : setdata("none", numDeChan, begin, stepsize, MRadialVelocity(),
4748 0 : MRadialVelocity(),
4749 : selToRawSpwIds, selectField, msSelectString, timerange, "",
4750 0 : Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
4751 0 : if(nullSelect_p){
4752 0 : os << ((timerange == "" && scanstr == ""
4753 0 : && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
4754 : << "No data was selected for field " << fldid << "."
4755 0 : << LogIO::POST;
4756 0 : continue;
4757 : }
4758 0 : if(precompute){
4759 : // Make componentlist for each spw.
4760 : // Pre-compute flux density for standard sources if not specified
4761 : // using the specified flux scale standard or catalog.
4762 : //
4763 : // The flux densities are calculated for all spws at once to avoid
4764 : // repeatedly digging up the flux model (and possibly the ephemeris).
4765 : //
4766 0 : MSColumns msselc(*mssel_p);
4767 : //if(nullSelect_p || msselc.nrow() < 1){
4768 0 : if(!nullSelect_p and msselc.nrow() < 1){
4769 0 : os << ((timerange == "" && scanstr == ""
4770 0 : && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
4771 : << "No data was selected for field " << fldid << "."
4772 0 : << LogIO::POST;
4773 0 : continue;
4774 : }
4775 :
4776 : // chnage to return cocantenated CL?
4777 0 : foundSrc = sjy_computeFlux(os, fluxStd, returnFluxes, returnFluxErrs, tempCLs,
4778 : fluxUsed, fluxScaleName, aveEpoch, mfreqs, model, fieldName,
4779 : msselc, fldid, fieldDir, selToRawSpwIds, standard);
4780 : (void)foundSrc;
4781 0 : }
4782 :
4783 : //*************** For loop about spw starts here ****************************
4784 0 : Vector<Double> freqscaling;
4785 0 : Vector<Double> freqsOfScale;
4786 0 : Vector<Int> rawspwids(nspws);
4787 : // make raw spw id list
4788 0 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4789 0 : Int rawspwid = selToRawSpwIds[selspw];
4790 0 : rawspwids[selspw]=rawspwid;
4791 : }
4792 :
4793 : // move inside sjy_computeFlux - TT, 2014.06.13
4794 : /***
4795 : if(foundSrc){
4796 : // Log fluxes found from the standard catalog database to HISTORY table
4797 : // get I-flux density for the selected spw (returnFluxes[nspw][4])
4798 : // Read this as fluxUsed = returnFluxes[selspw][0].value().
4799 : os << "CHECK: foundSrc....."<<LogIO::POST;
4800 : returnFluxes[selspw][0].value(fluxUsed);
4801 :
4802 : // Log flux density found for this field and spectral window
4803 : os.output().width(12);
4804 : os << fieldName;
4805 : os.output().width(2);
4806 : os << " (fld ind " << fldid << ") spw ";
4807 : os << rawspwid << " ";
4808 : os.output().width(0);
4809 : os.output().precision(5);
4810 : os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
4811 : os << "Q=" << fluxUsed(1) << ", ";
4812 : os << "U=" << fluxUsed(2) << ", ";
4813 : os << "V=" << fluxUsed(3) << "] Jy, ";
4814 : os << ("(" + fluxScaleName + ")") << LogIO::POST;
4815 : writeHistory(os);
4816 : }
4817 :
4818 : // If a model image has been specified,
4819 : // rescale it according to the I f.d. determined above
4820 :
4821 : //Vector<Double> freqscaling;
4822 : //Vector<Double> freqsOfScale;
4823 :
4824 : //MEpoch mtime = msc.field().timeMeas()(fldid);
4825 :
4826 : } //spw for-loop end
4827 : ****/
4828 :
4829 0 : MEpoch mtime = msc.field().timeMeas()(fldid);
4830 :
4831 : // model image prep. changed to do all spws at once - TT, 2014.06.13
4832 0 : if(model != ""){
4833 :
4834 0 : tmodimage = sjy_prepImage(os, fluxStd, fluxUsed[0], freqsOfScale, freqscaling, model, msc.spectralWindow(),
4835 : // tmodimage = sjy_prepImage(os, fluxStd, fluxUsed, freqsOfScale, freqscaling, model, msc.spectralWindow(),
4836 : // rawspwid, chanDep, mfreqs, selspw, fieldName,
4837 : selToRawSpwIds, chanDep, mfreqs, fieldName,
4838 : fieldDir, freqUnit, fluxdens, precompute, spix,
4839 : reffreq, aveEpoch, fldid);
4840 :
4841 : }
4842 0 : else if (!precompute) {
4843 : // do it in sjy_makeComponentList()
4844 : // TODO: add polindex, polangle, rm handling
4845 : // for now ignore circular polarization
4846 : //Vector<Double> cppars(1,0.0);
4847 0 : Vector<Double> checkfluxes;
4848 0 : sjy_makeComponentList(os, tempCLs, returnFluxes, fluxUsed[0], selToRawSpwIds, mfreqs, fieldName, fieldDir,
4849 : spix, pipars, papars, rotMeas, reffreq, aveEpoch, fldid);
4850 0 : returnFluxes[0][0].value(checkfluxes);
4851 0 : }
4852 : /*** moved to sjy_makeComponentList()
4853 : // make componentlist using flux densities from the user specfied fluxdensity(per-spw)
4854 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4855 : Int rawspwid = selToRawSpwIds[selspw];
4856 : rawspwids[selspw]=rawspwid;
4857 : if(model == "" && !precompute){
4858 : // **** inside spw for-loop
4859 : // fluxUsed was supplied by the user instead of FluxStandard, so
4860 : // make a component list for it now, for use in ft.
4861 :
4862 : // Set the component flux density
4863 : Flux<Double> fluxval;
4864 : Flux<Double> fluxerr;
4865 : fluxval.setValue(fluxUsed[0]);
4866 : // Create a point component at the field center
4867 : // with the specified flux density
4868 : // - obviously this does not correct for solar objects...
4869 : PointShape point(fieldDir);
4870 : SpectralIndex siModel;
4871 : if(reffreq.getValue().getValue() > 0.0){
4872 : MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
4873 : MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
4874 : siModel.setRefFrequency(reffreq);
4875 : siModel.setIndex(spix);
4876 : returnFluxes[selspw][0].setValue(fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][0])));
4877 : }
4878 : else{
4879 : if(spix != 0.0){ // If not the default, complain and quit.
4880 : os << LogIO::SEVERE
4881 : << "spix cannot be nonzero with reffreq = 0!"
4882 : << LogIO::POST;
4883 : //return false;
4884 : }
4885 : siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
4886 : siModel.setIndex(0.0);
4887 : }
4888 :
4889 : // No worries about varying fluxes or sizes here, so any time will do.
4890 : // Moved this line up (TT 2013/05/09)
4891 : //MEpoch mtime = msc.field().timeMeas()(fldid);
4892 : tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
4893 : mfreqs[selspw][0],
4894 : mtime, fluxval, point,
4895 : siModel,
4896 : // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
4897 : ms_p->tableName() +
4898 : "_setjy_spw" +
4899 : String::toString(selspw) +
4900 : "_");
4901 : }
4902 : ***/
4903 :
4904 : // clear existing model for the selected field and for all selected spws
4905 : // outside spw loop
4906 : //if (!useModelCol_p && selspw==0) {
4907 0 : if (!useModelCol_p) {
4908 0 : String tmpspwstring=spwstring;
4909 0 : if (tmpspwstring=="") tmpspwstring="*";
4910 : os << LogIO::NORMAL
4911 : << "Will clear any existing model with matching field="
4912 : << fieldName
4913 : << " and spw=" << tmpspwstring
4914 0 : << LogIO::POST;
4915 :
4916 0 : String fldidstr = String::toString(fldid);
4917 : // use field id due to possible MSSelection bug for handing field name with blanks
4918 : //VisModelData::clearModel(*mssel_p, fieldName, spwstring)
4919 0 : VisModelData::clearModel(*mssel_p, fldidstr, spwstring);
4920 0 : }
4921 : // TODO: do it for all spw at once............
4922 : //sjy_make_visibilities(tmodimage, os, rawspwid, fldid, tempCLs[selspw],
4923 : // timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
4924 :
4925 : /***
4926 : if(tmodimage)
4927 : delete tmodimage;
4928 : tmodimage = NULL;
4929 : // if (Table::canDeleteTable("temp.setjy.image")) Table::deleteTable("temp.setjy.image");
4930 :
4931 : if(tempCLs[selspw] != ""){
4932 : String errmsg;
4933 :
4934 : //didAnything = true;
4935 : // commentted out for testing of concatCLs, may need to uncommentted later!!!!!!
4936 :
4937 : if(Table::canDeleteTable(errmsg, tempCLs[selspw]))
4938 : Table::deleteTable(tempCLs[selspw]);
4939 : else
4940 : os << LogIO::WARN
4941 : << "Could not rm " << tempCLs[selspw]
4942 : << " because the " << errmsg << "."
4943 : << LogIO::POST;
4944 : }
4945 : ***/
4946 :
4947 0 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4948 0 : Record subrec;
4949 : //store fluxd actually used to scale (not input fluxdensity)
4950 0 : Vector<Double> finalFluxUsed;
4951 : // Flux of first chan
4952 0 : returnFluxes[selspw][0].value(finalFluxUsed);
4953 0 : subrec.define("fluxd",finalFluxUsed);
4954 : // TODO: add fluxd error when the flux density uncertainties
4955 : // are corrrectly filled.
4956 : //
4957 : //retvalperField.defineRecord(String::toString(rawspwid),subrec);
4958 0 : retvalperField.defineRecord(String::toString(selToRawSpwIds[selspw]),subrec);
4959 0 : } // for selspw end **********************************************
4960 : //retval.defineRecord(fieldName,retvalperField);
4961 0 : retvalperField.define("fieldName",fieldName);
4962 0 : retval.defineRecord(String::toString(fldid),retvalperField);
4963 :
4964 : // cocatenate componentlists - not yet used....
4965 : //if (tempCLs[0]!="") {
4966 : // concatcl name should contains field name mjd etc...
4967 : // ostringstream oss;
4968 : // oss<< ms_p->tableName() << "_setjy_"
4969 : // << fieldName << "_" << mtime.get("d").getValue()
4970 : // << "d.cl";
4971 : // String concatcl(oss);
4972 : // sjy_concatComponentLists(os, tempCLs, concatcl);
4973 : //}
4974 :
4975 : //sjy_make_visibilities(tmodimage, os, rawspwids, fldid, concatcl,
4976 : // timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
4977 : //
4978 : //### Uncomment above once setjyFTMachine can handle multi-row componentlist #############
4979 :
4980 0 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4981 0 : sjy_make_visibilities(tmodimage, os, rawspwids[selspw], fldid, tempCLs[selspw],
4982 : timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
4983 : }
4984 : // #######################################################################################
4985 : // clean-up
4986 : //
4987 0 : if(tmodimage)
4988 0 : delete tmodimage;
4989 0 : tmodimage = NULL;
4990 :
4991 0 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4992 0 : if(tempCLs[selspw] != ""){
4993 0 : String errmsg;
4994 :
4995 : //didAnything = true;
4996 :
4997 0 : if(TableUtil::canDeleteTable(errmsg, tempCLs[selspw]))
4998 0 : TableUtil::deleteTable(tempCLs[selspw]);
4999 : else
5000 : os << LogIO::WARN
5001 0 : << "Could not rm " << tempCLs[selspw]
5002 : << " because the " << errmsg << "."
5003 0 : << LogIO::POST;
5004 :
5005 : //if(Table::canDeleteTable(errmsg, concatcl))
5006 : // Table::deleteTable(concatcl);
5007 0 : }
5008 : }
5009 :
5010 0 : } // End of loop over fields.
5011 : // add a format info for the returned flux densities (Record)
5012 : //retval.define("format","{field name: {spw Id: {fluxd: [I,Q,U,V] in Jy}}}");
5013 0 : retval.define("format","{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}");
5014 :
5015 0 : if(!precompute && spix[0] != 0.0 && reffreq.getValue().getValue() > 0.0){
5016 : os << LogIO::NORMAL
5017 : << "Flux density as a function of frequency (channel 0 of each spw):\n"
5018 : << " Frequency (GHz) Flux Density (Jy, Stokes I)"
5019 0 : << LogIO::POST;
5020 0 : for(uInt selspw = 0; selspw < nspws; ++selspw)
5021 0 : os << " " << mfreqs[selspw][0].get("GHz").getValue() << " "
5022 0 : << returnFluxes[selspw][0].value(Stokes::I).getValue()
5023 0 : << LogIO::POST;
5024 : }
5025 :
5026 0 : this->writeHistory(os);
5027 0 : this->unlock();
5028 : //return true;
5029 0 : }
5030 0 : catch (AipsError x){
5031 0 : this->unlock();
5032 0 : for(Int i = tempCLs.nelements(); i--;){
5033 0 : if(tempCLs[i] != "")
5034 0 : TableUtil::deleteTable(tempCLs[i]);
5035 : }
5036 0 : if (tmodimage) delete tmodimage; tmodimage=NULL;
5037 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
5038 : //return false;
5039 0 : }
5040 : //return didAnything;
5041 0 : return retval;
5042 0 : }
5043 :
5044 0 : String Imager::make_comp(const String& objName,
5045 : const String& standard,
5046 : const MEpoch& mtime, const Vector<MFrequency>& freqv,
5047 : const String& prefix)
5048 : {
5049 0 : Bool foundSrc = false;
5050 0 : logSink_p.clearLocally();
5051 0 : LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
5052 :
5053 0 : Vector<String> clistnames(1);
5054 : try{
5055 : FluxStandard::FluxScale fluxScaleEnum;
5056 0 : String fluxScaleName("user-specified");
5057 :
5058 0 : if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
5059 0 : throw(AipsError(standard + " is not a recognized flux density scale"));
5060 :
5061 0 : FluxStandard fluxStd(fluxScaleEnum);
5062 :
5063 0 : Vector<Vector<Flux<Double> > > returnFluxes(1), returnFluxErrs(1);
5064 0 : Vector<Vector<MFrequency> > mfreqs(1);
5065 0 : uInt nfreqs = freqv.nelements();
5066 :
5067 0 : mfreqs[0] = freqv;
5068 0 : returnFluxes[0].resize(nfreqs);
5069 0 : returnFluxErrs[0].resize(nfreqs);
5070 :
5071 0 : MDirection objDir;
5072 :
5073 0 : if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 ||
5074 0 : fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017)
5075 : {
5076 0 : fluxStd.setInterpMethod("nearest");
5077 : }
5078 0 : foundSrc = fluxStd.computeCL(objName, mfreqs, mtime, objDir,
5079 : returnFluxes, returnFluxErrs,
5080 : clistnames, prefix);
5081 0 : }
5082 0 : catch(AipsError x){
5083 0 : os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
5084 0 : RETHROW(x);
5085 0 : }
5086 0 : return foundSrc ? clistnames[0] : "";
5087 0 : }
5088 :
5089 0 : Unit Imager::sjy_setup_arrs(Vector<Vector<Flux<Double> > >& returnFluxes,
5090 : Vector<Vector<Flux<Double> > >& returnFluxErrs,
5091 : Vector<Vector<Double> >& fluxUsed,
5092 : Vector<String>& tempCLs,
5093 : Vector<Vector<MFrequency> >& mfreqs,
5094 : const MSSpWindowColumns& spwcols, const uInt nspws,
5095 : const Vector<Int>& selToRawSpwIds, const Bool chanDep)
5096 : {
5097 : // .getUnits() is a little confusing - it seems to return a Vector which is
5098 : // a list of all the units, not the unit for each row.
5099 :
5100 :
5101 0 : const Unit freqUnit(spwcols.chanFreqQuant().getUnits()[0]);
5102 :
5103 0 : IPosition ipos(1, 0);
5104 :
5105 0 : tempCLs.resize(nspws);
5106 0 : for(uInt selspw = 0; selspw < nspws; ++selspw){
5107 0 : Int rawspwid = selToRawSpwIds[selspw];
5108 :
5109 0 : if(chanDep){
5110 0 : mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid);
5111 0 : uInt nchan = mfreqs[selspw].nelements();
5112 0 : returnFluxes[selspw].resize(nchan);
5113 0 : returnFluxErrs[selspw].resize(nchan);
5114 : }
5115 : else{
5116 0 : mfreqs[selspw].resize(1);
5117 0 : returnFluxes[selspw].resize(1);
5118 0 : returnFluxErrs[selspw].resize(1);
5119 :
5120 : // Determine spectral window center frequency
5121 0 : Double medianFreq = median(spwcols.chanFreq()(rawspwid));
5122 0 : mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid)(ipos);
5123 0 : mfreqs[selspw].set(MVFrequency(Quantum<Double>(medianFreq, freqUnit)));
5124 : }
5125 : // initialize fluxUsed to 0
5126 0 : Vector<Double> iquvF(4,0.0);
5127 0 : fluxUsed[selspw]=iquvF;
5128 0 : }
5129 :
5130 0 : return freqUnit;
5131 0 : }
5132 : // new signature should be...
5133 : /***
5134 : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
5135 : const Vector<Int>& rawspwids, const Int fldid,
5136 : const String& clname, const String& timerange,
5137 : const String& scanstr, const String& intentstr, const String& obsidstr,
5138 : const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
5139 : ***/
5140 0 : Bool Imager::sjy_make_visibilities(TempImage<Float> *tmodimage, LogIO& os,
5141 : const Int rawspwid, const Int fldid,
5142 : const String& clname, const String& timerange,
5143 : const String& scanstr, const String& intentstr, const String& obsidstr,
5144 : const Vector<Double>& freqsOfScale, const Vector<Double>& freqscaling)
5145 : {
5146 0 : Bool made_visibilities = false;
5147 :
5148 : // Select the uv-data for this field and spw. id.;
5149 : // all frequency channels selected.
5150 0 : Vector<Int> selectSpw(1), selectField(1);
5151 : // for the new
5152 : //Vector<Int> selectSpw, selectField(1);
5153 : //selectSpw.resize(rawspwids.nelements());
5154 : //selectSpw = rawspwids;
5155 : //
5156 0 : selectSpw[0] = rawspwid;
5157 0 : selectField[0] = fldid;
5158 0 : String msSelectString = "";
5159 0 : Vector<Int> numDeChan(1);
5160 0 : numDeChan[0] = 0;
5161 0 : Vector<Int> begin(1);
5162 0 : begin[0] = 0;
5163 0 : Vector<Int> stepsize(1);
5164 0 : stepsize[0] = 1;
5165 : //TempImage<Float> tmodimage = tmodimages[0];
5166 0 : if(tmodimage || clname != "") {
5167 : //if(!tmodimages[0].null() || clname != "")
5168 0 : setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(),
5169 0 : MRadialVelocity(),
5170 : selectSpw, selectField, msSelectString, timerange, "",
5171 0 : Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
5172 : }
5173 0 : if(!nullSelect_p){
5174 : // Use ft to form visibilities
5175 0 : Vector<String> modelv;
5176 :
5177 0 : if(tmodimage){
5178 : //if(!tmodimages[0].null()){
5179 : //for (uInt imod=0; imod<tmodimages.nelements();imod++) {
5180 : //if(!tmodimages[imod].null()) {
5181 0 : if(sm_p)
5182 0 : destroySkyEquation();
5183 : // do if for each spw?
5184 0 : if(freqsOfScale.nelements() > 0){
5185 : //if(freqsOfScales[imod].nelements() > 0){
5186 0 : delete ft_p;
5187 0 : ft_p=NULL;
5188 0 : ftmachine_p="SetJyGridFT";
5189 0 : createFTMachine();
5190 0 : (static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScale, freqscaling);
5191 : //(static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScales[imod], freqscalings[imod]);
5192 : }
5193 0 : if(!ft_p)
5194 0 : createFTMachine();
5195 0 : sm_p = new CleanImageSkyModel();
5196 : // loop over for multiple spw model images
5197 0 : sm_p->add(*tmodimage, 1);
5198 : //sm_p->add(*(tmodimages[imod]), 1);
5199 : //} //if-tmodimages..
5200 : //} //for loop
5201 : // this has no effect (SetJyGridFT hardcoded to use linear now, Aug. 2016)
5202 : //ft_p->setFreqInterpolation("nearest");
5203 0 : setSkyEquation();
5204 0 : se_p->predict(false);
5205 0 : destroySkyEquation();
5206 :
5207 0 : made_visibilities = true;
5208 : }
5209 0 : else if(clname != ""){
5210 : //made_visibilities = ft(modelv, clname, false);
5211 0 : made_visibilities = ft(modelv, clname, false);
5212 0 : destroySkyEquation();
5213 : }
5214 : else
5215 : os << LogIO::NORMAL
5216 : << "Skipping an empty component list for spw " << rawspwid
5217 : // for new one
5218 : // << "Skipping an empty component list for spw " << rawspwids
5219 0 : << LogIO::POST;
5220 0 : }
5221 0 : return made_visibilities;
5222 0 : }
5223 :
5224 :
5225 0 : Bool Imager::sjy_concatComponentLists(LogIO& os, const Vector<String>& tempCLs, const String& outTempCL)
5226 : {
5227 0 : ComponentList concatCL;
5228 : try {
5229 0 : for (uInt icl=0; icl<tempCLs.nelements(); icl++) {
5230 0 : if (tempCLs[icl]!="") {
5231 : // expected format _setjy_spw#_...
5232 0 : String::size_type spos=tempCLs[icl].find(String("spw"));
5233 0 : String::size_type epos=tempCLs[icl].find_first_of("_",spos);
5234 0 : String clab = tempCLs[icl].substr(spos,epos-spos);
5235 0 : Path clname(tempCLs[icl]);
5236 0 : os <<LogIO::DEBUG1 << " tempCLs["<<icl<<"]="<<tempCLs[icl]<<LogIO::POST;
5237 0 : ComponentList tempcl(clname, true);
5238 0 : Vector<Int> which(1,0);
5239 0 : tempcl.setLabel(which,clab);
5240 0 : os << LogIO::DEBUG1 << "adding "<<tempCLs[icl]<<" to "<<outTempCL<<LogIO::POST;
5241 0 : concatCL.addList(tempcl);
5242 0 : }
5243 : }
5244 0 : concatCL.rename(outTempCL, Table::New);
5245 0 : return true;
5246 0 : } catch (AipsError x) {
5247 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
5248 0 : << LogIO::EXCEPTION;
5249 0 : return false;
5250 0 : }
5251 0 : }
5252 :
5253 0 : Bool Imager::sjy_computeFlux(LogIO& os, FluxStandard& fluxStd,
5254 : Vector<Vector<Flux<Double> > >& returnFluxes,
5255 : Vector<Vector<Flux<Double> > >& returnFluxErrs,
5256 : Vector<String>& tempCLs,
5257 : //Vector<Double>& fluxUsed,
5258 : Vector<Vector<Double> >& fluxUsed,
5259 : String& fluxScaleName, MEpoch& aveEpoch,
5260 : const Vector<Vector<MFrequency> >& mfreqs,
5261 : const String& model, const String& fieldName,
5262 : const MSColumns& msc, const Int fldid,
5263 : const MDirection& fieldDir, const Vector<Int>& selToRawSpwIds,
5264 : const String& standard)
5265 : {
5266 0 : Bool foundSrc = false;
5267 :
5268 0 : Double meantime = msc.time()(0);
5269 0 : meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
5270 0 : MEpoch mtime(msc.timeMeas()(0));
5271 0 : mtime.set(Quantity(meantime, "s"));
5272 0 : if(model != ""){
5273 : // Just get the fluxes and their uncertainties for scaling the image.
5274 : //foundSrc = fluxStd.compute(fieldName, mfreqs, returnFluxes,
5275 : // returnFluxErrs);
5276 0 : foundSrc = fluxStd.compute(fieldName, fieldDir, mfreqs, mtime, returnFluxes,
5277 : returnFluxErrs);
5278 : }
5279 : else{
5280 : // Go ahead and get FluxStandard to make the ComponentList, since
5281 : // it knows what type of component to use.
5282 :
5283 : // This is _a_ time. It would be more accurate and safer, but
5284 : // slower, to use the weighted average of the times at which this
5285 : // source was observed, and to use the range of times in the
5286 : // estimate of the error introduced by using a single time.
5287 : //
5288 : // Obviously that would be overkill if the source does not vary.
5289 : //
5290 : /***
5291 : Double meantime = msc.time()(0);
5292 : meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
5293 : MEpoch mtime(msc.timeMeas()(0));
5294 : mtime.set(Quantity(meantime, "s"));
5295 : ***/
5296 :
5297 0 : aveEpoch=mtime;
5298 :
5299 0 : foundSrc = fluxStd.computeCL(fieldName, mfreqs, mtime, fieldDir,
5300 : returnFluxes, returnFluxErrs,
5301 0 : tempCLs, ms_p->tableName()+"_setjy_");
5302 : }
5303 0 : if(!foundSrc){
5304 0 : if(standard == String("SOURCE")){
5305 : // *** THIS MODE IS NOT USED IN CURRENT SETJY ***
5306 : // dgoscha, NCSA, 02 May, 2002
5307 : // this else condtion is to handle the case where the user
5308 : // specifies standard='SOURCE' in the setjy argument. This will
5309 : // then look into the SOURCE_MODEL column of the SOURCE subtable
5310 : // for a table-record entry that points to a component list with the
5311 : // model information in it.
5312 :
5313 : // Look in the SOURCE_MODEL column of the SOURCE subtable for
5314 : // the name of the CL which contains the model.
5315 :
5316 : // First test to make sure the SOURCE_MODEL column exists.
5317 0 : if(ms_p->source().tableDesc().isColumn("SOURCE_MODEL")){
5318 0 : TableRecord modelRecord;
5319 0 : msc.source().sourceModel().get(0, modelRecord);
5320 :
5321 : // Get the name of the model component list from the table record
5322 : Table modelRecordTable =
5323 0 : modelRecord.asTable(modelRecord.fieldNumber(String ("model")));
5324 0 : String modelCLName = modelRecordTable.tableName();
5325 0 : modelRecord.closeTable(modelRecord.fieldNumber(String ("model")));
5326 :
5327 : // Now grab the flux from the model component list and use.
5328 0 : ComponentList modelCL = ComponentList(Path(modelCLName), true);
5329 0 : SkyComponent fluxComponent = modelCL.component(fldid);
5330 :
5331 : //fluxUsed = 0;
5332 0 : fluxUsed(0) = 0;
5333 : //fluxUsed = real(fluxComponent.flux().value());
5334 0 : fluxUsed(0) = real(fluxComponent.flux().value());
5335 0 : fluxScaleName = modelCLName;
5336 0 : }
5337 : else {
5338 : os << LogIO::SEVERE << "Missing SOURCE_MODEL column."
5339 : << LogIO::SEVERE << "Continuing with the default, I = 1.0 Jy"
5340 0 : << LogIO::POST;
5341 : //fluxUsed = 0;
5342 0 : fluxUsed(0) = 0;
5343 : //fluxUsed(0) = 1.0;
5344 0 : fluxUsed(0)(0) = 1.0;
5345 : }
5346 : }
5347 : else {
5348 : // Source not found; use Stokes I=1.0 Jy for now
5349 : // (The flux standard already issued a complaint like this...)
5350 : // os << LogIO::WARN
5351 : // << fieldName << " was not recognized by " << standard
5352 : // << ".\nContinuing with the default, I = 1.0 Jy"
5353 : // << LogIO::POST;
5354 : //fluxUsed = 0;
5355 0 : fluxUsed(0) = 0;
5356 : //fluxUsed(0) = 1.0;
5357 0 : fluxUsed(0)(0) = 1.0;
5358 0 : fluxScaleName = "default";
5359 : }
5360 :
5361 : // Currently, if !foundSrc, then the flux density is the same for all
5362 : // spws.
5363 : // Log the flux density found for this field.
5364 0 : os.output().width(12);
5365 0 : os << fieldName << " ";
5366 0 : os.output().width(0);
5367 0 : os.output().precision(4);
5368 : /***
5369 : os << LogIO::NORMAL << "[I=" << fluxUsed(0) << ", "; // Loglevel INFO
5370 : os << "Q=" << fluxUsed(1) << ", ";
5371 : os << "U=" << fluxUsed(2) << ", ";
5372 : os << "V=" << fluxUsed(3) << "] Jy, ";
5373 : ***/
5374 0 : os << LogIO::NORMAL << "[I=" << fluxUsed(0)(0) << ", "; // Loglevel INFO
5375 0 : os << "Q=" << fluxUsed(0)(1) << ", ";
5376 0 : os << "U=" << fluxUsed(0)(2) << ", ";
5377 0 : os << "V=" << fluxUsed(0)(3) << "] Jy @ ";
5378 0 : os << mfreqs(0)(0).getValue()<<"Hz, ";
5379 0 : os << ("(" + fluxScaleName + ")") << LogIO::POST;
5380 0 : writeHistory(os);
5381 : } // End of if(!foundSrc).
5382 : else {
5383 : // Logging/History for foundSrc=true (moved from the im.setjy method)
5384 0 : for (uInt selspw=0; selspw<selToRawSpwIds.nelements(); selspw++) {
5385 0 : returnFluxes[selspw][0].value(fluxUsed[selspw]);
5386 : // Log flux density found for this field and spectral window
5387 0 : os.output().width(12);
5388 0 : os << fieldName;
5389 0 : os.output().width(2);
5390 0 : os << " (fld ind " << fldid << ") spw ";
5391 0 : os << selToRawSpwIds[selspw] << " ";
5392 0 : os.output().width(0);
5393 0 : os.output().precision(5);
5394 0 : os << LogIO::NORMAL << "[I=" << fluxUsed(selspw)(0) << ", "; // Loglevel INFO
5395 0 : os << "Q=" << fluxUsed(selspw)(1) << ", ";
5396 0 : os << "U=" << fluxUsed(selspw)(2) << ", ";
5397 0 : os << "V=" << fluxUsed(selspw)(3) << "] Jy @ ";
5398 0 : os << mfreqs(selspw)(0).getValue()<<"Hz, ";
5399 0 : os << ("(" + fluxScaleName + ")") << LogIO::POST;
5400 0 : writeHistory(os);
5401 : }
5402 : }
5403 0 : return foundSrc;
5404 0 : }
5405 :
5406 : //make componentlist(s) with user specified flux density
5407 0 : void Imager::sjy_makeComponentList(LogIO& os, Vector<String>& tempCLs,
5408 : Vector<Vector<Flux<Double> > >& returnFluxes,
5409 : const Vector<Double>& fluxUsed,
5410 : const Vector<Int>& selToRawSpwIds,
5411 : const Vector<Vector<MFrequency> >& mfreqs,
5412 : const String& fieldName,
5413 : const MDirection& fieldDir,
5414 : const Vector<Double>& spix,
5415 : const Vector<Double>& pipars,
5416 : const Vector<Double>& papars,
5417 : const Double& rotMeas,
5418 : // circ pol parameters
5419 : //const Vector<Double>& cppars,
5420 : const MFrequency& reffreq,
5421 : const MEpoch& mtime,
5422 : const Int /*fldid*/)
5423 : {
5424 :
5425 0 : for(uInt selspw = 0; selspw < selToRawSpwIds.nelements(); ++selspw){
5426 : // fluxUsed was supplied by the user instead of FluxStandard, so
5427 : // make a component list for it now, for use in ft.
5428 :
5429 : // if spix is a float/double and q,u fluxes not set or pipars and papars not
5430 : // set => SpectralIndex
5431 : // if spix is a float/double and q,u fluxes is set but not pipars and papers
5432 : // => spectralindex
5433 : // if spix is a float/double and q,u fluxes and pipars and papars are set
5434 : // => tabular
5435 : // if spix is a vector but qu fluxes nor pipars and papers are not set
5436 : // => tabular
5437 : // if spix is a vector => tabular form
5438 : //
5439 : // Set the component flux density
5440 0 : Flux<Double> fluxval;
5441 0 : Flux<Double> fluxerr;
5442 0 : fluxval.setValue(fluxUsed);
5443 : // Create a point component at the field center
5444 : // with the specified flux density
5445 : // - obviously this does not correct for solar objects...
5446 0 : PointShape point(fieldDir);
5447 :
5448 0 : Bool useTabularFlux(false);
5449 : //check if to use tabular form or SpectralIndex model
5450 0 : if ( spix.nelements() > 1 ) {
5451 0 : useTabularFlux=true;
5452 : }
5453 : else {
5454 : //if (pipars.nelements() > 1 || papars.nelements() > 1 || rotMeas != 0.0) {
5455 0 : if (pipars.nelements() > 1 || papars.nelements() > 1 ) {
5456 0 : useTabularFlux=true;
5457 : }
5458 : }
5459 0 : SpectralIndex siModel;
5460 : //Vector<Double> iflux;
5461 : //Vector<Double> qflux;
5462 : //Vector<Double> uflux;
5463 0 : Vector<Flux<Double> > fluxvalvec;
5464 0 : Bool gotQUFlux(false);
5465 0 : Bool useFluxAsIs(false);
5466 : //
5467 0 : if(reffreq.getValue().getValue() > 0.0){
5468 : //original code uses first time of the data but shouldn't be using the same time as for
5469 : //FluxStandard::makeComponentList?
5470 : //MeasFrame mFrame(MEpoch(msc.timeMeas()(0)), mLocation_p, fieldDir);
5471 0 : MeasFrame mFrame(mtime, mLocation_p, fieldDir);
5472 0 : MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
5473 0 : siModel.setRefFrequency(reffreq);
5474 : // if spix is not array of double,do this otherwise need to set flux densities by tabular...
5475 : //
5476 0 : Int nchn = mfreqs[selspw].nelements();
5477 0 : fluxvalvec.resize(nchn);
5478 0 : Vector<Double> iflux(nchn);
5479 0 : Vector<Double> qflux(nchn);
5480 0 : Vector<Double> uflux(nchn);
5481 0 : Vector<Double> vflux(nchn,0.0);
5482 : // circular polarization fraction
5483 0 : Double circpolFraction=0.0;
5484 0 : if ( fluxUsed[0] !=0.0 && fluxUsed[3] != 0.0 ) {
5485 0 : circpolFraction = fluxUsed[3]/fluxUsed[0];
5486 : }
5487 :
5488 0 : if (spix.nelements()==1) {
5489 : //siModel.setIndex(spix[0]);
5490 0 : Vector<Double> stokesindex(4);
5491 0 : stokesindex[0]=spix[0];
5492 0 : stokesindex[1]=0.0;
5493 0 : stokesindex[2]=rotMeas!=0.0? rotMeas: 0.0;
5494 0 : stokesindex[3]=0.0;
5495 0 : siModel.setStokesIndex(stokesindex);
5496 : // still use iflux if q,u flux=0 but polindex and polangle is set
5497 0 : for (uInt ichn = 0; ichn < uInt(nchn); ichn++) {
5498 0 : iflux[ichn] = fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][ichn]));
5499 : }
5500 0 : }
5501 : else {
5502 : // tabular case
5503 0 : sjy_calciflux(mfreqs[selspw],reffreq,fluxUsed[0],spix,iflux);
5504 : }
5505 : // linear pol
5506 0 : Vector<Double> inpipars;
5507 0 : Vector<Double> inpapars;
5508 0 : if ( pipars.nelements() > 0 || papars.nelements() > 0 ) {
5509 0 : inpipars.resize(pipars.nelements());
5510 0 : inpipars=pipars;
5511 0 : inpapars.resize(papars.nelements());
5512 0 : inpapars=papars;
5513 : }
5514 :
5515 : // Either Q or U non-zero, so use them
5516 0 : if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0) {
5517 : // if Q U flux densities are given use that as 0th coefficient
5518 0 : Double pi0 = sqrt(fluxUsed[1] * fluxUsed[1] + fluxUsed[2] * fluxUsed[2]) / fluxUsed[0];
5519 0 : Double pa0 = 0.5 * atan2(fluxUsed[2],fluxUsed[1]);
5520 : os<<LogIO::DEBUG1<<"Polindex c0="<<pi0<<", polangle c0="<<pa0
5521 0 : <<" determined from input flux densities are used"<<LogIO::POST;
5522 0 : if ( pipars.nelements() == 0 || papars.nelements() == 0 ) {
5523 0 : inpipars.resize(1);
5524 0 : inpapars.resize(1);
5525 : }
5526 0 : inpipars[0] = pi0;
5527 0 : inpapars[0] = pa0;
5528 : }
5529 : //if (useTabularFlux) {
5530 0 : if (inpipars.nelements()!=0 && inpapars.nelements()!=0) {
5531 : // cerr<<"running sjy_calcquflux...."<<endl;
5532 : // - returns qflux and uflux
5533 0 : gotQUFlux = sjy_calcquflux(inpipars, inpapars, iflux, rotMeas, mfreqs[selspw], reffreq, qflux, uflux);
5534 : }
5535 0 : else if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0 || fluxUsed[3] != 0.0) {
5536 0 : gotQUFlux=true;
5537 0 : useFluxAsIs=true;
5538 : }
5539 : /***
5540 : if ( !useTabularFlux ) {
5541 : Vector<Double> stokesIndex(4);
5542 : stokesIndex[0] = index[0];
5543 : //need to translate polindex ...etc to stokesIndex[1,2]
5544 : siModel.setStokesIndex(spix);
5545 : }
5546 : ***/
5547 0 : for (uInt ichn=0; ichn < iflux.nelements(); ichn++) {
5548 0 : if (!gotQUFlux) {
5549 0 : qflux[ichn] = 0.0;
5550 0 : uflux[ichn] = 0.0;
5551 : }
5552 0 : else if(useFluxAsIs) {
5553 0 : qflux[ichn] = fluxUsed[1];
5554 0 : uflux[ichn] = fluxUsed[2];
5555 0 : vflux[ichn] = fluxUsed[3];
5556 : }
5557 0 : if ( circpolFraction != 0.0) vflux[ichn] = iflux[ichn]*circpolFraction;
5558 0 : Flux<Double> iquvflux(iflux[ichn],qflux[ichn],uflux[ichn],vflux[ichn]);
5559 0 : fluxvalvec[ichn] = iquvflux;
5560 0 : }
5561 0 : returnFluxes[selspw][0]=fluxvalvec[0];
5562 0 : }
5563 : else{
5564 0 : if(spix[0] != 0.0){ // If not the default, complain and quit.
5565 : os << LogIO::SEVERE
5566 : << "spix cannot be nonzero with reffreq = 0!"
5567 0 : << LogIO::POST;
5568 : //return false;
5569 : }
5570 0 : siModel.setRefFrequency(MFrequency(Quantity(1.0, "GHz")));
5571 0 : siModel.setIndex(0.0);
5572 : }
5573 : // TODO: call tabular form method for full pol specification....
5574 : //
5575 : // No worries about varying fluxes or sizes here, so any time will do.
5576 0 : if ( useTabularFlux ) {
5577 0 : tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
5578 : mfreqs[selspw],
5579 : mtime, fluxvalvec, point,
5580 0 : ms_p->tableName() +
5581 0 : "_setjy_spw" +
5582 0 : String::toString(selspw) +
5583 0 : "_");
5584 : }
5585 : else {
5586 : //if simodel is set use this
5587 : //cerr<<"NON-Tabular makeComponentList..."<<endl;
5588 : //if (fluxval.value(1) ==0.0 && fluxval.value(2) == 0.0 && gotQUFlux) {
5589 :
5590 : // fluxval is @ thefreq, make sure proper freq is used
5591 : // Note that refreq in siModel will be overriden by thefreq
5592 0 : MFrequency thefreq = reffreq;
5593 0 : if ( gotQUFlux) {
5594 0 : fluxval=fluxvalvec[0];
5595 0 : thefreq=mfreqs[selspw][0];
5596 : }
5597 0 : tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
5598 : // mfreqs[selspw][0],
5599 : thefreq,
5600 : mtime, fluxval, point,
5601 : siModel,
5602 : // jagonzal (CAS-4109): Specify table name to avoid clashing between different CASA engines when running vs a MMS
5603 0 : ms_p->tableName() +
5604 0 : "_setjy_spw" +
5605 0 : String::toString(selspw) +
5606 0 : "_");
5607 0 : }
5608 0 : }
5609 0 : }
5610 :
5611 : // modified the input model image by regridding, scaling with a flux standard
5612 0 : TempImage<Float>* Imager::sjy_prepImage(LogIO& os, FluxStandard& fluxStd,
5613 : Vector<Double>& fluxUsed, Vector<Double>& freqsOfScale,
5614 : Vector<Double>& freqscale, const String& model,
5615 : const MSSpWindowColumns& spwcols,
5616 : //const Int rawspwid, const Bool chanDep,
5617 : const Vector<Int> rawspwids, const Bool chanDep,
5618 : const Vector<Vector<MFrequency> >& mfreqs,
5619 : //const uInt selspw, const String& fieldName,
5620 : const String& fieldName,
5621 : const MDirection& fieldDir,
5622 : const Unit& freqUnit,
5623 : const Vector<Double>& fluxdens,
5624 : const Bool precompute,
5625 : //const Double spix,
5626 : const Vector<Double>& spix,
5627 : const MFrequency& reffreq,
5628 : const MEpoch& aveEpoch,
5629 : const Int fieldId)
5630 : {
5631 0 : TempImage<Float>* tmodimage = NULL;
5632 :
5633 : Double freqMax, freqMin;
5634 0 : Vector<Vector<Int> >dummy;
5635 0 : String msname=mssel_p->antenna().tableName();
5636 0 : msname.erase(msname.length()-8);
5637 : //adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, String::toString(rawspwid));
5638 : // Get freqmin and freqmax in LSRK for the entire span of the selected spws
5639 0 : String selSpwsStr;
5640 0 : for (uInt ispw=0; ispw < rawspwids.nelements(); ispw++) {
5641 0 : if (selSpwsStr!="") selSpwsStr += ", ";
5642 0 : selSpwsStr += String::toString(rawspwids(ispw));
5643 : }
5644 0 : adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, selSpwsStr);
5645 :
5646 : // Find min channel width to increment to construct freqsofScale
5647 0 : Double freqWidth = 0;
5648 : //
5649 0 : for (uInt ispw = 0; ispw<rawspwids.nelements(); ispw++) {
5650 0 : Vector<Double> freqWidths = spwcols.chanWidth()(rawspwids(ispw));
5651 :
5652 0 : Double minChanWidth = min(fabs(freqWidths));
5653 : // freqWidth init....
5654 0 : if (freqWidth == 0)
5655 0 : freqWidth = minChanWidth;
5656 : else
5657 0 : freqWidth = min(freqWidth,minChanWidth);
5658 0 : }
5659 :
5660 : // ADDED for debug
5661 : //Int rawspwid = rawspwids[0];
5662 : //Vector<Double> freqArray = spwcols.chanFreq()(rawspwid);
5663 : //Int nchan=freqArray.shape()[0] ;
5664 0 : Int nchan = Int(ceil(fabs(freqMax - freqMin)/freqWidth))+1;
5665 : //cerr<<"nchan="<<nchan<<" freqMax="<<freqMax<<" freqMin="<<freqMin<<" freqWidth="<<freqWidth<<endl;
5666 : //Filling it with the LSRK values
5667 : // SetJyGridFT will trigger nearestNeighbour interpolation for nchan>=2
5668 0 : Vector<Double> freqArray(nchan);
5669 0 : if (nchan==1) {
5670 0 : freqArray[0] = freqMin;
5671 : }
5672 0 : else if (nchan==2) {
5673 0 : freqArray[0] = freqMin;
5674 0 : freqArray[1] = freqMax;
5675 : }
5676 0 : else if (nchan==3) {
5677 0 : freqArray[0] = freqMin - freqWidth;
5678 0 : freqArray[1] = freqMin;
5679 0 : freqArray[2] = freqMin + freqWidth;
5680 : }
5681 : else {
5682 0 : for (Int k =0;k < nchan; ++k){
5683 0 : freqArray[k]=freqMin+k*freqWidth;
5684 : }
5685 : }
5686 : //Vector<Double> freqInc = spwcols.chanWidth()(rawspwid);
5687 0 : Double medianFreq = median(freqArray);
5688 0 : freqsOfScale.resize();
5689 0 : freqscale.resize();
5690 :
5691 : // 2 bw channel extra
5692 : // UNCOMMENTED for debug
5693 : //freqWidth = fabs(freqMax - freqMin) + 2 * max(freqInc);
5694 0 : Matrix<Double> fluxUsedPerChan; // 4 rows nchan col ...will resize when needed
5695 :
5696 : // Set fluxUsedPerChan to the flux densities for each chan.
5697 0 : if(chanDep || (spix[0] != 0.0 && fluxdens[0] != 0.0)){
5698 0 : IPosition whichChan(1, 0);
5699 0 : Flux<Double> returnFlux;
5700 0 : Flux<Double> returnFluxErr;
5701 0 : Double reffreqInGHz = 1.0;
5702 :
5703 0 : Unit ghz("GHz");
5704 0 : if(!precompute)
5705 0 : reffreqInGHz = reffreq.get(ghz).getValue();
5706 :
5707 0 : fluxUsedPerChan.resize(4, freqArray.nelements());
5708 0 : for(uInt k = 0; k < freqArray.nelements(); ++k){
5709 0 : whichChan[0] = k;
5710 0 : if(precompute){
5711 : //fluxStd.compute(fieldName, spwcols.chanFreqMeas()(rawspwid)(whichChan),
5712 : // returnFlux, returnFluxErr);
5713 0 : fluxStd.compute(fieldName, fieldDir, MFrequency(Quantity(freqArray[k], "Hz"), MFrequency::LSRK),
5714 : aveEpoch, returnFlux, returnFluxErr);
5715 0 : returnFlux.value(fluxUsed);
5716 : }
5717 : else{
5718 : // spix: index = c0 + c1*log(f/fo) + c2*log(f/fo)^2+ ...
5719 : // = log(So) + alpha*log(f/fo) + curv1*log(f/f0)^2 ....
5720 0 : uInt order = spix.nelements();
5721 0 : Polynomial<Double> spixfunc(order);
5722 0 : Vector<Double> coeffs(order+1);
5723 0 : coeffs[0] = log10(fluxdens[0]);
5724 0 : for (uInt ispix = 1; ispix < order+1; ispix++) {
5725 0 : coeffs[ispix] = spix[ispix-1];
5726 : }
5727 0 : spixfunc.setCoefficients(coeffs);
5728 :
5729 : //Double freq = spwcols.chanFreqMeas()(rawspwids(0))(whichChan).get(ghz).getValue();
5730 : //Double specfac = pow(freq / reffreqInGHz, spix);
5731 : // TT mod-06/11/14
5732 : // freqArray may or may not be exactly match with data chan frequencies
5733 : // so probably make sense to use freqArray instead
5734 : //Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spix);
5735 0 : Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spixfunc(freqArray[k]));
5736 :
5737 0 : for(uInt stokes = 0; stokes < 4; ++stokes)
5738 0 : fluxUsed[stokes] = fluxdens[stokes] * specfac;
5739 0 : }
5740 0 : fluxUsedPerChan.column(k) = fluxUsed;
5741 : }
5742 0 : }
5743 0 : PagedImage<Float> modimage(model);
5744 0 : modimage.table().unmarkForDelete();
5745 0 : IPosition imshape = modimage.shape();
5746 0 : CoordinateSystem csys(modimage.coordinates());
5747 0 : Int freqAxis = CoordinateUtil::findSpectralAxis(csys);
5748 0 : Vector<Stokes::StokesTypes> whichPols;
5749 0 : Int polAxis = CoordinateUtil::findStokesAxis(whichPols, csys);
5750 0 : Int icoord = csys.findCoordinate(Coordinate::SPECTRAL);
5751 0 : SpectralCoordinate spcsys = csys.spectralCoordinate(icoord);
5752 0 : MEpoch elEpoch; MDirection elDir; MFrequency::Types elTypes; MPosition elPos;
5753 0 : spcsys.getReferenceConversion(elTypes, elEpoch, elPos, elDir);
5754 0 : spcsys.setReferenceConversion(MFrequency::LSRK, aveEpoch, elPos, elDir);
5755 0 : spcsys.setReferenceValue(Vector<Double>(1, medianFreq));
5756 0 : spcsys.setReferencePixel(Vector<Double>(1, 0.0));
5757 0 : spcsys.setWorldAxisUnits(Vector<String>(1,
5758 : //mfreqs[selspw][0].getUnit().getName()));
5759 0 : mfreqs[0][0].getUnit().getName()));
5760 : //make image freq. width wide enough for FTMachine to work correctly
5761 0 : spcsys.setIncrement(Vector<Double>(1, 2*fabs(freqMax-freqMin)));
5762 : // make a cube model if the model is a cube already
5763 0 : if(modimage.shape()(freqAxis) >1){
5764 : // model image is a cube...just regrid it then
5765 : os << LogIO::NORMAL
5766 : << "The model image is a cube, so it is being regridded but without scaling the flux density."
5767 0 : << LogIO::POST;
5768 0 : spcsys = SpectralCoordinate(
5769 : //MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
5770 0 : MFrequency::castType(mfreqs[0][0].getRef().getType()),
5771 0 : freqArray, spcsys.restFrequency());
5772 0 : imshape(freqAxis)=freqArray.nelements();
5773 0 : csys.replaceCoordinate(spcsys, icoord);
5774 0 : tmodimage = new TempImage<Float>(imshape, csys);
5775 0 : sjy_regridCubeChans(tmodimage, modimage, freqAxis);
5776 : //return from here itself
5777 0 : return tmodimage;
5778 : }
5779 :
5780 0 : if(chanDep && (fluxUsedPerChan.ncolumn() > 1)){
5781 : //spcsys = SpectralCoordinate(
5782 : // MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
5783 : // freqArray, spcsys.restFrequency());
5784 0 : if(freqAxis < 2 || polAxis < 2)
5785 0 : throw(AipsError("Cannot setjy with a model that has spectral or stokes axis before direction axes.\n Please reorder the axes of the image"));
5786 0 : freqscale.resize(freqArray.nelements());
5787 0 : freqsOfScale.resize(freqArray.nelements());
5788 0 : freqsOfScale=freqArray;
5789 0 : freqscale=1.0;
5790 0 : if(freqAxis == 2) {//pol and freq are swapped
5791 0 : imshape[2]=imshape[3];
5792 0 : imshape[3] = 1;
5793 0 : Vector<Int> trans(4);
5794 0 : trans[0] = 0; trans[1] = 1; trans[2] = 3; trans[3] = 2;
5795 0 : csys.transpose(trans, trans);
5796 0 : }
5797 : else{
5798 0 : imshape(freqAxis) = 1;
5799 : }
5800 : }
5801 0 : csys.replaceCoordinate(spcsys, icoord);
5802 0 : tmodimage = new TempImage<Float>(imshape, csys);
5803 0 : IPosition blcin(modimage.shape().nelements(), 0);
5804 0 : IPosition trcin=modimage.shape()-1;
5805 0 : IPosition blcout(imshape.nelements(), 0);
5806 0 : IPosition trcout=imshape-1;
5807 :
5808 0 : for (uInt ipol=0; ipol < imshape[2]; ++ipol){
5809 0 : blcin[polAxis]=ipol;
5810 0 : trcin[polAxis]=ipol;
5811 0 : blcout[2]=ipol;
5812 0 : trcout[2]=ipol;
5813 0 : Slicer slin(blcin, trcin, Slicer::endIsLast);
5814 0 : Slicer slout(blcout, trcout, Slicer::endIsLast);
5815 0 : SubImage<Float> subimout(*tmodimage, slout, true);
5816 0 : SubImage<Float> subimin(modimage, slin, false);
5817 0 : subimout.copyData(subimin);
5818 0 : }
5819 : os << LogIO::DEBUG1
5820 : << "freqUnit.getName() = " << freqUnit.getName()
5821 0 : << LogIO::POST;
5822 : os << LogIO::DEBUG1
5823 : //<< "mfreqs[selspw].get(freqUnit).getValue() = "
5824 : //<< mfreqs[selspw][0].get(freqUnit).getValue()
5825 : << "mfreqs[0][0].get(freqUnit).getValue() = "
5826 0 : << mfreqs[0][0].get(freqUnit).getValue()
5827 0 : << LogIO::POST;
5828 :
5829 : // Check direction consistency (reported in log message below)
5830 0 : String err;
5831 0 : if(!CoordinateUtil::setDirectionConversion(err, csys, fieldDir.getRefString())){
5832 : os << "LogIO::WARN "
5833 : << "Could not set direction conversion between flux image and "
5834 0 : << fieldDir.getRefString() << LogIO::POST;
5835 : }
5836 0 : Int dircoord(csys.findCoordinate(Coordinate::DIRECTION));
5837 0 : DirectionCoordinate dircsys=csys.directionCoordinate(dircoord);
5838 0 : MVDirection mvd;
5839 0 : dircsys.toWorld(mvd,dircsys.referencePixel());
5840 0 : Double sep = fieldDir.getValue().separation(mvd,"\"").getValue();
5841 :
5842 : //Apply radius limit for 3C286,3C48,3C147 and 3C138
5843 0 : sjy_setRadiusLimit(tmodimage, modimage, model, dircsys);
5844 :
5845 : // for debugging
5846 : //PagedImage<Float> checkIm(TiledShape(modimage.shape(),
5847 : // modimage.niceCursorShape()),
5848 : // modimage.coordinates(),
5849 : // "checkImage");
5850 : //checkIm.copyData((LatticeExpr<Float>)(*tmodimage));
5851 :
5852 0 : if(fluxdens[0] != 0.0){
5853 0 : Float sumI = 1.0;
5854 :
5855 : // ?: can't handle the different return types.
5856 0 : if(whichPols.nelements() > 1)
5857 : //sumI = sum(ImagePolarimetry(modimage).stokesI()).getFloat();
5858 0 : sumI = sum(ImagePolarimetry(*tmodimage).stokesI()).getFloat();
5859 : else
5860 : //sumI = sum(modimage).getFloat();
5861 0 : sumI = sum(*tmodimage).getFloat();
5862 :
5863 : //if(selspw == 0)
5864 : os << LogIO::NORMAL
5865 0 : << "Using model image " << modimage.name() // Loglevel INFO
5866 0 : << LogIO::POST;
5867 :
5868 : // scale the image
5869 0 : if(freqscale.nelements() > 0){
5870 0 : Int midchan = freqArray.nelements()/2;
5871 0 : if(modimage.shape()(freqAxis) == 1){
5872 : // IPosition blc(imshape.nelements(), 0);
5873 : //IPosition trc = imshape - 1;
5874 : os << LogIO::NORMAL
5875 : //<< "Scaling spw " << selspw << "'s model image by channel to I = "
5876 0 : << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image by channel to I = "
5877 0 : << fluxUsedPerChan.row(0)(0)<<", "
5878 0 : << fluxUsedPerChan.row(0)(midchan)<<", "
5879 0 : << fluxUsedPerChan.row(0)(nchan-1)
5880 : << " Jy @("
5881 0 : << freqArray(0)<<", "
5882 0 : << freqArray(midchan)<<", "
5883 0 : << freqArray(nchan-1)
5884 : <<")Hz (LSRK) for visibility prediction (a few representative values are shown)."
5885 0 : << LogIO::POST;
5886 0 : writeHistory(os);
5887 0 : for(uInt k = 0; k < fluxUsedPerChan.ncolumn(); ++k){
5888 0 : freqscale[k] = fluxUsedPerChan.column(k)(0)/sumI;
5889 : //blc[3] = k;
5890 : //trc[3] = k;
5891 : //Slicer sl(blc, trc, Slicer::endIsLast);
5892 : //SubImage<Float> subim(*tmodimage, sl, true);
5893 : //subim.copyData((LatticeExpr<Float>)(modimage*scale));
5894 : }
5895 : // for debug
5896 : //cerr<<"freqscale="<<freqscale<<endl;
5897 : //cerr<<"freqsOfScale="<<freqsOfScale<<endl;
5898 : }
5899 : }
5900 : else{
5901 : // Scale factor
5902 0 : Float scale = fluxUsed[0] / sumI;
5903 : //for addition of sjy_setRadiusLimit
5904 : //tmodimage->copyData( (LatticeExpr<Float>)(modimage * scale) );
5905 0 : tmodimage->copyData( (LatticeExpr<Float>)(*tmodimage * scale) );
5906 : os << LogIO::NORMAL
5907 : // << "Scaling spw " << selspw << "'s model image to I = "
5908 0 : << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image to I = "
5909 0 : << fluxUsed[0] // Loglevel INFO
5910 : << " Jy @ "
5911 : //<< mfreqs[0][0].getValue()
5912 0 : << freqArray(0)
5913 : << "Hz (LSRK) for visibility prediction."
5914 0 : << LogIO::POST;
5915 0 : writeHistory(os);
5916 : }
5917 : }
5918 : else{
5919 : os << LogIO::NORMAL // Loglevel INFO
5920 : << "Using the model image's original unscaled flux density for visibility prediction."
5921 0 : << LogIO::POST;
5922 0 : writeHistory(os);
5923 : // included in sjy_setRadiusLimit
5924 : //tmodimage->copyData( (LatticeExpr<Float>)(modimage) );
5925 : }
5926 :
5927 : //if(selspw == 0){
5928 : os << LogIO::NORMAL // Loglevel INFO
5929 : << "The model image's reference pixel is " << sep
5930 : << " arcsec from " << fieldName << "'s phase center."
5931 0 : << LogIO::POST;
5932 0 : writeHistory(os);
5933 : //}
5934 :
5935 0 : return tmodimage;
5936 0 : }
5937 :
5938 0 : Bool Imager::sjy_regridCubeChans(TempImage<Float>* tmodimage,
5939 : PagedImage<Float>& modimage, Int freqAxis)
5940 : {
5941 0 : if(freqAxis != 3)
5942 0 : throw(AipsError("Cannot setjy with a cube model that does not have the spectral axis as the last one.\n Please reorder the axes of the image"));
5943 0 : ImageRegrid<Float> ir;
5944 0 : IPosition axes(1, freqAxis); // regrid the spectral only
5945 0 : ir.regrid(*tmodimage, Interpolate2D::LINEAR, axes, modimage);
5946 0 : return true;
5947 0 : }
5948 :
5949 0 : Bool Imager::sjy_setRadiusLimit(TempImage<Float>* tmodimage,
5950 : PagedImage<Float>& modimage, const String& model, DirectionCoordinate& dircsys)
5951 : {
5952 0 : Path path(model);
5953 0 : String basename=path.baseName();
5954 : Float arad;
5955 : // radius limit in arcsec from AIPS
5956 0 : if (basename.find("3C286")==0) {
5957 0 : arad=3.0;
5958 : }
5959 0 : else if (basename.find("3C48")==0) {
5960 0 : arad=0.95;
5961 : }
5962 0 : else if (basename.find("3C147")==0) {
5963 0 : arad=0.85;
5964 : }
5965 0 : else if (basename.find("3C138")==0) {
5966 0 : arad=0.75;
5967 : }
5968 : else {
5969 0 : arad=0;
5970 0 : tmodimage->copyData(modimage);
5971 0 : return true;
5972 : }
5973 : try {
5974 0 : Quantity qrad(arad,"arcsec");
5975 0 : Float prad=Float(qrad.get(Unit("rad")).getValue()/abs(dircsys.increment()(0)));
5976 0 : Float radius = (prad >0.5 ? prad: 0.5);
5977 : //Add current ms name to avoid file access clash for MMS processing
5978 0 : String tempmaskname=ms_p->tableName()+"__tmp_mask_setjy_radiuslimit";
5979 0 : PagedImage<Float> maskImage(TiledShape(modimage.shape(),
5980 0 : modimage.niceCursorShape()),
5981 0 : modimage.coordinates(), tempmaskname);
5982 0 : maskImage.table().markForDelete();
5983 0 : Matrix<Float> circ(1,3);
5984 0 : Record *imrec=0;
5985 0 : Matrix<Quantity> blctrcs;
5986 0 : circ(0,0)=radius;
5987 0 : circ(0,1)=dircsys.referencePixel()(0);
5988 0 : circ(0,2)=dircsys.referencePixel()(1);
5989 0 : Imager::regionToImageMask(tempmaskname,imrec,blctrcs,circ,1.0);
5990 0 : PagedImage<Float> tmpmask(tempmaskname);
5991 0 : tmpmask.table().markForDelete();
5992 0 : tmodimage->copyData( (LatticeExpr<Float>)(tmpmask*modimage));
5993 0 : }
5994 0 : catch (...) {
5995 0 : return false;
5996 0 : }
5997 0 : return true;
5998 0 : }
5999 :
6000 0 : Bool Imager::sjy_calciflux(const Vector<MFrequency>& freqs, const MFrequency& reffreq,
6001 : const Double refflux, const Vector<Double>& vspix, Vector<Double>& iflux)
6002 : {
6003 : try {
6004 : // assume polynomical is log(S) = c0 + alpha*log(f/fo) + curv1*log(f/fo)^2+
6005 : // vspix should contains [alpha, curv1, etc..] and c0 is calculated from refflux
6006 0 : uInt porder = vspix.nelements();
6007 0 : Polynomial<Double> lf(porder);
6008 0 : Vector<Double> coeffs(porder+1);
6009 0 : coeffs[0] = log10(refflux);
6010 0 : for (uInt i = 1; i < vspix.nelements()+1; i++ ) {
6011 0 : coeffs[i] = vspix[i-1];
6012 : }
6013 0 : lf.setCoefficients(coeffs);
6014 0 : Int nf = freqs.nelements();
6015 0 : iflux.resize(nf);
6016 0 : Unit frequnit("GHz");
6017 0 : Double reffreqval = reffreq.get(frequnit).getValue();
6018 0 : for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
6019 0 : iflux[cfidx] = pow(10.0,lf(log10(freqs[cfidx].get(frequnit).getValue()/reffreqval)));
6020 : }
6021 0 : }
6022 0 : catch (...) {
6023 0 : return false;
6024 0 : }
6025 0 : return true;
6026 : }
6027 :
6028 0 : Bool Imager::sjy_calcquflux(const Vector<Double>& pipars, const Vector<Double>& papars,
6029 : const Vector<Double>& iflux, const Double rotMeas,
6030 : const Vector<MFrequency>& freqs,
6031 : const MFrequency& reffreq, Vector<Double>& qflux,
6032 : Vector<Double>& uflux)
6033 : {
6034 :
6035 : try {
6036 0 : Int nf = freqs.nelements();
6037 : //polindex
6038 : // of the form, pi_o + c1*(f-fo)/fo + c2*(f-fo)/fo
6039 0 : Polynomial<Double> pipoly(pipars.nelements());
6040 0 : pipoly.setCoefficients(pipars);
6041 : //pangle
6042 0 : Polynomial<Double> papoly(papars.nelements());
6043 0 : papoly.setCoefficients(papars);
6044 0 : qflux.resize(nf);
6045 0 : uflux.resize(nf);
6046 0 : Unit ghz("Hz");
6047 0 : Double f0 = reffreq.get(ghz).getValue();
6048 :
6049 0 : for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
6050 0 : Double f = freqs[cfidx].get(ghz).getValue();
6051 0 : Double ipi = pipoly((f-f0)/f0);
6052 0 : Double ipa = papoly((f-f0)/f0);
6053 0 : Double iiflux = iflux[cfidx];
6054 0 : Double qfluxval = ipi * iiflux * cos(2.0*ipa);
6055 0 : Double ufluxval = ipi * iiflux * sin(2.0*ipa);
6056 : //debug
6057 : //if (cfidx<10) cerr<<"sjy_calcquflux:: poli="<<ipi<<" pola="<<ipa<<" qflux="<<qfluxval<<" uflux="<<ufluxval<<endl;
6058 0 : if (rotMeas!=0.0 ) {
6059 0 : Double rotangle = 2*rotMeas * C::c * C::c * (f0*f0-f*f)/(f*f*f0*f0);
6060 : //if (cfidx<10) cerr<<"rotangle="<<rotangle<<endl;
6061 0 : qflux[cfidx] = qfluxval*cos(rotangle) - ufluxval*sin(rotangle);
6062 0 : uflux[cfidx] = qfluxval*sin(rotangle) + ufluxval*cos(rotangle);
6063 : }
6064 : else {
6065 0 : qflux[cfidx] = qfluxval;
6066 0 : uflux[cfidx] = ufluxval;
6067 : }
6068 : //if (cfidx<10) cerr<<"uflux/qflux["<<cfidx<<"]="<<uflux[cfidx]/qflux[cfidx]<<endl;
6069 : }
6070 0 : }
6071 0 : catch (...) {
6072 0 : return false;
6073 0 : }
6074 0 : return true;
6075 : }
6076 :
6077 :
6078 0 : Bool Imager::clone(const String& imageName, const String& newImageName)
6079 : {
6080 : //if(!valid()) return false;
6081 : // This is not needed if(!assertDefinedImageParameters()) return false;
6082 0 : LogIO os(LogOrigin("imager", "clone()", WHERE));
6083 : try {
6084 0 : PagedImage<Float> oldImage(imageName);
6085 0 : PagedImage<Float> newImage(TiledShape(oldImage.shape(),
6086 0 : oldImage.niceCursorShape()), oldImage.coordinates(),
6087 0 : newImageName);
6088 0 : newImage.set(0.0);
6089 0 : newImage.table().flush(true, true);
6090 0 : } catch (AipsError x) {
6091 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6092 0 : return false;
6093 0 : }
6094 0 : return true;
6095 0 : }
6096 :
6097 : // Make an empty image
6098 14 : Bool Imager::make(const String& model)
6099 : {
6100 :
6101 14 : if(!valid())
6102 : {
6103 0 : return false;
6104 : }
6105 28 : LogIO os(LogOrigin("imager", "make()", WHERE));
6106 :
6107 14 : this->lock();
6108 : try {
6109 14 : if(!assertDefinedImageParameters())
6110 : {
6111 0 : return false;
6112 : }
6113 :
6114 : // Make an image with the required shape and coordinates
6115 14 : String modelName(model);
6116 14 : if(modelName=="") modelName=imageName()+".model";
6117 : os << LogIO::DEBUG1
6118 14 : << "Making empty image: " << modelName << LogIO::POST;
6119 :
6120 14 : removeTable(modelName);
6121 14 : CoordinateSystem coords;
6122 : //if(!imagecoordinates(coords, false))
6123 14 : if(!imagecoordinates2(coords, false))
6124 : {
6125 0 : this->unlock();
6126 0 : return false;
6127 : }
6128 14 : this->makeEmptyImage(coords, modelName, fieldid_p);
6129 14 : this->unlock();
6130 :
6131 14 : return true;
6132 14 : } catch (AipsError x) {
6133 0 : this->unlock();
6134 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6135 :
6136 0 : return false;
6137 :
6138 0 : }
6139 : this->unlock();
6140 :
6141 : return true;
6142 14 : }
6143 :
6144 : // Fit the psf. If psf is blank then make the psf first.
6145 14 : Bool Imager::fitpsf(const String& psf, ImageBeamSet& mbeam) {
6146 :
6147 14 : if(!valid())
6148 : {
6149 0 : return false;
6150 : }
6151 28 : LogIO os(LogOrigin("imager", "fitpsf()", WHERE));
6152 :
6153 14 : this->lock();
6154 : try {
6155 14 : if(!assertDefinedImageParameters())
6156 : {
6157 0 : this->unlock();
6158 0 : return false;
6159 : }
6160 :
6161 14 : os << LogIO::NORMAL << "Fitting to psf" << LogIO::POST; // Loglevel PROGRESS
6162 :
6163 14 : String lpsf; lpsf=psf;
6164 14 : if(lpsf=="") {
6165 0 : lpsf=imageName()+".psf";
6166 0 : makeimage("psf", lpsf);
6167 : }
6168 :
6169 14 : if(!Table::isReadable(lpsf)) {
6170 0 : this->unlock();
6171 : os << LogIO::SEVERE << "PSF image " << lpsf << " does not exist"
6172 0 : << LogIO::POST;
6173 :
6174 0 : return false;
6175 : }
6176 :
6177 14 : PagedImage<Float> psfImage(lpsf);
6178 14 : StokesImageUtil::FitGaussianPSF(psfImage, mbeam);
6179 14 : beam_p = mbeam;
6180 14 : beamValid_p=true;
6181 :
6182 14 : GaussianBeam elbeam=beam_p(0,0);
6183 : os << LogIO::NORMAL // Loglevel INFO
6184 : << " Beam fit: " << elbeam.getMajor("arcsec") << " by "
6185 : << elbeam.getMinor("arcsec") << " (arcsec) at pa "
6186 14 : << elbeam.getPA(Unit("deg")) << " (deg) " << endl;
6187 :
6188 14 : this->unlock();
6189 :
6190 14 : return true;
6191 14 : } catch (AipsError x) {
6192 0 : this->unlock();
6193 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6194 :
6195 0 : return false;
6196 0 : }
6197 : this->unlock();
6198 :
6199 : return true;
6200 14 : }
6201 :
6202 :
6203 0 : Bool Imager::setscales(const String& scaleMethod,
6204 : const Int inscales,
6205 : const Vector<Float>& userScaleSizes)
6206 : {
6207 0 : scaleMethod_p = scaleMethod;
6208 0 : userScaleSizes_p.resize(userScaleSizes.nelements());
6209 0 : userScaleSizes_p = userScaleSizes;
6210 0 : if (scaleMethod_p == "uservector") {
6211 0 : nscales_p = userScaleSizes.nelements();
6212 : } else {
6213 0 : nscales_p = inscales;
6214 : }
6215 : //Force the creation of a new sm_p with the new scales
6216 0 : destroySkyEquation();
6217 0 : scaleInfoValid_p = true;
6218 0 : return true;
6219 : };
6220 :
6221 0 : Bool Imager::setSmallScaleBias(const Float inbias)
6222 : {
6223 0 : smallScaleBias_p = inbias;
6224 0 : return true;
6225 : }
6226 :
6227 : // Added for wb algo.
6228 0 : Bool Imager::settaylorterms(const Int intaylor,const Double inreffreq)
6229 : {
6230 0 : ntaylor_p = intaylor;
6231 0 : reffreq_p = inreffreq;
6232 0 : return true;
6233 : };
6234 :
6235 : // Set the beam
6236 0 : Bool Imager::setbeam(const ImageBeamSet& mbeam)
6237 : {
6238 0 : if(!valid()) return false;
6239 :
6240 0 : LogIO os(LogOrigin("imager", "setbeam()", WHERE));
6241 0 : beam_p = ImageBeamSet(mbeam);
6242 0 : beamValid_p=true;
6243 :
6244 0 : return true;
6245 0 : }
6246 :
6247 : // Plot the uv plane
6248 0 : Bool Imager::plotuv(const Bool rotate)
6249 : {
6250 :
6251 0 : if(!valid()) return false;
6252 :
6253 0 : LogIO os(LogOrigin("imager", "plotuv()", WHERE));
6254 :
6255 0 : this->lock();
6256 : try {
6257 : os << LogIO::NORMAL // Loglevel PROGRESS
6258 0 : << "Plotting uv coverage for currently selected data" << LogIO::POST;
6259 :
6260 0 : ROVisIter& vi(*rvi_p);
6261 0 : VisBuffer vb(vi);
6262 :
6263 0 : uInt nVis = count_visibilities(rvi_p, true, true);
6264 :
6265 0 : if(nVis==0) {
6266 0 : this->unlock();
6267 0 : os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
6268 0 : return false;
6269 : }
6270 :
6271 0 : if(rotate) {
6272 : os << LogIO::NORMAL // Loglevel INFO
6273 0 : << "UVW will be rotated to specified phase center" << LogIO::POST;
6274 : }
6275 :
6276 :
6277 0 : Vector<Float> u(nVis); u=0.0;
6278 0 : Vector<Float> v(nVis); v=0.0;
6279 0 : Vector<Float> uRotated(nVis); uRotated=0.0;
6280 0 : Vector<Float> vRotated(nVis); vRotated=0.0;
6281 0 : Float maxAbsUV=0.0;
6282 :
6283 0 : Int iVis=0;
6284 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6285 0 : for (vi.origin();vi.more();vi++) {
6286 0 : Int nRow=vb.nRow();
6287 0 : Int nChan=vb.nChannel();
6288 0 : Vector<Double> uvwRotated(3);
6289 0 : MeasFrame mFrame((MEpoch(Quantity(vb.time()(0), "s"))), mLocation_p);
6290 0 : UVWMachine uvwMachine(phaseCenter_p, vb.phaseCenter(), mFrame);
6291 0 : for (Int row=0; row<nRow; ++row) {
6292 0 : if(rotate) {
6293 0 : for (Int dim=0;dim<3;++dim) {
6294 0 : uvwRotated(dim)=vb.uvw()(row)(dim);
6295 : }
6296 0 : uvwMachine.convertUVW(uvwRotated);
6297 : }
6298 :
6299 0 : for (Int chn=0; chn<nChan; ++chn) {
6300 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6301 0 : Float f=vb.frequency()(chn)/C::c;
6302 0 : u(iVis)=vb.uvw()(row)(0)*f;
6303 0 : v(iVis)=vb.uvw()(row)(1)*f;
6304 0 : if(abs(u(iVis))>maxAbsUV) maxAbsUV=abs(u(iVis));
6305 0 : if(abs(v(iVis))>maxAbsUV) maxAbsUV=abs(v(iVis));
6306 0 : if(rotate) {
6307 0 : uRotated(iVis)=uvwRotated(0)*f;
6308 0 : vRotated(iVis)=uvwRotated(1)*f;
6309 0 : if(abs(uRotated(iVis))>maxAbsUV) maxAbsUV=abs(uRotated(iVis));
6310 0 : if(abs(vRotated(iVis))>maxAbsUV) maxAbsUV=abs(vRotated(iVis));
6311 : }
6312 0 : ++iVis;
6313 : }
6314 : }
6315 : }
6316 0 : }
6317 : }
6318 :
6319 0 : if(maxAbsUV==0.0) {
6320 0 : this->unlock();
6321 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6322 0 : return false;
6323 : }
6324 : else {
6325 0 : Quantity cell(0.5/maxAbsUV, "rad");
6326 : os << LogIO::NORMAL // Loglevel INFO
6327 0 : << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
6328 : os << LogIO::NORMAL // Loglevel INFO
6329 0 : << "Recommended cell size < " << cell.get("arcsec").getValue()
6330 0 : << " arcsec" << LogIO::POST;
6331 0 : }
6332 :
6333 :
6334 0 : return false;
6335 :
6336 : this->unlock();
6337 :
6338 0 : }
6339 0 : catch (AipsError x) {
6340 0 : this->unlock();
6341 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6342 0 : return false;
6343 :
6344 0 : }
6345 0 : catch (...) {
6346 0 : this->unlock();
6347 0 : }
6348 0 : this->unlock();
6349 :
6350 :
6351 :
6352 0 : return true;
6353 0 : }
6354 :
6355 : // Plot the visibilities
6356 0 : Bool Imager::plotvis(const String& type, const Int increment)
6357 : {
6358 :
6359 0 : if(!valid()) return false;
6360 0 : LogIO os(LogOrigin("imager", "plotvis()", WHERE));
6361 :
6362 0 : this->lock();
6363 : try {
6364 :
6365 : os << LogIO::NORMAL // Loglevel PROGRESS
6366 : << "Plotting Stokes I visibility for currently selected data"
6367 0 : << LogIO::POST;
6368 :
6369 :
6370 0 : MSColumns msc(*mssel_p);
6371 0 : Bool hasCorrected=!(msc.correctedData().isNull());
6372 0 : Bool hasModel= true; //with virtual model data service model data is always there
6373 : //why bother if it is not requested
6374 0 : if(!((type == "all") || (type=="model") || (type == "residual")))
6375 0 : hasModel=false;
6376 0 : if(!((type == "all") || (type=="corrected") || (type == "residual")))
6377 0 : hasCorrected=false;
6378 :
6379 :
6380 :
6381 0 : Bool twoPol=true;
6382 0 : Vector<String> polType=msc.feed().polarizationType()(0);
6383 0 : if (polType(0)!="X" && polType(0)!="Y" &&
6384 0 : polType(0)!="R" && polType(0)!="L") {
6385 0 : twoPol=false;
6386 : }
6387 :
6388 0 : ROVisIter& vi(*rvi_p);
6389 0 : VisBuffer vb(vi);
6390 :
6391 0 : Int nVis=0;
6392 0 : Int counter=0;
6393 0 : Float maxWeight=0;
6394 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6395 0 : for (vi.origin();vi.more();vi++) {
6396 0 : Int nRow=vb.nRow();
6397 0 : Int nChan=vb.nChannel();
6398 0 : maxWeight=max(maxWeight, max(vb.imagingWeight()));
6399 0 : for (Int row=0; row<nRow; ++row) {
6400 0 : for (Int chn=0; chn<nChan; ++chn) {
6401 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6402 0 : ++counter;
6403 0 : if(counter==increment) {
6404 0 : counter=0;
6405 0 : ++nVis;
6406 : }
6407 : }
6408 : }
6409 : }
6410 : }
6411 : }
6412 :
6413 0 : if(nVis==0) {
6414 0 : os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
6415 0 : if(maxWeight <=0){
6416 : os << LogIO::SEVERE << "Max of imaging-weight is " << maxWeight
6417 0 : << LogIO::POST;
6418 : os << LogIO::SEVERE << "Try setting it with the function weight"
6419 0 : << LogIO::POST;
6420 : }
6421 0 : this->unlock();
6422 0 : return false;
6423 : }
6424 :
6425 0 : if(increment>1) {
6426 : os << LogIO::NORMAL << "For increment = " << increment << ", found " << nVis // Loglevel INFO
6427 0 : << " points for plotting" << endl;
6428 : }
6429 : else {
6430 0 : os << LogIO::NORMAL << "Found " << nVis << " points for plotting" << endl; // Loglevel INFO
6431 : }
6432 0 : Vector<Float> amp(nVis); amp=0.0;
6433 0 : Vector<Float> correctedAmp(nVis); correctedAmp=0.0;
6434 0 : Vector<Float> modelAmp(nVis); modelAmp=0.0;
6435 0 : Vector<Float> residualAmp(nVis); residualAmp=0.0;
6436 0 : Vector<Float> uvDistance(nVis); uvDistance=0.0;
6437 :
6438 0 : if(!hasModel)
6439 0 : modelAmp.resize();
6440 0 : if(!hasCorrected)
6441 0 : correctedAmp.resize();
6442 0 : if(!hasCorrected || !hasModel)
6443 0 : residualAmp.resize();
6444 :
6445 :
6446 0 : Float maxuvDistance=0.0;
6447 0 : Float maxAmp=0.0;
6448 0 : Float maxCorrectedAmp=0.0;
6449 0 : Float maxModelAmp=0.0;
6450 0 : Float maxResidualAmp=0.0;
6451 0 : Int iVis=0;
6452 0 : counter=0;
6453 0 : vi.originChunks();
6454 0 : vi.origin();
6455 0 : uInt numCorrPol=vb.nCorr();
6456 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6457 0 : for (vi.origin();vi.more();vi++) {
6458 0 : Int nRow=vb.nRow();
6459 0 : Int nChan=vb.nChannel();
6460 0 : for (Int row=0; row<nRow; ++row) {
6461 0 : for (Int chn=0; chn<nChan; ++chn) {
6462 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6463 0 : ++counter;
6464 0 : if(counter==increment) {
6465 0 : counter=0;
6466 0 : Float f=vb.frequency()(chn)/C::c;
6467 0 : Float u=vb.uvw()(row)(0)*f;
6468 0 : Float v=vb.uvw()(row)(1)*f;
6469 0 : uvDistance(iVis)=sqrt(square(u)+square(v));
6470 0 : if(twoPol) {
6471 0 : amp(iVis)=sqrt((square(abs(vb.visCube()(0,chn,row)))+
6472 0 : square(abs(vb.visCube()(numCorrPol,chn,row))))/2.0);
6473 0 : if(hasCorrected)
6474 0 : correctedAmp(iVis)=
6475 0 : sqrt((square(abs(vb.correctedVisCube()(0,chn,row)))+
6476 0 : square(abs(vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6477 0 : if(hasModel)
6478 0 : modelAmp(iVis)=
6479 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)))+
6480 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row))))/2.0);
6481 0 : if(hasCorrected && hasModel)
6482 0 : residualAmp(iVis)=
6483 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
6484 0 : vb.correctedVisCube()(0,chn,row)))+
6485 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
6486 0 : vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6487 : }
6488 : else {
6489 0 : amp(iVis)=abs(vb.visCube()(0,chn,row));
6490 0 : if(hasCorrected)
6491 0 : correctedAmp(iVis)=abs(vb.correctedVisCube()(0,chn,row));
6492 0 : if(hasModel)
6493 0 : modelAmp(iVis)=abs(vb.modelVisCube()(0,chn,row));
6494 0 : if(hasCorrected && hasModel)
6495 0 : residualAmp(iVis)=
6496 0 : abs(vb.modelVisCube()(0,chn,row)-
6497 0 : vb.correctedVisCube()(0,chn,row));
6498 : }
6499 0 : if(uvDistance(iVis)>maxuvDistance) {
6500 0 : maxuvDistance=uvDistance(iVis);
6501 : }
6502 0 : if(amp(iVis)>maxAmp) {
6503 0 : maxAmp=amp(iVis);
6504 : }
6505 0 : if(hasCorrected && (correctedAmp(iVis)>maxCorrectedAmp)) {
6506 0 : maxCorrectedAmp=correctedAmp(iVis);
6507 : }
6508 0 : if(hasModel && (modelAmp(iVis)>maxModelAmp)) {
6509 0 : maxModelAmp=modelAmp(iVis);
6510 : }
6511 0 : if((hasModel&&hasCorrected) && (residualAmp(iVis)>maxResidualAmp)) {
6512 0 : maxResidualAmp=residualAmp(iVis);
6513 : }
6514 0 : ++iVis;
6515 : }
6516 : }
6517 : }
6518 : }
6519 : }
6520 : }
6521 :
6522 :
6523 :
6524 0 : if(maxuvDistance==0.0) {
6525 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6526 0 : this->unlock();
6527 0 : return false;
6528 : }
6529 :
6530 :
6531 :
6532 :
6533 :
6534 0 : Float Ymax(0.0);
6535 :
6536 0 : if (type.contains("corrected") && hasCorrected)
6537 0 : if(maxCorrectedAmp>Ymax) Ymax = maxCorrectedAmp;
6538 :
6539 0 : if (type.contains("model") && hasModel)
6540 0 : if(maxModelAmp>Ymax) Ymax = maxModelAmp;
6541 :
6542 0 : if (type.contains("residual") && (hasModel && hasCorrected))
6543 0 : if(maxResidualAmp>Ymax) Ymax = maxResidualAmp;
6544 :
6545 0 : if (type.contains("observed"))
6546 0 : if(maxAmp>Ymax) Ymax = maxAmp;
6547 :
6548 0 : if ((type=="all") || (type == ""))
6549 : {
6550 0 : if (maxAmp > Ymax) Ymax = maxAmp;
6551 0 : if(hasCorrected && (maxCorrectedAmp>Ymax)) Ymax = maxCorrectedAmp;
6552 0 : if(hasModel && (maxModelAmp>Ymax)) Ymax = maxModelAmp;
6553 0 : if((hasModel && hasCorrected) && maxResidualAmp>Ymax) Ymax = maxResidualAmp;
6554 : }
6555 :
6556 :
6557 0 : return false;
6558 :
6559 :
6560 : this->unlock();
6561 : return true;
6562 0 : } catch (AipsError x) {
6563 0 : this->unlock();
6564 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6565 0 : return false;
6566 0 : }
6567 : this->unlock();
6568 :
6569 : return true;
6570 0 : }
6571 :
6572 : // Plot the weights
6573 0 : Bool Imager::plotweights(const Bool gridded, const Int increment)
6574 : {
6575 :
6576 0 : if(!valid()) return false;
6577 0 : LogIO os(LogOrigin("imager", "plotweights()", WHERE));
6578 :
6579 0 : this->lock();
6580 : try {
6581 :
6582 :
6583 : os << LogIO::NORMAL // Loglevel PROGRESS
6584 : << "Plotting imaging weights for currently selected data"
6585 0 : << LogIO::POST;
6586 :
6587 0 : ROVisIter& vi(*rvi_p);
6588 0 : VisBuffer vb(vi);
6589 :
6590 0 : if(gridded) {
6591 0 : if(!assertDefinedImageParameters()) {this->unlock(); return false;}
6592 : // First find the gridded weights
6593 : Float uscale, vscale;
6594 : Int uorigin, vorigin;
6595 0 : uscale=(nx_p*mcellx_p.get("rad").getValue())/2.0;
6596 0 : vscale=(ny_p*mcelly_p.get("rad").getValue())/2.0;
6597 0 : uorigin=nx_p/2;
6598 0 : vorigin=ny_p/2;
6599 :
6600 : // Simply declare a big matrix
6601 0 : Float maxWeight=0.0;
6602 0 : Matrix<Float> gwt(nx_p,ny_p);
6603 0 : gwt=0.0;
6604 :
6605 : Float u, v;
6606 0 : Float sumwt=0.0;
6607 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6608 0 : for (vi.origin();vi.more();vi++) {
6609 0 : Int nRow=vb.nRow();
6610 0 : Int nChan=vb.nChannel();
6611 0 : for (Int row=0; row<nRow; ++row) {
6612 0 : for (Int chn=0; chn<nChan; ++chn) {
6613 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6614 0 : Float f=vb.frequency()(chn)/C::c;
6615 0 : u=vb.uvw()(row)(0)*f;
6616 0 : v=vb.uvw()(row)(1)*f;
6617 0 : Int ucell=Int(uscale*u+uorigin);
6618 0 : Int vcell=Int(vscale*v+vorigin);
6619 0 : if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
6620 0 : gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
6621 0 : sumwt+=vb.imagingWeight()(chn,row);
6622 0 : if(vb.imagingWeight()(chn,row)>maxWeight) {
6623 0 : maxWeight=vb.imagingWeight()(chn,row);
6624 : }
6625 : }
6626 0 : ucell=Int(-uscale*u+uorigin);
6627 0 : vcell=Int(-vscale*v+vorigin);
6628 0 : if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
6629 0 : gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
6630 : }
6631 : }
6632 : }
6633 : }
6634 : }
6635 : }
6636 :
6637 0 : if(sumwt>0.0) {
6638 0 : os << LogIO::NORMAL << "Sum of weights = " << sumwt << endl; // Loglevel INFO
6639 : }
6640 : else {
6641 0 : this->unlock();
6642 : os << LogIO::SEVERE << "Sum of weights is zero: perhaps you need to weight the data"
6643 0 : << LogIO::POST;
6644 0 : return false;
6645 : }
6646 :
6647 :
6648 : //Float umax=Float(nx_p/2)/uscale;
6649 : //Float vmax=Float(ny_p/2)/vscale;
6650 :
6651 :
6652 0 : return false;
6653 0 : }
6654 : else {
6655 :
6656 : // Now do the points plot
6657 0 : Int nVis=0;
6658 0 : Int counter=0;
6659 0 : Float maxWeight=0.0;
6660 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6661 0 : for (vi.origin();vi.more();vi++) {
6662 0 : Int nRow=vb.nRow();
6663 0 : Int nChan=vb.nChannel();
6664 0 : for (Int row=0; row<nRow; ++row) {
6665 0 : for (Int chn=0; chn<nChan; ++chn) {
6666 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6667 0 : ++counter;
6668 0 : if(counter==increment) {
6669 0 : counter=0;
6670 0 : ++nVis;
6671 : }
6672 : }
6673 : }
6674 : }
6675 : }
6676 : }
6677 :
6678 0 : if(increment>1) {
6679 : os << LogIO::NORMAL // Loglevel INFO
6680 : << "For increment = " << increment << ", found " << nVis
6681 0 : << " points for plotting" << endl;
6682 : }
6683 : else {
6684 : os << LogIO::NORMAL // Loglevel INFO
6685 0 : << "Found " << nVis << " points for plotting" << endl;
6686 : }
6687 :
6688 0 : Float maxuvDistance=0.0;
6689 0 : Vector<Float> weights(nVis);
6690 0 : Vector<Float> uvDistance(nVis);
6691 0 : weights=0.0;
6692 0 : uvDistance=0.0;
6693 :
6694 0 : Int iVis=0;
6695 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6696 0 : for (vi.origin();vi.more();vi++) {
6697 0 : Int nRow=vb.nRow();
6698 0 : Int nChan=vb.nChannel();
6699 0 : for (Int row=0; row<nRow; ++row) {
6700 0 : for (Int chn=0; chn<nChan; ++chn) {
6701 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6702 0 : ++counter;
6703 0 : if(counter==increment) {
6704 0 : Float f=vb.frequency()(chn)/C::c;
6705 0 : Float u=vb.uvw()(row)(0)*f;
6706 0 : Float v=vb.uvw()(row)(1)*f;
6707 0 : uvDistance(iVis)=sqrt(square(u)+square(v));
6708 0 : weights(iVis)=vb.imagingWeight()(chn,row);
6709 0 : if(vb.imagingWeight()(chn,row)>maxWeight) {
6710 0 : maxWeight=vb.imagingWeight()(chn,row);
6711 : }
6712 0 : if(uvDistance(iVis)>maxuvDistance) {
6713 0 : maxuvDistance=uvDistance(iVis);
6714 : }
6715 0 : counter=0;
6716 0 : ++iVis;
6717 : }
6718 : }
6719 : }
6720 : }
6721 : }
6722 : }
6723 :
6724 0 : if(maxuvDistance==0.0) {
6725 0 : this->unlock();
6726 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6727 0 : return false;
6728 : }
6729 :
6730 :
6731 0 : return false;
6732 0 : }
6733 :
6734 :
6735 :
6736 : this->unlock();
6737 : return true;
6738 0 : } catch (AipsError x) {
6739 0 : this->unlock();
6740 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6741 0 : return false;
6742 0 : }
6743 : this->unlock();
6744 :
6745 : return true;
6746 0 : }
6747 :
6748 0 : Bool Imager::clipvis(const Quantity& threshold)
6749 : {
6750 :
6751 0 : if(!valid()) return false;
6752 :
6753 0 : LogIO os(LogOrigin("imager", "clipvis()", WHERE));
6754 :
6755 0 : this->lock();
6756 : try {
6757 :
6758 0 : Float thres=threshold.get("Jy").getValue();
6759 :
6760 : os << LogIO::NORMAL // Loglevel PROGRESS
6761 : << "Clipping visibilities where residual visibility > "
6762 0 : << thres << " Jy" << LogIO::POST;
6763 0 : if(!wvi_p){
6764 : os << LogIO::WARN
6765 : << "Cannot clip visibilities in read only mode of ms"
6766 0 : << LogIO::POST;
6767 0 : return false;
6768 : }
6769 0 : VisIter& vi(*wvi_p);
6770 0 : VisBuffer vb(vi);
6771 :
6772 :
6773 0 : vi.originChunks();
6774 0 : vi.origin();
6775 : // Making sure picking LL for [RR RL LR LL] correlations or [RR LL]
6776 0 : uInt numCorrPol=vb.modelVisCube().shape()(0) - 1 ;
6777 0 : Int nBad=0;
6778 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6779 0 : for (vi.origin();vi.more();vi++) {
6780 0 : Int nRow=vb.nRow();
6781 0 : Int nChan=vb.nChannel();
6782 0 : for (Int row=0; row<nRow; ++row) {
6783 0 : for (Int chn=0; chn<nChan; ++chn) {
6784 0 : if(!vb.flag()(chn,row)) {
6785 : Float residualAmp=
6786 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
6787 0 : vb.correctedVisCube()(0,chn,row)))+
6788 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
6789 0 : vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6790 0 : if(residualAmp>thres) {
6791 0 : vb.flag()(chn,row)=true;
6792 0 : ++nBad;
6793 : }
6794 : }
6795 : }
6796 : }
6797 0 : vi.setFlag(vb.flag());
6798 : }
6799 : }
6800 :
6801 0 : os << LogIO::NORMAL << "Flagged " << nBad << " points" << LogIO::POST; // Loglevel INFO
6802 :
6803 0 : this->unlock();
6804 0 : return true;
6805 0 : } catch (AipsError x) {
6806 0 : this->unlock();
6807 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6808 0 : }
6809 0 : this->unlock();
6810 :
6811 0 : return true;
6812 0 : }
6813 :
6814 : // Plot various ids
6815 0 : Bool Imager::plotsummary()
6816 : {
6817 :
6818 0 : if(!valid()) return false;
6819 :
6820 0 : LogIO os(LogOrigin("imager", "plotsummary()", WHERE));
6821 :
6822 0 : os << LogIO::WARN << "NOT implemented " << LogIO::POST;
6823 0 : return false;
6824 :
6825 : this->lock();
6826 : try {
6827 : /*
6828 : os << "Plotting field and spectral window ids for currently selected data" << LogIO::POST;
6829 :
6830 : ROVisIter& vi(*rvi_p);
6831 : VisBuffer vb(vi);
6832 :
6833 : Int nVis=0;
6834 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6835 : for (vi.origin();vi.more();vi++) {
6836 : Int nRow=vb.nRow();
6837 : for (Int row=0; row<nRow; ++row) {
6838 : ++nVis;
6839 : }
6840 : }
6841 : }
6842 :
6843 : os << "Found " << nVis << " selected records" << LogIO::POST;
6844 :
6845 : Vector<Float> fieldId(nVis);
6846 : Vector<Float> spectralWindowId(nVis);
6847 : Vector<Double> t(nVis);
6848 :
6849 : Int maxFieldId=0;
6850 : Int maxSpectralWindowId=0;
6851 : Int iVis=0;
6852 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6853 : for (vi.origin();vi.more();vi++) {
6854 : Int nRow=vb.nRow();
6855 : for (Int row=0; row<nRow; ++row) {
6856 : t(iVis)=vb.time()(row);
6857 : fieldId(iVis)=vb.fieldId()+1.0;
6858 : spectralWindowId(iVis)=vb.spectralWindow()+1.003;
6859 : if(Int(fieldId(iVis))>maxFieldId) maxFieldId=Int(fieldId(iVis));
6860 : if(Int(spectralWindowId(iVis))>maxSpectralWindowId)
6861 : maxSpectralWindowId=Int(spectralWindowId(iVis));
6862 : ++iVis;
6863 : }
6864 : }
6865 : }
6866 :
6867 : Double tStart=t(0);
6868 : Vector<Float> timeFloat(nVis);
6869 : for(Int i=0;i<nVis;++i) {
6870 : timeFloat(i)=Float(t(i)-tStart);
6871 : }
6872 :
6873 : MSColumns msc(*ms_p);
6874 : PGPlotter plotter=getPGPlotter();
6875 : plotter.subp(1, 2);
6876 : plotter.page();
6877 : plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0, Float(maxFieldId)*1.1);
6878 : plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
6879 : String xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
6880 : plotter.lab(xLabel, "ID", "Field IDs for " +imageName());
6881 : plotter.sci(1);
6882 : for (Int fid=0;fid<maxFieldId;++fid) {
6883 : String fieldName=msc.field().name()(fid);
6884 : plotter.text(1.02*timeFloat(nVis-1), Float(fid+1), fieldName);
6885 : }
6886 : plotter.pt(timeFloat,fieldId,-1);
6887 : plotter.page();
6888 : plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0,
6889 : Float(maxSpectralWindowId)*1.1);
6890 : plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
6891 : xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
6892 : plotter.lab(xLabel, "ID", "Spectral Window IDs for " +imageName());
6893 : plotter.sci(1);
6894 : for(Int spwId=0;spwId<maxSpectralWindowId;++spwId) {
6895 : Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spwId);
6896 : ostringstream spwString;
6897 : spwString<<chanFreq(0)/1.0e9<<" GHz";
6898 : plotter.text(1.02*timeFloat(nVis-1), Float(spwId+1),
6899 : spwString);
6900 : }
6901 : plotter.pt(timeFloat,spectralWindowId,-1);
6902 : plotter.iden();
6903 : this->unlock();
6904 : return true;
6905 : */
6906 : } catch (AipsError x) {
6907 : this->unlock();
6908 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6909 : return false;
6910 : }
6911 :
6912 : this->unlock();
6913 :
6914 : return true;
6915 0 : }
6916 :
6917 :
6918 0 : Bool Imager::detached() const
6919 : {
6920 0 : if (ms_p.null()) {
6921 0 : LogIO os(LogOrigin("imager", "detached()", WHERE));
6922 : os << LogIO::SEVERE <<
6923 : "imager is detached - cannot perform operation." << endl <<
6924 0 : "Call imager.open('filename') to reattach." << LogIO::POST;
6925 0 : return true;
6926 0 : }
6927 0 : return false;
6928 : }
6929 :
6930 0 : Bool Imager::makemodelfromsd(const String& sdImage, const String& modelImage,
6931 : const String& lowPSF, String& maskImage)
6932 : {
6933 :
6934 0 : if(!valid()) return false;
6935 :
6936 0 : LogIO os(LogOrigin("imager", "makemodelfromsd()", WHERE));
6937 :
6938 : try {
6939 :
6940 0 : if(!Table::isReadable(sdImage)){
6941 : os << LogIO::SEVERE << "Single Dish " << sdImage
6942 0 : << " image is not readable" << LogIO::EXCEPTION;
6943 :
6944 0 : return false;
6945 : }
6946 :
6947 : os << LogIO::NORMAL << "Creating an initial model image " << modelImage // Loglevel INFO
6948 0 : << " from single dish image " << sdImage << LogIO::POST;
6949 :
6950 0 : CoordinateSystem coordsys;
6951 : //imagecoordinates(coordsys);
6952 0 : imagecoordinates2(coordsys);
6953 0 : String modelName=modelImage;
6954 0 : this->makeEmptyImage(coordsys, modelName, fieldid_p);
6955 :
6956 0 : PagedImage<Float> model(modelImage);
6957 0 : PagedImage<Float> low0(sdImage);
6958 0 : String sdObs=low0.coordinates().obsInfo().telescope();
6959 :
6960 0 : GaussianBeam lBeam;
6961 0 : ImageInfo lowInfo=low0.imageInfo();
6962 0 : lBeam=lowInfo.restoringBeam();
6963 :
6964 0 : Float beamFactor=-1.0;
6965 :
6966 :
6967 : // regrid the single dish image
6968 : {
6969 0 : ImageRegrid<Float> ir;
6970 0 : IPosition axes(3,0,1,3); // if its a cube, regrid the spectral too
6971 0 : ir.regrid(model, Interpolate2D::LINEAR, axes, low0);
6972 0 : }
6973 :
6974 :
6975 :
6976 : // Will need to make a complex image to apply the beam
6977 0 : TempImage<Complex> ctemp(model.shape(), model.coordinates());
6978 0 : if(lowPSF=="") {
6979 : os << LogIO::NORMAL // Loglevel INFO
6980 : << "Using primary beam of single dish to determine flux scale"
6981 0 : << LogIO::POST;
6982 :
6983 0 : TempImage<Float> beamTemp(model.shape(), model.coordinates());
6984 : //Make the PB accordingly
6985 0 : if(lBeam.isNull()) {
6986 :
6987 0 : if (doDefaultVP_p) {
6988 0 : if(telescope_p!=""){
6989 0 : ObsInfo myobsinfo=this->latestObsInfo();
6990 0 : myobsinfo.setTelescope(telescope_p);
6991 0 : coordsys.setObsInfo(myobsinfo);
6992 :
6993 0 : }
6994 : else{
6995 0 : if(sdObs != ""){
6996 0 : telescope_p=sdObs;
6997 0 : ObsInfo myobsinfo=this->latestObsInfo();
6998 0 : myobsinfo.setTelescope(telescope_p);
6999 0 : coordsys.setObsInfo(myobsinfo);
7000 0 : }
7001 : else{
7002 0 : telescope_p=coordsys.obsInfo().telescope();
7003 : }
7004 : }
7005 0 : beamTemp.setCoordinateInfo(coordsys);
7006 0 : this->makePBImage(beamTemp);
7007 :
7008 : }
7009 : else{
7010 0 : Table vpTable(vpTableStr_p);
7011 0 : this->makePBImage(vpTable, beamTemp);
7012 0 : }
7013 0 : StokesImageUtil::FitGaussianPSF(beamTemp, lBeam);
7014 0 : LatticeExprNode sumImage = sum(beamTemp);
7015 0 : beamFactor=sumImage.getFloat();
7016 :
7017 0 : }
7018 :
7019 :
7020 0 : }
7021 : else {
7022 : os << LogIO::NORMAL // Loglevel INFO
7023 : << "Using specified low resolution PSF to determine sd flux scale"
7024 0 : << LogIO::POST;
7025 : // regrid the single dish psf
7026 0 : PagedImage<Float> lowpsf0(lowPSF);
7027 0 : TempImage<Float> lowpsf(model.shape(), model.coordinates());
7028 : {
7029 0 : ImageRegrid<Float> ir;
7030 0 : IPosition axes(2,0,1); //
7031 0 : ir.regrid(lowpsf, Interpolate2D::LINEAR, axes, lowpsf0);
7032 0 : }
7033 0 : LatticeExprNode sumImage = sum(lowpsf);
7034 0 : beamFactor=sumImage.getFloat();
7035 0 : if(lBeam.isNull()) {
7036 0 : os << LogIO::NORMAL << "Finding SD beam from given PSF" << LogIO::POST; // Loglevel PROGRESS
7037 0 : StokesImageUtil::FitGaussianPSF(lowpsf0, lBeam);
7038 : }
7039 0 : }
7040 :
7041 :
7042 : // This factor comes from the beam volumes
7043 0 : if(sdScale_p!=1.0)
7044 : os << LogIO::DEBUG1
7045 : << "Multiplying single dish data by user specified factor "
7046 0 : << sdScale_p << LogIO::POST;
7047 0 : Float sdScaling = sdScale_p;
7048 0 : if(! lBeam.isNull()) {
7049 0 : Int directionIndex=model.coordinates().findCoordinate(Coordinate::DIRECTION);
7050 : DirectionCoordinate
7051 0 : directionCoord=model.coordinates().directionCoordinate(directionIndex);
7052 0 : Vector<String> units(2); units.set("arcsec");
7053 0 : directionCoord.setWorldAxisUnits(units);
7054 0 : Vector<Double> incr= directionCoord.increment();
7055 0 : if(beamFactor >0.0) {
7056 0 : beamFactor=1.0/beamFactor;
7057 : }
7058 : else{
7059 : // beamFactor=
7060 : // abs(incr(0)*incr(1))/(lBeam(0).get("arcsec").getValue()*lBeam(1).get("arcsec").getValue()*1.162);
7061 : //Brute Force for now.
7062 0 : IPosition imshape(4, nx_p, ny_p, 1, 1);
7063 0 : TempImage<Float> lowpsf(imshape, coordsys);
7064 0 : lowpsf.set(0.0);
7065 0 : IPosition center(4, Int((nx_p/4)*2), Int((ny_p/4)*2),0,0);
7066 0 : lowpsf.putAt(1.0, center);
7067 0 : StokesImageUtil::Convolve(lowpsf, lBeam, false);
7068 0 : LatticeExprNode sumImage = sum(lowpsf);
7069 0 : beamFactor=1.0/sumImage.getFloat();
7070 :
7071 :
7072 0 : }
7073 : os << LogIO::NORMAL << "Beam volume factor " // Loglevel INFO
7074 0 : << beamFactor << LogIO::POST;
7075 0 : sdScaling*=beamFactor;
7076 0 : }
7077 : else {
7078 0 : os << LogIO::WARN << "Insufficient information to scale correctly" << LogIO::POST;
7079 : }
7080 :
7081 : //Convert to Jy/pixel
7082 0 : model.copyData( (LatticeExpr<Float>)((model * sdScaling)));
7083 0 : model.setUnits(Unit("Jy/pixel"));
7084 :
7085 : //make a mask image
7086 0 : this->makeEmptyImage(coordsys, maskImage, fieldid_p);
7087 0 : PagedImage<Float> mask(maskImage);
7088 0 : mask.set(1.0);
7089 0 : ArrayLattice<Bool> sdMask(model.getMask());
7090 0 : mask.copyData( LatticeExpr<Float> (mask* ntrue(sdMask)*model));
7091 0 : StokesImageUtil::MaskFrom(mask, mask, Quantity(0.0, "Jy"));
7092 0 : model.copyData( LatticeExpr<Float> (mask*model));
7093 0 : return true;
7094 0 : } catch (AipsError x) {
7095 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
7096 0 : << LogIO::POST;
7097 0 : return false;
7098 0 : }
7099 :
7100 : return true;
7101 :
7102 :
7103 0 : }
7104 :
7105 :
7106 0 : Int Imager::interactivemask(const String& image, const String& mask,
7107 : Int& niter, Int& ncycles, String& thresh, const Bool forceReload){
7108 :
7109 0 : LogIO os(LogOrigin("Imager", "interactivemask()", WHERE));
7110 0 : if(Table::isReadable(mask)) {
7111 0 : if (! Table::isWritable(mask)) {
7112 0 : os << LogIO::WARN << "Mask image is not modifiable " << LogIO::POST;
7113 0 : return false;
7114 : }
7115 : //we should regrid here if image and mask do not match
7116 : }
7117 : else{
7118 0 : clone(image, mask);
7119 : }
7120 : #ifdef USE_GRPC
7121 0 : Quantity thr;
7122 0 : if ( ! Quantity::read(thr,thresh) ) thr = Quantity(0,"Jy");
7123 0 : float thold = (float) thr.get("Jy").getValue( );
7124 0 : grpcInteractiveClean::getManager( ).setControls( niter, ncycles, thold);
7125 : #endif
7126 0 : return false;
7127 0 : }
7128 :
7129 0 : Record Imager::iClean(const String& algorithm, const Int niter, const Double gain,
7130 : const Quantity& threshold,
7131 : const Bool displayprogress,
7132 : const Vector<String>& model,
7133 : const Vector<Bool>& keepfixed, const String& complist,
7134 : const Vector<String>& mask,
7135 : const Vector<String>& image,
7136 : const Vector<String>& residual,
7137 : const Vector<String>& psfnames,
7138 : const Bool interactive, const Int npercycle,
7139 : const String& masktemplate)
7140 : {
7141 0 : Record rstat;
7142 :
7143 0 : logSink_p.clearLocally();
7144 0 : LogIO os(LogOrigin("imager", "iClean()"), logSink_p);
7145 :
7146 0 : if(!ms_p.null()) {
7147 : //try
7148 : {
7149 :
7150 0 : Vector<String> amodel(model);
7151 0 : Vector<Bool> fixed(keepfixed);
7152 0 : Vector<String> amask(mask);
7153 0 : Vector<String> aimage(image);
7154 0 : Vector<String> aresidual(residual);
7155 0 : Vector<String> apsf(psfnames);
7156 :
7157 0 : if(String(algorithm) != "msmfs") ntaylor_p=1; /* masks increment by ntaylor_p only for msmfs */
7158 0 : uInt nmods = aresidual.nelements()/ntaylor_p;
7159 :
7160 0 : if( (apsf.nelements()==1) && apsf[0]==String(""))
7161 0 : apsf.resize();
7162 0 : if(!interactive){
7163 0 : rstat = clean(String(algorithm), niter, gain,
7164 : threshold, displayprogress,
7165 0 : amodel, fixed, String(complist), amask,
7166 0 : aimage, aresidual, apsf);
7167 : }
7168 : else{
7169 0 : if((amask.nelements()==0) || (amask[0]==String(""))){
7170 0 : amask.resize(amodel.nelements());
7171 0 : for (uInt k=0; k < amask.nelements(); ++k){
7172 0 : amask[k]=amodel[k]+String(".mask");
7173 : }
7174 : }
7175 0 : Vector<Bool> nointerac(nmods);
7176 0 : nointerac.set(false);
7177 0 : if(fixed.nelements() != nmods){
7178 0 : fixed.resize(nmods);
7179 0 : fixed.set(false);
7180 : }
7181 0 : Bool forceReload=true;
7182 0 : Int nloop=0;
7183 0 : if(npercycle != 0)
7184 0 : nloop=niter/npercycle;
7185 0 : Int continter=0;
7186 0 : Int elniter=npercycle;
7187 0 : ostringstream oos;
7188 0 : threshold.print(oos);
7189 0 : String thresh=String(oos);
7190 0 : if(String(masktemplate) != String("")){
7191 0 : continter=interactivemask(masktemplate, amask[0],
7192 : elniter, nloop, thresh);
7193 : }
7194 : else {
7195 : // do a zero component clean to get started
7196 0 : rstat=clean(String(algorithm), 0, gain,
7197 : threshold, displayprogress,
7198 0 : amodel, fixed, String(complist), amask,
7199 0 : aimage, aresidual, Vector<String>(0), false);
7200 :
7201 0 : for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
7202 0 : if(Table::isReadable(aimage[nIm]) && Table::isWritable(aresidual[nIm]) ){
7203 0 : PagedImage<Float> rest(aimage[nIm]);
7204 0 : PagedImage<Float> resi(aresidual[nIm]);
7205 0 : copyMask(resi, rest, "mask0");
7206 0 : }
7207 0 : forceReload=forceReload || (aresidual.nelements() >1);
7208 0 : continter=interactivemask(aresidual[nIm], amask[nIm],
7209 : elniter, nloop,thresh, forceReload);
7210 0 : forceReload=false;
7211 0 : if(continter>=1)
7212 0 : nointerac(nIm)=true;
7213 0 : if(continter==2)
7214 0 : fixed(nIm)=true;
7215 :
7216 : }
7217 0 : if(allEQ(nointerac, true)){
7218 0 : elniter=niter;
7219 : //make it do one more loop/clean but with all niter
7220 0 : nloop=1;
7221 : }
7222 : }
7223 0 : for (Int k=0; k < nloop; ++k){
7224 :
7225 0 : casacore::Quantity thrsh;
7226 0 : if(!casacore::Quantity::read(thrsh, thresh)){
7227 : os << LogIO::WARN << "Error interpreting threshold"
7228 0 : << LogIO::POST;
7229 0 : thrsh=casacore::Quantity(0, "Jy");
7230 0 : thresh="0.0Jy";
7231 : }
7232 0 : Vector<String> elpsf(0);
7233 : //Need to save psfs in interactive only once and lets do it the
7234 : //first time
7235 0 : if(k==0)
7236 0 : elpsf=apsf;
7237 0 : if(anyEQ(fixed, false)){
7238 0 : rstat = clean(String(algorithm), elniter, gain,
7239 : thrsh,
7240 : displayprogress,
7241 0 : amodel, fixed, String(complist),
7242 : amask,
7243 0 : aimage, aresidual, elpsf, k == 0);
7244 : //if clean converged... equivalent to stop
7245 0 : if(rstat.asBool("converged")){
7246 0 : continter=2;
7247 0 : fixed.set(true);
7248 : }
7249 0 : if(anyEQ(fixed, false) && anyEQ(nointerac,false)){
7250 0 : Int remainloop=nloop-k-1;
7251 0 : for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
7252 0 : if(!nointerac(nIm)){
7253 0 : continter=interactivemask(aresidual[nIm], amask[nIm],
7254 :
7255 : elniter, remainloop,
7256 0 : thresh, (aresidual.nelements() >1));
7257 0 : if(continter>=1)
7258 0 : nointerac(nIm)=true;
7259 0 : if(continter==2)
7260 0 : fixed(nIm)=true;
7261 : }
7262 : }
7263 0 : k=nloop-remainloop-1;
7264 0 : if(allEQ(nointerac,true)){
7265 0 : elniter=niter-(k+1)*npercycle;
7266 : //make it do one more loop/clean but with remaining niter
7267 0 : k=nloop-2;
7268 : }
7269 : }
7270 : }
7271 0 : }
7272 : //Unset the mask in the residual
7273 : // Cause as requested in CAS-1768...
7274 0 : for (uInt nIm=0; nIm < aresidual.nelements(); ++nIm){
7275 0 : if(Table::isWritable(aresidual[nIm]) ){
7276 0 : PagedImage<Float> resi(aresidual[nIm]);
7277 0 : if(resi.hasRegion("mask0", RegionHandler::Masks)){
7278 0 : resi.setDefaultMask("");
7279 : }
7280 0 : }
7281 : }
7282 :
7283 0 : }
7284 :
7285 0 : os << "Restoring Image(s) with the clean-beam" << LogIO::POST;
7286 0 : restoreImages(aimage, (niter>=0) );
7287 0 : this->writeHistory(os);
7288 : try{
7289 : // write data processing history into image logtable
7290 0 : LoggerHolder imagelog (false);
7291 0 : LogSink& sink = imagelog.sink();
7292 0 : LogOrigin lor( String("imager"), String("clean()") );
7293 0 : LogMessage msg(lor);
7294 0 : sink.postLocally(msg);
7295 0 : MSHistoryColumns msHis(ms_p->history());
7296 0 : transferHistory(imagelog, msHis);
7297 0 : for (Int thismodel=0;thismodel<Int(aimage.nelements());++thismodel) {
7298 0 : if(Table::isWritable(aimage(thismodel))){
7299 0 : PagedImage<Float> restoredImage(aimage(thismodel),
7300 0 : TableLock(TableLock::AutoNoReadLocking));
7301 0 : LoggerHolder& log = restoredImage.logger();
7302 0 : log.append(imagelog);
7303 0 : log.flush();
7304 0 : restoredImage.table().relinquishAutoLocks(true);
7305 0 : }
7306 : }
7307 0 : }
7308 0 : catch(exception& x){
7309 :
7310 0 : this->unlock();
7311 0 : destroySkyEquation();
7312 0 : os << LogIO::WARN << "Caught exception: " << x.what()
7313 0 : << LogIO::POST;
7314 : os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
7315 0 : <<LogIO::POST;
7316 : //continue and wrap up this function
7317 :
7318 0 : }
7319 0 : catch(...){
7320 0 : this->unlock();
7321 0 : destroySkyEquation();
7322 0 : os << LogIO::WARN << "Caught unknown exception" << LogIO::POST;
7323 : os << LogIO::SEVERE << "The MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
7324 0 : <<LogIO::POST;
7325 :
7326 0 : }
7327 :
7328 :
7329 0 : } //catch (AipsError x) {
7330 : //os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
7331 : // RETHROW(x);
7332 : // }
7333 : } else {
7334 0 : os << LogIO::SEVERE << "No MeasurementSet has been assigned, please run open." << LogIO::POST;
7335 : }
7336 0 : return rstat;
7337 0 : }
7338 :
7339 0 : Bool Imager::adviseChanSelex(Double& freqStart, Double& freqEnd,
7340 : const Double& freqStep, const MFrequency::Types& freqframe,
7341 : Vector< Vector<Int> >& spw, Vector< Vector<Int> >& start,
7342 : Vector< Vector<Int> >& nchan, const String& ms, const Int field_id, const Bool getFreqRange, const String spwselection){
7343 :
7344 0 : LogIO os(LogOrigin("imager", "adviseChanSelex"));
7345 0 : if(ms==String("")){
7346 0 : if(numMS_p < 1 || !rvi_p){
7347 : os << LogIO::SEVERE << "Data selection incomplete"
7348 0 : << LogIO::POST;
7349 0 : return false;
7350 : }
7351 : }
7352 0 : spw.resize();
7353 0 : start.resize();
7354 0 : nchan.resize();
7355 : try {
7356 0 : if(!getFreqRange){
7357 0 : Block<Vector<Int> > bnchan;
7358 0 : Block<Vector<Int> > bstart;
7359 0 : Block<Vector<Int> > bspw;
7360 : Double fS, fE;
7361 0 : fS=freqStart;
7362 0 : fE=freqEnd;
7363 0 : if(freqEnd < freqStart){
7364 0 : fS=freqEnd;
7365 0 : fE=freqStart;
7366 : }
7367 :
7368 0 : if(ms==String("")){
7369 0 : rvi_p->getSpwInFreqRange(bspw, bstart, bnchan, fS, fE, fabs(freqStep), freqframe);
7370 : }
7371 : else{
7372 0 : bnchan.resize(1);
7373 0 : bstart.resize(1);
7374 0 : bspw.resize(1);
7375 0 : MeasurementSet elms(String(ms), TableLock(TableLock::AutoNoReadLocking), Table::Old);
7376 0 : MSUtil::getSpwInFreqRange(bspw[0], bstart[0], bnchan[0], elms, fS, fE, fabs(freqStep), freqframe, field_id);
7377 0 : elms.relinquishAutoLocks(true);
7378 :
7379 0 : }
7380 0 : spw=Vector<Vector<Int> >(bspw.begin( ), bspw.end( ));
7381 0 : start=Vector<Vector<Int> >(bstart.begin( ), bstart.end( ));
7382 0 : nchan=Vector<Vector<Int> >(bnchan.begin( ), bnchan.end( ));
7383 0 : }
7384 : else{
7385 0 : if(ms==String("")){
7386 0 : rvi_p->getFreqInSpwRange(freqStart, freqEnd, freqframe);
7387 : }
7388 : else{
7389 0 : MeasurementSet elms(ms, TableLock(TableLock::AutoNoReadLocking), Table::Old);
7390 0 : MSSelection thisSelection;
7391 0 : String spsel=spwselection;
7392 0 : if(spsel=="")spsel="*";
7393 0 : thisSelection.setSpwExpr(spsel);
7394 0 : TableExprNode exprNode=thisSelection.toTableExprNode(&elms);
7395 0 : Matrix<Int> chanlist=thisSelection.getChanList();
7396 0 : if(chanlist.ncolumn() <3){
7397 0 : freqStart=-1.0;
7398 0 : freqEnd=-1.0;
7399 0 : return false;
7400 : }
7401 0 : Vector<Int> elspw=chanlist.column(0);
7402 0 : Vector<Int> elstart=chanlist.column(1);
7403 0 : Vector<Int> elnchan=Vector<Int> (chanlist.column(2)-elstart)+1;
7404 0 : MSUtil::getFreqRangeInSpw(freqStart, freqEnd, elspw, elstart, elnchan, elms, freqframe, field_id);
7405 0 : }
7406 :
7407 : }
7408 :
7409 :
7410 :
7411 :
7412 0 : } catch (AipsError x) {
7413 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
7414 0 : << LogIO::POST;
7415 0 : return false;
7416 0 : }
7417 0 : catch (...){
7418 : os << LogIO::SEVERE << "Unknown exception handled"
7419 0 : << LogIO::POST;
7420 0 : return false;
7421 :
7422 0 : }
7423 :
7424 0 : return true;
7425 :
7426 0 : }
7427 :
7428 :
7429 :
7430 : } //# NAMESPACE CASA - END
7431 :
|