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 1679 : Imager::Imager()
194 1679 : : msname_p(""), vs_p(0), rvi_p(0), wvi_p(0), ft_p(0),
195 1679 : cft_p(0), se_p(0),
196 1679 : sm_p(0), vp_p(0), gvp_p(0), setimaged_p(false), nullSelect_p(false),
197 1679 : mssFreqSel_p(), mssChanSel_p(),
198 1679 : clean_panel_p(0), image_id_p(0), mask_id_p(0),
199 5037 : prev_image_id_p(0), prev_mask_id_p(0), projection_p("SIN")
200 : {
201 1679 : ms_p=0;
202 1679 : mssel_p=0;
203 1679 : lockCounter_p=0;
204 1679 : numMS_p=0;
205 1679 : defaults();
206 1679 : };
207 :
208 :
209 1679 : void Imager::defaults()
210 : {
211 :
212 1679 : setimaged_p=false;
213 1679 : nullSelect_p=false;
214 1679 : nx_p=128; ny_p=128; facets_p=1;
215 1679 : wprojPlanes_p=-1;
216 1679 : mcellx_p=Quantity(1, "arcsec"); mcelly_p=Quantity(1, "arcsec");
217 1679 : shiftx_p=Quantity(0.0, "arcsec"); shifty_p=Quantity(0.0, "arcsec");
218 1679 : distance_p=Quantity(0.0, "m");
219 1679 : stokes_p="I"; npol_p=1;
220 1679 : nscales_p=5;
221 1679 : ntaylor_p=1;
222 1679 : reffreq_p=0.0;
223 1679 : useNewMTFT_p=false;
224 1679 : scaleMethod_p="nscales";
225 1679 : scaleInfoValid_p=false;
226 1679 : dataMode_p="none";
227 1679 : imageMode_p="MFS";
228 1679 : dataNchan_p=0;
229 1679 : imageNchan_p=0;
230 1679 : doVP_p=false;
231 1679 : doDefaultVP_p = true;
232 1679 : parAngleInc_p=Quantity(360.,"deg");
233 1679 : skyPosThreshold_p=Quantity(180.,"deg");
234 1679 : telescope_p="";
235 1679 : gridfunction_p="SF";
236 1679 : minWeight_p=0.;
237 1679 : clipminmax_p=false;
238 1679 : doMultiFields_p=false;
239 1679 : doWideBand_p=false;
240 1679 : multiFields_p=false;
241 : // Use half the machine memory as cache. The user can override
242 : // this via the setoptions function().
243 1679 : 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 1679 : if(cache_p <=0 )
247 0 : cache_p=2000000000/8;
248 1679 : tile_p=16;
249 1679 : ftmachine_p="ft";
250 1679 : wfGridding_p=false;
251 1679 : padding_p=1.2;
252 1679 : sdScale_p=1.0;
253 1679 : sdWeight_p=1.0;
254 1679 : sdConvSupport_p=-1;
255 :
256 1679 : doShift_p=false;
257 1679 : spectralwindowids_p.resize(1);
258 1679 : spectralwindowids_p=0;
259 1679 : fieldid_p=0;
260 1679 : dataspectralwindowids_p.resize(0);
261 1679 : datadescids_p.resize(0);
262 1679 : datafieldids_p.resize(0);
263 1679 : mImageStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
264 1679 : mImageStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
265 1679 : mDataStart_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
266 1679 : mDataStep_p=MRadialVelocity(Quantity(0.0, "km/s"), MRadialVelocity::LSRK);
267 1679 : beamValid_p=false;
268 1679 : beam_p = ImageBeamSet();
269 1679 : images_p.resize(0);
270 1679 : masks_p.resize(0);
271 1679 : fluxMasks_p.resize(0);
272 1679 : residuals_p.resize(0);
273 1679 : componentList_p=0;
274 :
275 1679 : cyclefactor_p = 1.5;
276 1679 : cyclespeedup_p = -1;
277 1679 : cyclemaxpsffraction_p = 0.8;
278 1679 : stoplargenegatives_p = 2;
279 1679 : stoppointmode_p = -1;
280 1679 : fluxscale_p.resize(0);
281 1679 : scaleType_p = "NONE";
282 1679 : minPB_p = 0.1;
283 1679 : constPB_p = 0.4;
284 1679 : redoSkyModel_p=true;
285 1679 : nmodels_p=0;
286 1679 : useModelCol_p=false;
287 1679 : freqFrameValid_p=false;
288 1679 : doTrackSource_p=false;
289 1679 : freqInterpMethod_p="nearest";
290 1679 : pointingDirCol_p="DIRECTION";
291 1679 : logSink_p=LogSink(LogMessage::NORMAL, false);
292 1679 : imwgt_p=VisImagingWeight();
293 1679 : smallScaleBias_p=0.6;
294 1679 : freqFrame_p=MFrequency::LSRK;
295 1679 : imageTileVol_p=0;
296 1679 : singlePrec_p=false;
297 1679 : spwchansels_p.resize();
298 1679 : flatnoise_p=true;
299 1679 : freqrange_p.resize();
300 1679 : numthreads_p=-1;
301 1679 : avoidTempLatt_p=false;
302 1679 : mssFreqSel_p.resize();
303 1679 : mssChanSel_p.resize();
304 1679 : projection_p=String("SIN");
305 :
306 1679 : }
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 2166 : Imager::~Imager()
432 : {
433 : try{
434 1679 : destroySkyEquation();
435 1679 : this->unlock(); //unlock things if they are in a locked state
436 :
437 : //if (mssel_p) {
438 : // delete mssel_p;
439 : // }
440 1679 : mssel_p = 0;
441 : //if (ms_p) {
442 : // delete ms_p;
443 : //}
444 1679 : ms_p = 0;
445 1679 : if (vs_p) {
446 0 : delete vs_p;
447 : }
448 1679 : if(rvi_p)
449 522 : delete rvi_p;
450 1679 : rvi_p=wvi_p=0;
451 :
452 1679 : vs_p = 0;
453 1679 : if (ft_p) {
454 165 : delete ft_p;
455 : }
456 :
457 :
458 1679 : ft_p = 0;
459 1679 : if (cft_p) {
460 192 : delete cft_p;
461 : }
462 1679 : 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 2166 : }
491 :
492 :
493 487 : Bool Imager::open(MeasurementSet& theMs, Bool /*compress*/, Bool useModelCol)
494 : {
495 :
496 974 : LogIO os(LogOrigin("Imager", "open()", WHERE));
497 :
498 487 : if (!ms_p.null()) {
499 0 : *ms_p = theMs;
500 : } else {
501 487 : ms_p = new MeasurementSet(theMs);
502 487 : AlwaysAssert(!ms_p.null(), AipsError);
503 : }
504 :
505 :
506 : try {
507 487 : this->openSubTables();
508 487 : this->lock();
509 487 : msname_p = ms_p->tableName();
510 :
511 487 : os << "Opening MeasurementSet " << msname_p << LogIO::POST;
512 :
513 : // Check for DATA or FLOAT_DATA column
514 1152 : if(!ms_p->tableDesc().isColumn("DATA") &&
515 665 : !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 487 : 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 487 : mssel_p=new MeasurementSet(*ms_p);
542 487 : useModelCol_p=useModelCol;
543 :
544 : // Now create the VisSet
545 487 : this->makeVisSet(*mssel_p);
546 487 : AlwaysAssert(rvi_p, AipsError);
547 :
548 : // Polarization
549 487 : MSColumns msc(*mssel_p);
550 487 : Vector<String> polType=msc.feed().polarizationType()(0);
551 619 : if (polType(0)!="X" && polType(0)!="Y" &&
552 619 : 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 487 : numMS_p=1;
559 :
560 487 : this->unlock();
561 :
562 487 : return true;
563 487 : } 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 487 : }
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 244 : IPosition Imager::imageshape() const
615 : {
616 244 : 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 150 : 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 150 : logSink_p.clearLocally();
842 300 : LogIO os(LogOrigin("imager", "defineimage()"), logSink_p);
843 150 : if(cellx.getValue() == 0.0 || celly.getValue()==0.0)
844 1 : throw(AipsError("Infinite resolution not possible... please do let us know what you are drinking"));
845 149 : os << LogIO::NORMAL << "Defining image properties:"; // Loglevel INFO
846 : os << "nx=" << nx << " ny=" << ny
847 298 : << " cellx='" << cellx.getValue() << cellx.getUnit()
848 298 : << "' 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 149 : << " frame=" << mFreqFrame
855 149 : << " distance='" << distance.getValue() << distance.getUnit() <<"'";
856 149 : os << LogIO::POST;
857 149 : ostringstream clicom;
858 149 : clicom << " phaseCenter='" ;
859 149 : if(fieldid < 0){
860 126 : MVAngle mvRA=phaseCenter.getAngle().getValue()(0);
861 126 : MVAngle mvDEC=phaseCenter.getAngle().getValue()(1);
862 126 : clicom << mvRA(0.0).string(MVAngle::TIME,8) << ", ";
863 126 : clicom << mvDEC(0.0).string(MVAngle::ANGLE_CLEAN,8) << ", ";
864 126 : }
865 : else{
866 23 : clicom << "field-" << fieldid<< " ";
867 : }
868 149 : clicom << "' mStart='" << mStart << "' qStep='" << qStep << "'";
869 149 : clicom << "' mFreqStart='" << mFreqStart;
870 149 : os << String(clicom);
871 149 : os << LogIO::POST;
872 :
873 : try {
874 :
875 149 : this->lock();
876 149 : this->writeCommand(os);
877 :
878 149 : doTrackSource_p=dotrackDir;
879 149 : 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 149 : 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 149 : nx_p=nx;
936 149 : ny_p=ny;
937 149 : mcellx_p=cellx;
938 149 : mcelly_p=celly;
939 149 : distance_p=distance;
940 149 : stokes_p=stokes;
941 149 : imageMode_p=mode;
942 149 : imageMode_p.upcase();
943 149 : imageNchan_p=nchan;
944 149 : imageStart_p=start;
945 149 : imageStep_p=step;
946 149 : if(mode.contains("VEL")){
947 3 : mImageStart_p=mStart;
948 3 : mImageStep_p=MRadialVelocity(qStep);
949 : }
950 149 : if(mode.contains("FREQ")){
951 4 : mfImageStart_p=mFreqStart;
952 4 : mfImageStep_p=MFrequency(qStep);
953 : }
954 149 : restFreq_p=restFreq;
955 149 : freqFrame_p=mFreqFrame;
956 149 : spectralwindowids_p.resize(spectralwindowids.nelements());
957 149 : spectralwindowids_p=spectralwindowids;
958 149 : fieldid_p=fieldid;
959 149 : facets_p=facets;
960 149 : redoSkyModel_p=true;
961 149 : destroySkyEquation();
962 :
963 : // Now make the derived quantities
964 149 : Vector<Int> whichStokes = decideNPolPlanes(false);
965 149 : if( whichStokes.nelements()==1 && whichStokes[0]==0 )
966 : {
967 1 : this->unlock();
968 1 : 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 148 : nchan_p=imageNchan_p;
974 :
975 148 : if(fieldid < 0){
976 125 : doShift_p=true;
977 125 : phaseCenter_p=phaseCenter;
978 : }
979 : else {
980 23 : MSFieldColumns msfield(ms_p->field());
981 23 : phaseCenter_p=msfield.phaseDirMeas(fieldid_p);
982 23 : }
983 :
984 : // we only support projections SIN, CAR, TAN, and SFL
985 148 : Projection::Type const ptype = Projection::type(projection);
986 148 : if (ptype != Projection::SIN && ptype != Projection::CAR
987 2 : && 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 148 : projection_p = projection;
993 : }
994 :
995 :
996 : // Now we have set the image parameters
997 148 : setimaged_p=true;
998 148 : beamValid_p=false;
999 :
1000 148 : this->unlock();
1001 :
1002 :
1003 148 : return true;
1004 150 : } catch (AipsError x) {
1005 1 : this->unlock();
1006 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1007 1 : << LogIO::EXCEPTION;
1008 0 : return false;
1009 2 : }
1010 : return true;
1011 151 : }
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 426 : 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 852 : LogIO os(LogOrigin("imager", "setdata()"), logSink_p);
1243 426 : 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 426 : MRadialVelocity dummy;
1258 : //Calling the old setdata
1259 426 : return setdata(mode, nchan, start, step, dummy, dummy, spectralwindowids,
1260 : fieldids, msSelect, timerng, fieldnames, antIndex,
1261 852 : antnames, spwstring, uvdist, scan, intent, obs, useModelCol);
1262 :
1263 426 : }
1264 :
1265 :
1266 550 : 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 550 : logSink_p.clearLocally();
1282 1100 : LogIO os(LogOrigin("imager", "data selection"), logSink_p);
1283 :
1284 550 : 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 550 : << " start=" << start << " step=" << step;
1294 550 : ostringstream clicom;
1295 550 : clicom << " mstart='" << mStart << "' mstep='" << mStep;
1296 550 : os << String(clicom) ;
1297 : os << "' spectralwindowids=" << spectralwindowids
1298 550 : << " fieldids=" << fieldids << " msselect=" << msSelect;
1299 :
1300 550 : nullSelect_p=false;
1301 550 : String local_spwstring(spwstring);
1302 550 : if (local_spwstring == "") local_spwstring="*";
1303 : try {
1304 :
1305 550 : this->lock();
1306 550 : this->writeCommand(os);
1307 :
1308 : os << (be_calm ? LogIO::NORMAL2 : LogIO::NORMAL)
1309 1100 : << "Performing selection on MeasurementSet : " << ms_p->tableName()
1310 550 : << LogIO::POST; // Loglevel PROGRESS
1311 : //Some MSSelection
1312 550 : 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 550 : datafieldids_p.resize(fieldids.nelements());
1323 550 : datafieldids_p = fieldids;
1324 550 : if(datafieldids_p.nelements() > 0){
1325 124 : thisSelection.setFieldExpr(MSSelection::indexExprStr(datafieldids_p));
1326 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1327 124 : << "Selecting on field ids : " << datafieldids_p << LogIO::POST;
1328 : }
1329 550 : if(fieldnames != ""){
1330 80 : thisSelection.setFieldExpr(fieldnames);
1331 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1332 80 : << "Selecting on fields : " << fieldnames << LogIO::POST;
1333 : }
1334 :
1335 550 : dataspectralwindowids_p.resize(spectralwindowids.nelements());
1336 550 : dataspectralwindowids_p = spectralwindowids;
1337 550 : if(dataspectralwindowids_p.nelements() > 0){
1338 124 : thisSelection.setSpwExpr(MSSelection::indexExprStr(dataspectralwindowids_p));
1339 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1340 124 : << "Selecting on spectral windows" << LogIO::POST;
1341 : }
1342 426 : else if(local_spwstring != ""){
1343 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1344 : << "Selecting on spectral windows expression : " << local_spwstring
1345 426 : << LogIO::POST;
1346 426 : thisSelection.setSpwExpr(local_spwstring);
1347 : }
1348 :
1349 550 : 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 550 : if(antnames != ""){
1355 157 : Vector<String>antNames(1, antnames);
1356 : // thisSelection.setAntennaExpr(MSSelection::nameExprStr(antNames));
1357 157 : thisSelection.setAntennaExpr(antnames);
1358 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1359 157 : << "Selecting on antenna names : " << antnames << LogIO::POST;
1360 157 : }
1361 :
1362 550 : if(timerng != ""){
1363 : // Vector<String>timerange(1, timerng);
1364 5 : thisSelection.setTimeExpr(timerng);
1365 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1366 5 : << "Selecting on time range : " << timerng << LogIO::POST;
1367 : }
1368 :
1369 550 : 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 550 : if(scan != ""){
1376 28 : thisSelection.setScanExpr(scan);
1377 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1378 28 : << "Selecting on scan : " << scan << LogIO::POST;
1379 : }
1380 550 : if(intent != "") {
1381 122 : thisSelection.setStateExpr(intent);
1382 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1383 122 : << "Selecting on State Expr : " << intent << LogIO::POST;
1384 : }
1385 550 : if(obs != ""){
1386 7 : thisSelection.setObservationExpr(obs);
1387 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1388 7 : << "Selecting on Observation Expr : " << obs << LogIO::POST;
1389 : }
1390 550 : 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 550 : TableExprNode exprNode;
1398 : try{
1399 550 : 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 550 : if(ft_p)
1418 73 : delete ft_p;
1419 550 : ft_p=0;
1420 550 : dataMode_p=mode;
1421 550 : dataNchan_p.resize();
1422 550 : dataStart_p.resize();
1423 550 : dataStep_p.resize();
1424 550 : dataNchan_p=nchan;
1425 550 : dataStart_p=start;
1426 550 : dataStep_p=step;
1427 550 : mDataStart_p=mStart;
1428 550 : mDataStep_p=mStep;
1429 : // useModelCol_p=useModelCol;
1430 :
1431 550 : if(rvi_p)
1432 550 : delete rvi_p;
1433 550 : rvi_p=0;
1434 550 : wvi_p=0;
1435 : // if(mssel_p) delete mssel_p;
1436 550 : mssel_p=0;
1437 :
1438 550 : datafieldids_p.resize();
1439 550 : datafieldids_p=thisSelection.getFieldList();
1440 550 : if(datafieldids_p.nelements()==0){
1441 346 : Int nf=ms_p->field().nrow();
1442 346 : datafieldids_p.resize(nf);
1443 346 : 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 550 : Matrix<Int> chansels=thisSelection.getChanList(NULL, 1, true);
1455 550 : mssChanSel_p.assign(chansels);
1456 550 : mssFreqSel_p.resize();
1457 550 : mssFreqSel_p=thisSelection.getChanFreqList(NULL, true);
1458 :
1459 : //cout<<"chansels="<<chansels<<endl;
1460 : //convert the selection into flag
1461 550 : uInt nms = 1;
1462 550 : uInt nrow = chansels.nrow();
1463 550 : dataspectralwindowids_p.resize();
1464 550 : const MSSpWindowColumns spwc(ms_p->spectralWindow());
1465 550 : uInt nspw = spwc.nrow();
1466 550 : const ScalarColumn<Int> spwNchans(spwc.numChan());
1467 550 : Vector<Int> nchanvec = spwNchans.getColumn();
1468 550 : Int maxnchan = 0;
1469 3027 : for (uInt i=0;i<nchanvec.nelements();i++) {
1470 2477 : maxnchan=max(nchanvec[i],maxnchan);
1471 : }
1472 :
1473 550 : spwchansels_p.resize(nms,nspw,maxnchan);
1474 550 : spwchansels_p.set(0);
1475 550 : uInt nselspw=0;
1476 550 : 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 550 : spwchansels_p=0; //deselect
1483 550 : Int prvspwid=-1;
1484 550 : Vector<Int> selspw;
1485 1375 : for (uInt i=0;i<nrow;i++) {
1486 825 : Vector<Int> sel = chansels.row(i);
1487 825 : Int spwid = sel[0];
1488 825 : if((sel[1] >= nchanvec[spwid]) || (sel[2] >=nchanvec[spwid]))
1489 0 : throw(AipsError("Unexpected selection in spw selection of spwid "+String::toString(spwid)));
1490 825 : if (spwid != prvspwid){
1491 797 : nselspw++;
1492 797 : selspw.resize(nselspw,true);
1493 797 : selspw[nselspw-1]=spwid;
1494 : }
1495 825 : uInt minc= sel[1];
1496 825 : uInt maxc = sel[2];
1497 825 : uInt step = sel[3];
1498 : // step as the same context as in im.selectvis
1499 : // select channels
1500 340401 : for (uInt k=minc;k<(maxc+1);k+=step) {
1501 339576 : spwchansels_p(0,spwid,k)=1;
1502 : }
1503 825 : prvspwid=spwid;
1504 825 : }
1505 550 : dataspectralwindowids_p=selspw;
1506 550 : }
1507 :
1508 : // Map the selected spectral window ids to data description ids
1509 550 : 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 550 : MSDataDescIndex msDatIndex(ms_p->dataDescription());
1515 550 : datadescids_p.resize(0);
1516 550 : datadescids_p=msDatIndex.matchSpwId(dataspectralwindowids_p);
1517 :
1518 550 : if (datafieldids_p.nelements() > 1) {
1519 126 : os << LogIO::NORMAL4<< "Multiple fields specified" << LogIO::POST;
1520 126 : multiFields_p = true;
1521 : }
1522 :
1523 :
1524 550 : 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 463 : if(nselspw==dataspectralwindowids_p.nelements()){
1533 :
1534 463 : dataMode_p="channel";
1535 463 : dataStep_p.resize(dataspectralwindowids_p.nelements());
1536 463 : dataStart_p.resize(dataspectralwindowids_p.nelements());
1537 463 : dataNchan_p.resize(dataspectralwindowids_p.nelements());
1538 463 : Cube<Int> spwchansels_tmp=spwchansels_p;
1539 :
1540 1173 : for (uInt k =0 ; k < dataspectralwindowids_p.nelements(); ++k){
1541 710 : uInt curspwid=dataspectralwindowids_p[k];
1542 : //dataStep_p[k]=1;
1543 710 : if (nrow > 0) {
1544 710 : 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 710 : dataStart_p[k]=0;
1551 710 : dataNchan_p[k]=nchanvec(curspwid);
1552 : //find start
1553 710 : Bool first =true;
1554 710 : uInt nchn = 0;
1555 710 : uInt lastchan = 0;
1556 290175 : for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++) {
1557 289465 : if (spwchansels_p(0,curspwid,j)==1) {
1558 289153 : if (first) {
1559 710 : dataStart_p[k]=j;
1560 710 : first = false;
1561 : }
1562 289153 : lastchan=j;
1563 289153 : nchn++;
1564 : }
1565 : }
1566 710 : 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 290175 : for (uInt j=0 ; j < uInt(nchanvec(curspwid)); j++){
1579 289465 : if ( Int(j) < nchanvec(curspwid)-dataStart_p[k]) {
1580 289309 : spwchansels_tmp(0,curspwid,j) = spwchansels_p(0,curspwid,j+dataStart_p[k]);
1581 : }
1582 : else {
1583 156 : spwchansels_tmp(0,curspwid,j) = 0;
1584 : }
1585 : }
1586 : }
1587 463 : spwchansels_p = spwchansels_tmp;
1588 463 : }
1589 : }
1590 550 : if(!(exprNode.isNull())){
1591 550 : 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 550 : AlwaysAssert(!mssel_p.null(), AipsError);
1599 550 : if(mssel_p->nrow()==0) {
1600 : //delete mssel_p;
1601 19 : mssel_p=0;
1602 : os << (be_calm ? LogIO::NORMAL4 : LogIO::WARN)
1603 : << "Selection is empty: reverting to sorted MeasurementSet"
1604 19 : << LogIO::POST;
1605 19 : mssel_p=new MeasurementSet(*ms_p);
1606 19 : nullSelect_p=true;
1607 : }
1608 : else {
1609 531 : mssel_p->flush();
1610 531 : nullSelect_p=false;
1611 : }
1612 550 : if (nullSelect_p) {
1613 19 : if ((mssel_p->field()).nrow() > 1) {
1614 18 : os << LogIO::NORMAL4 << "Multiple fields selected" << LogIO::POST;
1615 18 : multiFields_p = true;
1616 : } else {
1617 1 : os << LogIO::NORMAL4 << "Single field selected" << LogIO::POST;
1618 1 : multiFields_p = false;
1619 : }
1620 : }
1621 :
1622 550 : uInt nvis_all = ms_p->nrow();
1623 :
1624 : // Now create the VisSet
1625 550 : this->makeVisSet(*mssel_p);
1626 550 : AlwaysAssert(rvi_p, AipsError);
1627 550 : uInt nvis_sel = mssel_p->nrow();
1628 :
1629 550 : if(nvis_sel != nvis_all) {
1630 : os << LogIO::NORMAL // Loglevel INFO
1631 : << "Selected " << nvis_sel << " out of "
1632 : << nvis_all << " rows."
1633 254 : << LogIO::POST;
1634 : }
1635 : else {
1636 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL)
1637 296 : << "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 550 : Vector<Int> chancounts(dataspectralwindowids_p.nelements());
1644 550 : chancounts=0;
1645 : // if( local_spwstring == "" ) os << "Selected all spws and channels" << LogIO::POST;
1646 : //else os << "Channel selection : " << local_spwstring << LogIO::POST;
1647 550 : os << (be_calm ? LogIO::NORMAL4 : LogIO::NORMAL) << "Selected:";
1648 1347 : for(uInt k=0;k<dataspectralwindowids_p.nelements();k++)
1649 : {
1650 340655 : for(uInt ch=0;ch<uInt(nchanvec(dataspectralwindowids_p[k]));ch++)
1651 339858 : {if(spwchansels_p(0,dataspectralwindowids_p[k],ch)) chancounts[k]++; }
1652 797 : 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 550 : os << LogIO::POST;
1657 :
1658 : // Now we do a selection to cut down the amount of information
1659 : // passed around.
1660 :
1661 550 : this->selectDataChannel(dataspectralwindowids_p, dataMode_p,
1662 550 : dataNchan_p, dataStart_p, dataStep_p,
1663 550 : mDataStart_p, mDataStep_p);
1664 : ///Tell iterator to use on the fly imaging weights if scratch columns is
1665 : ///not in use
1666 550 : imwgt_p=VisImagingWeight("natural");
1667 550 : rvi_p->useImagingWeight(imwgt_p);
1668 :
1669 : // Guess that the beam is no longer valid
1670 550 : beamValid_p=false;
1671 550 : destroySkyEquation();
1672 550 : 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 550 : this->unlock();
1679 550 : return !nullSelect_p;
1680 550 : } catch (AipsError x) {
1681 0 : this->unlock();
1682 0 : throw(x);
1683 :
1684 : return false;
1685 0 : }
1686 : return !nullSelect_p;
1687 550 : }
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 125 : 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 250 : LogIO os(LogOrigin("Imager", "setvp()", WHERE));
1728 :
1729 125 : os << LogIO::NORMAL << "Setting voltage pattern parameters" << LogIO::POST; // Loglevel PROGRESS
1730 :
1731 125 : if(!dovp && !vp_p)
1732 0 : delete vp_p;
1733 125 : vp_p=0;
1734 125 : doVP_p=dovp;
1735 125 : doDefaultVP_p = doDefaultVPs;
1736 125 : vpTableStr_p = vpTable;
1737 125 : telescope_p= defaultTel;
1738 125 : if (doSquint) {
1739 0 : squintType_p = BeamSquint::GOFIGURE;
1740 : } else {
1741 125 : squintType_p = BeamSquint::NONE;
1742 : }
1743 :
1744 125 : parAngleInc_p = parAngleInc;
1745 :
1746 125 : skyPosThreshold_p = skyPosThreshold;
1747 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1748 : <<"Sky position tolerance is "<<skyPosThreshold_p.getValue("deg")
1749 125 : << " degrees" << LogIO::POST;
1750 :
1751 125 : if (doDefaultVP_p) {
1752 : os << (verbose ? LogIO::NORMAL : LogIO::NORMAL3) // Loglevel INFO
1753 125 : << "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 125 : 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 125 : destroySkyEquation();
1769 125 : return true;
1770 125 : }
1771 :
1772 122 : 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 122 : if(!valid())
1792 : {
1793 0 : return false;
1794 : }
1795 122 : if(!assertDefinedImageParameters())
1796 : {
1797 0 : return false;
1798 : }
1799 244 : LogIO os(LogOrigin("imager", "setoptions()", WHERE));
1800 :
1801 122 : os << LogIO::NORMAL << "Setting processing options" << LogIO::POST; // Loglevel PROGRESS
1802 :
1803 122 : ftmachine_p=downcase(ftmachine);
1804 122 : 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 122 : if(ftmachine_p=="wfmemoryft"){
1812 0 : wfGridding_p=true;
1813 0 : ftmachine_p="ft";
1814 : }
1815 :
1816 122 : wprojPlanes_p=wprojplanes;
1817 122 : epJTableName_p = epJTableName;
1818 122 : cfCacheDirName_p = cfCacheDirName;
1819 122 : rotPAStep_p = rotPAStep;
1820 122 : computePAStep_p = computePAStep;
1821 122 : pbLimit_p = pbLimit;
1822 122 : psTermOn_p=psTermOn;
1823 122 : aTermOn_p=aTermOn;
1824 122 : mTermOn_p=mTermOn;
1825 122 : wbAWP_p=wbawp;
1826 122 : conjBeams_p=conjBeams;
1827 122 : freqInterpMethod_p=interpMeth;
1828 122 : imageTileVol_p=imageTileVol;
1829 122 : if(imageTileVol_p <= 0){
1830 122 : avoidTempLatt_p=true;
1831 122 : imageTileVol_p=-1*imageTileVol_p;
1832 : }
1833 :
1834 :
1835 122 : singlePrec_p=singprec;
1836 :
1837 122 : if(cache>0) cache_p=cache;
1838 122 : if(tile>0) tile_p=tile;
1839 122 : gridfunction_p=downcase(gridfunction);
1840 122 : mLocation_p=mLocation;
1841 122 : if(padding>=1.0) {
1842 122 : padding_p=padding;
1843 : }
1844 :
1845 : // Check if gridfunction is set to gauss or gjinc for non single dish imaging
1846 122 : if (ftmachine_p!="sd"
1847 122 : && (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 122 : if(ft_p) {delete ft_p; ft_p=0;}
1854 122 : if(gvp_p) {delete gvp_p; gvp_p=0;}
1855 122 : if(cft_p) {delete cft_p; cft_p=0;}
1856 :
1857 122 : doPointing = applyPointingOffsets;
1858 122 : 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 122 : numthreads_p= numthreads;
1863 : #ifdef _OPENMP
1864 122 : if(numthreads > 0){
1865 0 : if(numthreads <= omp_get_max_threads()){
1866 0 : omp_set_num_threads(numthreads);
1867 : }
1868 : }
1869 : #endif
1870 122 : return true;
1871 122 : }
1872 :
1873 235 : 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 470 : LogIO os(LogOrigin("imager", "setsdoptions()", WHERE));
1882 :
1883 235 : os << LogIO::NORMAL << "Setting single dish processing options" << LogIO::POST; // Loglevel PROGRESS
1884 :
1885 235 : sdScale_p=scale;
1886 235 : sdWeight_p=weight;
1887 :
1888 :
1889 235 : sdConvSupport_p=convsupport;
1890 235 : pointingDirCol_p=pointCol;
1891 235 : pointingDirCol_p.upcase();
1892 235 : 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 235 : qtruncate_p=truncate;
1898 235 : qgwidth_p=gwidth;
1899 235 : qjwidth_p=jwidth;
1900 235 : minWeight_p = minweight;
1901 235 : clipminmax_p = clipminmax;
1902 235 : enablecache_p = enablecache;
1903 235 : convertfirst_p = convertfirst;
1904 235 : convertfirst_p.upcase();
1905 :
1906 :
1907 : // Destroy the FTMachine
1908 235 : if(ft_p) {delete ft_p; ft_p=0;}
1909 235 : if(gvp_p) {delete gvp_p; gvp_p=0;}
1910 235 : if(cft_p) {delete cft_p; cft_p=0;}
1911 :
1912 235 : return true;
1913 235 : }
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 14 : Bool Imager::regionToImageMask(const String& maskimage, Record* imageRegRec, Matrix<Quantity>& blctrcs, Matrix<Float>& circles, const Float& value){
2029 14 : PagedImage<Float> maskImage(maskimage);
2030 14 : CoordinateSystem cSys=maskImage.coordinates();
2031 14 : maskImage.table().markForDelete();
2032 14 : ImageRegion *boxregions=0;
2033 14 : ImageRegion *circleregions=0;
2034 14 : RegionManager regMan;
2035 14 : regMan.setcoordsys(cSys);
2036 14 : Vector<Quantum<Double> > blc(2);
2037 14 : Vector<Quantum<Double> > trc(2);
2038 14 : 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 14 : if((circles.nelements()) > 0){
2057 6 : if(circles.shape()(1) != 3)
2058 0 : throw(AipsError("Need a list of 3 elements to define a circle"));
2059 6 : Int nrow=circles.shape()(0);
2060 6 : Vector<Float> cent(2);
2061 6 : cent(0)=circles(0,1); cent(1)=circles(0,2);
2062 6 : Float radius=circles(0,0);
2063 12 : IPosition xyshape(2,maskImage.shape()(0),maskImage.shape()(1));
2064 6 : LCEllipsoid *circ= new LCEllipsoid(cent, radius, xyshape);
2065 : //Tell LCUnion to delete the pointers
2066 6 : LCUnion *elunion= new LCUnion(true, circ);
2067 : //now lets do the remainder
2068 6 : 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 6 : IPosition trc(2);
2076 6 : trc(0)=maskImage.shape()(2)-1;
2077 6 : trc(1)=maskImage.shape()(3)-1;
2078 12 : LCBox lbox(IPosition(2,0,0), trc,
2079 18 : IPosition(2,maskImage.shape()(2),maskImage.shape()(3)) );
2080 6 : LCExtension linter(*elunion, IPosition(2,2,3),lbox);
2081 6 : circleregions=new ImageRegion(linter);
2082 6 : delete elunion;
2083 6 : }
2084 :
2085 :
2086 14 : ImageRegion* recordRegion=0;
2087 14 : if(imageRegRec !=0){
2088 8 : TableRecord rec1;
2089 8 : rec1.assign(*imageRegRec);
2090 8 : recordRegion=ImageRegion::fromRecord(rec1,"");
2091 8 : }
2092 14 : ImageRegion *unionReg=0;
2093 14 : 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 14 : else if(boxregions !=0){
2099 0 : unionReg=boxregions;
2100 : }
2101 14 : else if(recordRegion !=0){
2102 8 : unionReg=recordRegion;
2103 : }
2104 :
2105 :
2106 :
2107 :
2108 14 : if(unionReg !=0){
2109 8 : regionToMask(maskImage, *unionReg, value);
2110 8 : delete unionReg; unionReg=0;
2111 : }
2112 : //As i can't unionize LCRegions and WCRegions; do circles seperately
2113 14 : if(circleregions !=0){
2114 6 : regionToMask(maskImage, *circleregions, value);
2115 6 : delete circleregions;
2116 6 : circleregions=0;
2117 : }
2118 14 : maskImage.table().unmarkForDelete();
2119 14 : return true;
2120 :
2121 14 : }
2122 :
2123 :
2124 14 : Bool Imager::regionToMask(ImageInterface<Float>& maskImage, ImageRegion& imagreg, const Float& value){
2125 :
2126 :
2127 14 : SubImage<Float> partToMask(maskImage, imagreg, true);
2128 14 : LatticeRegion latReg=imagreg.toLatticeRegion(maskImage.coordinates(), maskImage.shape());
2129 14 : ArrayLattice<Bool> pixmask(latReg.get());
2130 28 : LatticeExpr<Float> myexpr(iif(pixmask, value, partToMask) );
2131 14 : partToMask.copyData(myexpr);
2132 :
2133 14 : return true;
2134 14 : }
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 113 : 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 113 : Float effDiam=effDishDiam;
2177 113 : LoggerHolder lh (false);
2178 113 : LogIO os = lh.logio();
2179 113 : os << LogOrigin("imager", "feather()");
2180 :
2181 : try {
2182 113 : Bool noStokes=false;
2183 113 : String outLowRes=lowRes;
2184 113 : String outHighRes=highRes;
2185 : {
2186 113 : 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 113 : << "\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 113 : PagedImage<Float> high(outHighRes);
2233 113 : PagedImage<Float> low0(outLowRes);
2234 :
2235 113 : Feather::feather(image, high, low0, sdScale_p, lowPSF, doDefaultVP_p, vpTableStr_p, effDiam, lowPassFilterSD);
2236 114 : }
2237 :
2238 112 : if(noStokes){
2239 0 : TableUtil::deleteTable(outHighRes);
2240 0 : TableUtil::deleteTable(outLowRes);
2241 : }
2242 112 : return true;
2243 115 : } catch (AipsError x) {
2244 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2245 1 : << LogIO::EXCEPTION;
2246 0 : return false;
2247 2 : }
2248 :
2249 : return true;
2250 114 : }
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 256 : Bool Imager::makeimage(const String& type, const String& image,
2873 : const String& compleximage, const Bool verbose)
2874 : {
2875 256 : if(!valid())
2876 : {
2877 0 : return false;
2878 : }
2879 512 : LogIO os(LogOrigin("imager", "makeimage()", WHERE));
2880 :
2881 256 : this->lock();
2882 : try {
2883 256 : if(!assertDefinedImageParameters())
2884 : {
2885 0 : return false;
2886 : }
2887 :
2888 : os << LogIO::NORMAL // Loglevel INFO
2889 256 : << "Calculating image (without full skyequation)" << LogIO::POST;
2890 :
2891 256 : FTMachine::Type seType(FTMachine::OBSERVED);
2892 256 : Bool doSD(false);
2893 :
2894 256 : 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 256 : 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 256 : 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 256 : else if (type=="psf") {
2913 0 : seType=FTMachine::PSF;
2914 : os << "Making point spread function "
2915 0 : << LogIO::POST;
2916 : }
2917 256 : 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 256 : 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 256 : else if (type=="singledish") {
2930 122 : doSD = true;
2931 122 : seType=FTMachine::CORRECTED;
2932 : os << LogIO::NORMAL // Loglevel INFO
2933 122 : << "Making single dish image from corrected data" << LogIO::POST;
2934 : }
2935 134 : else if (type=="coverage") {
2936 122 : doSD = true;
2937 122 : seType=FTMachine::COVERAGE;
2938 : os << LogIO::NORMAL // Loglevel PROGRESS
2939 : << "Making single dish coverage function "
2940 122 : << LogIO::POST;
2941 : }
2942 12 : 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 12 : 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 12 : else if (type=="pb"){
2957 12 : 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 12 : CoordinateSystem coordsys;
2970 : //imagecoordinates(coordsys, verbose);
2971 12 : imagecoordinates2(coordsys, verbose);
2972 12 : if (doDefaultVP_p) {
2973 12 : 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 12 : telescope_p=coordsys.obsInfo().telescope();
2981 : }
2982 12 : this->unlock();
2983 12 : MSAntennaColumns ac(ms_p->antenna());
2984 12 : Double dishDiam=ac.dishDiameter()(0);
2985 12 : 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 12 : return this->makePBImage(coordsys, telescope_p, image, false, dishDiam);
2990 12 : }
2991 : else{
2992 0 : Table vpTable(vpTableStr_p);
2993 0 : this->unlock();
2994 0 : return this->makePBImage(coordsys, vpTable, image);
2995 0 : }
2996 :
2997 12 : }
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 244 : 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 244 : String imageName(image);
3014 244 : if(image=="") {
3015 0 : imageName=Imager::imageName()+".image";
3016 : }
3017 244 : os << LogIO::NORMAL << "Image is : " << imageName << LogIO::POST; // Loglevel INFO
3018 244 : Bool keepImage=(image!="");
3019 244 : Bool keepComplexImage=(compleximage!="")||(type=="holography")||(type=="holography-observed");
3020 244 : String cImageName(compleximage);
3021 :
3022 244 : if(compleximage=="") {
3023 244 : cImageName=imageName+".compleximage";
3024 : }
3025 :
3026 244 : if(keepComplexImage) {
3027 0 : os << "Retaining complex image: " << compleximage << LogIO::POST;
3028 : }
3029 :
3030 244 : CoordinateSystem imagecoords;
3031 : //if(!imagecoordinates(imagecoords, false))
3032 244 : if(!imagecoordinates2(imagecoords, false))
3033 : {
3034 0 : return false;
3035 : }
3036 244 : make(imageName);
3037 244 : PagedImage<Float> imageImage(imageName);
3038 244 : imageImage.set(0.0);
3039 244 : imageImage.table().markForDelete();
3040 :
3041 : // Now set up the tile size, here we guess only
3042 244 : IPosition cimageShape(imageshape());
3043 244 : Int tilex=32;
3044 244 : 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 488 : IPosition tileShape(4, min(tilex, cimageShape(0)), min(tilex, cimageShape(1)),
3060 732 : min(4, cimageShape(2)), min(32, cimageShape(3)));
3061 244 : CoordinateSystem cimagecoords;
3062 : //if(!imagecoordinates(cimagecoords, false))
3063 244 : if(!imagecoordinates2(cimagecoords, false))
3064 : {
3065 0 : return false;
3066 : }
3067 :
3068 :
3069 :
3070 244 : PagedImage<Complex> cImageImage(TiledShape(cimageShape, tileShape),
3071 : cimagecoords,
3072 244 : cImageName);
3073 244 : cImageImage.set(Complex(0.0));
3074 244 : cImageImage.setMaximumCacheSize(cache_p/2);
3075 244 : cImageImage.table().markForDelete();
3076 : //
3077 : // Add the distance to the object: this is not nice. We should define the
3078 : // coordinates properly.
3079 : //
3080 244 : Record info(imageImage.miscInfo());
3081 244 : info.define("distance", distance_p.get("m").getValue());
3082 244 : cImageImage.setMiscInfo(info);
3083 :
3084 :
3085 244 : String ftmachine(ftmachine_p);
3086 244 : if (!ft_p)
3087 122 : createFTMachine();
3088 :
3089 : os << LogIO::DEBUG1 << "FTMachine is : " << ftmachine
3090 244 : << " (" << ft_p << ")" << LogIO::POST;
3091 :
3092 :
3093 : // Now make the required image
3094 244 : Matrix<Float> weight;
3095 244 : ft_p->makeImage(seType, *rvi_p, cImageImage, weight);
3096 244 : StokesImageUtil::To(imageImage, cImageImage);
3097 : //
3098 : // Dirty way to set the proper unit to SD image
3099 : //
3100 244 : String msunit("");
3101 244 : String imunit;
3102 244 : if ( ms_p->tableDesc().isColumn("DATA") ){
3103 124 : msunit = ms_p->columnUnit(MS::DATA);
3104 124 : if (msunit == String("")) {
3105 124 : ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("DATA"));
3106 124 : if (dataColDesc.keywordSet().isDefined("UNIT"))
3107 0 : msunit = dataColDesc.keywordSet().asString("UNIT");
3108 124 : }
3109 120 : } else if ( ms_p->tableDesc().isColumn("FLOAT_DATA")) {
3110 120 : msunit = ms_p->columnUnit(MS::FLOAT_DATA);
3111 120 : if (msunit == String("")) {
3112 120 : ColumnDesc dataColDesc(ms_p->tableDesc().columnDesc("FLOAT_DATA"));
3113 120 : if (dataColDesc.keywordSet().isDefined("UNIT"))
3114 56 : msunit = dataColDesc.keywordSet().asString("UNIT");
3115 120 : }
3116 : }
3117 244 : msunit.upcase();
3118 244 : if (msunit == String("K"))
3119 56 : imunit = "K";
3120 : else
3121 188 : imunit = "Jy/beam";
3122 244 : imageImage.setUnits(Unit(imunit));
3123 244 : cImageImage.setUnits(Unit(imunit));
3124 : // imageImage.setUnits(Unit("Jy/beam"));
3125 : // cImageImage.setUnits(Unit("Jy/beam"));
3126 :
3127 244 : if(keepImage) {
3128 244 : imageImage.table().unmarkForDelete();
3129 : }
3130 244 : if(keepComplexImage) {
3131 0 : cImageImage.table().unmarkForDelete();
3132 : }
3133 244 : this->unlock();
3134 244 : return true;
3135 244 : } 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 256 : }
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 110 : Bool Imager::ft(const Vector<String>& model, const String& complist,
4305 : const Bool incremental, const Double phaseCenTime)
4306 : {
4307 110 : if(!valid()) return false;
4308 :
4309 220 : LogIO os(LogOrigin("imager", "ft()", WHERE));
4310 :
4311 110 : if (wvi_p==NULL)
4312 0 : os << LogIO::WARN << "Please make sure MS is writable when using Imager::ft" << LogIO::EXCEPTION;
4313 :
4314 110 : this->lock();
4315 : try {
4316 :
4317 110 : 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 220 : << String("Fourier transforming: ") +
4327 440 : (incremental ? String("adding to "): String("replacing "))+
4328 330 : (useModelCol_p ? String("MODEL_DATA column") : String("visibility model header")) << LogIO::POST;
4329 :
4330 110 : if (redoSkyModel_p){
4331 110 : if(!createSkyEquation(model, complist)) return false;
4332 : }
4333 110 : if(incremental){
4334 2 : for (Int mod=0; mod < (sm_p->numberOfModels()); ++mod){
4335 1 : (sm_p->deltaImage(mod)).copyData(sm_p->image(mod));
4336 : }
4337 : }
4338 110 : se_p->setPhaseCenterTime(phaseCenTime);
4339 110 : se_p->predict(incremental);
4340 :
4341 : // destroySkyEquation();
4342 :
4343 110 : this->unlock();
4344 110 : 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 110 : }
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 33 : 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 33 : Record retval;
4586 33 : if(!valid()) {
4587 0 : retval.define("process",false);
4588 0 : return retval;
4589 : }
4590 :
4591 33 : logSink_p.clearLocally();
4592 66 : LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
4593 33 : this->lock();
4594 :
4595 : // user specified flux densities (IQUV), global to the spws and fields
4596 33 : Vector<Double> fluxdens = fluxDensity;
4597 33 : if(fluxDensity.nelements() < 4){
4598 25 : fluxdens.resize(4,true);
4599 100 : for(Int i = fluxDensity.nelements(); i < 4; ++i)
4600 75 : fluxdens[i] = 0.0;
4601 : }
4602 :
4603 33 : Vector<String> tempCLs;
4604 33 : TempImage<Float> *tmodimage(NULL);
4605 :
4606 : try{
4607 33 : Bool precompute = fluxdens[0] < 0.0;
4608 :
4609 : // Figure out which fields/spws to treat
4610 : // including intent info
4611 33 : MSSelection mssel;
4612 33 : mssel.setFieldExpr(fieldnames);
4613 33 : mssel.setSpwExpr(spwstring);
4614 33 : mssel.setStateExpr(intentstr);
4615 33 : TableExprNode exprNode = mssel.toTableExprNode(&(*ms_p));
4616 : //Vector<Int> fldids;
4617 33 : Vector<Int> fldids(mssel.getFieldList());
4618 33 : Vector<Int> selToRawSpwIds(mssel.getSpwList());
4619 : // if intent is given try to do AND with fieldIds
4620 33 : if (intentstr!="") {
4621 1 : mssel_p = new MeasurementSet((*ms_p)(exprNode), &(*ms_p));
4622 1 : MSColumns tmpmsc(*mssel_p);
4623 1 : Vector<Int> fldidv=tmpmsc.fieldId().getColumn();
4624 1 : if (fldidv.nelements()==0)
4625 0 : throw(AipsError("No field ids were selected, please check input parameters"));
4626 2 : std::set<Int> ufldids(fldidv.begin(),fldidv.end());
4627 1 : std::vector<Int> tmpv(ufldids.begin(), ufldids.end());
4628 1 : fldids.resize(tmpv.size());
4629 1 : uInt count=0;
4630 2 : for (std::vector<int>::const_iterator it=tmpv.begin();it != tmpv.end(); it++)
4631 : {
4632 1 : fldids(count) = *it;
4633 1 : count++;
4634 : }
4635 1 : }
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 33 : expand_blank_sel(selToRawSpwIds, ms_p->spectralWindow().nrow());
4648 33 : expand_blank_sel(fldids, ms_p->field().nrow());
4649 :
4650 : // Warn against multiple fields in some circumstances.
4651 33 : 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 33 : os << LogIO::NORMAL;
4673 33 : if(precompute || spix[0] != 0.0)
4674 11 : os << "Using " << ((chanDep || (!precompute && spix[0] != 0.0)) ? "channel" :
4675 41 : "spw") << " dependent flux densities";
4676 : else
4677 3 : os << "The applied flux density does not depend on frequency.";
4678 33 : os << LogIO::POST;
4679 :
4680 : // Ignore user polarization if using an image.
4681 39 : if(model != "" &&
4682 6 : (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 33 : String fluxScaleName("user-specified");
4693 : FluxStandard::FluxScale fluxScaleEnum;
4694 33 : if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
4695 0 : throw(AipsError(standard + " is not a recognized flux density scale"));
4696 :
4697 33 : FluxStandard fluxStd(fluxScaleEnum);
4698 33 : if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 ||
4699 30 : fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017 ) {
4700 11 : fluxStd.setInterpMethod(interpolation);
4701 : }
4702 :
4703 : // Setup the frequency, Flux, and ComponentList arrays.
4704 33 : uInt nspws = selToRawSpwIds.nelements();
4705 33 : Vector<Vector<Flux<Double> > > returnFluxes(nspws), returnFluxErrs(nspws);
4706 33 : Vector<Vector<MFrequency> > mfreqs(nspws);
4707 33 : Vector<Vector<Double> > fluxUsed(nspws); // fluxesUsed(nspws,4)
4708 33 : MSColumns msc(*ms_p);
4709 33 : MEpoch aveEpoch=MEpoch(msc.timeMeas()(0));
4710 : const Unit freqUnit = sjy_setup_arrs(returnFluxes, returnFluxErrs, fluxUsed, tempCLs, mfreqs,
4711 33 : msc.spectralWindow(), nspws, selToRawSpwIds,
4712 33 : chanDep);
4713 : // Processing for each field ***************************************************
4714 70 : for(Int fldInd = fldids.nelements(); fldInd--;){
4715 37 : Int fldid = fldids[fldInd];
4716 : // Extract field name and field center position
4717 37 : MDirection fieldDir = msc.field().phaseDirMeas(fldid, msc.time()(0));
4718 37 : String fieldName = msc.field().name()(fldid);
4719 37 : Bool foundSrc = false;
4720 :
4721 : //for returned flux densities
4722 :
4723 37 : Record retvalperField;
4724 : //
4725 : //fluxUsed = fluxdens;
4726 37 : 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 37 : Vector<Int> selectField(1);
4739 37 : selectField[0] = fldid;
4740 37 : Vector<Int> numDeChan(1);
4741 37 : numDeChan[0] = 0;
4742 37 : Vector<Int> begin(1);
4743 37 : begin[0] = 0;
4744 37 : Vector<Int> stepsize(1);
4745 37 : stepsize[0] = 1;
4746 37 : String msSelectString = "";
4747 148 : setdata("none", numDeChan, begin, stepsize, MRadialVelocity(),
4748 74 : MRadialVelocity(),
4749 : selToRawSpwIds, selectField, msSelectString, timerange, "",
4750 74 : Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
4751 37 : if(nullSelect_p){
4752 8 : os << ((timerange == "" && scanstr == ""
4753 4 : && obsidstr == "") ? LogIO::WARN : LogIO::NORMAL)
4754 : << "No data was selected for field " << fldid << "."
4755 8 : << LogIO::POST;
4756 4 : continue;
4757 : }
4758 33 : 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 23 : MSColumns msselc(*mssel_p);
4767 : //if(nullSelect_p || msselc.nrow() < 1){
4768 23 : 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 23 : 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 23 : }
4782 :
4783 : //*************** For loop about spw starts here ****************************
4784 33 : Vector<Double> freqscaling;
4785 33 : Vector<Double> freqsOfScale;
4786 33 : Vector<Int> rawspwids(nspws);
4787 : // make raw spw id list
4788 120 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4789 87 : Int rawspwid = selToRawSpwIds[selspw];
4790 87 : 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 33 : MEpoch mtime = msc.field().timeMeas()(fldid);
4830 :
4831 : // model image prep. changed to do all spws at once - TT, 2014.06.13
4832 33 : if(model != ""){
4833 :
4834 6 : 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 27 : 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 10 : Vector<Double> checkfluxes;
4848 10 : sjy_makeComponentList(os, tempCLs, returnFluxes, fluxUsed[0], selToRawSpwIds, mfreqs, fieldName, fieldDir,
4849 : spix, pipars, papars, rotMeas, reffreq, aveEpoch, fldid);
4850 10 : returnFluxes[0][0].value(checkfluxes);
4851 10 : }
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 33 : if (!useModelCol_p) {
4908 7 : String tmpspwstring=spwstring;
4909 7 : if (tmpspwstring=="") tmpspwstring="*";
4910 : os << LogIO::NORMAL
4911 : << "Will clear any existing model with matching field="
4912 : << fieldName
4913 : << " and spw=" << tmpspwstring
4914 7 : << LogIO::POST;
4915 :
4916 7 : 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 7 : VisModelData::clearModel(*mssel_p, fldidstr, spwstring);
4920 7 : }
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 120 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4948 87 : Record subrec;
4949 : //store fluxd actually used to scale (not input fluxdensity)
4950 87 : Vector<Double> finalFluxUsed;
4951 : // Flux of first chan
4952 87 : returnFluxes[selspw][0].value(finalFluxUsed);
4953 87 : 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 87 : retvalperField.defineRecord(String::toString(selToRawSpwIds[selspw]),subrec);
4959 87 : } // for selspw end **********************************************
4960 : //retval.defineRecord(fieldName,retvalperField);
4961 33 : retvalperField.define("fieldName",fieldName);
4962 33 : 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 120 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4981 87 : sjy_make_visibilities(tmodimage, os, rawspwids[selspw], fldid, tempCLs[selspw],
4982 : timerange, scanstr, intentstr, obsidstr, freqsOfScale, freqscaling);
4983 : }
4984 : // #######################################################################################
4985 : // clean-up
4986 : //
4987 33 : if(tmodimage)
4988 6 : delete tmodimage;
4989 33 : tmodimage = NULL;
4990 :
4991 120 : for(uInt selspw = 0; selspw < nspws; ++selspw){
4992 87 : if(tempCLs[selspw] != ""){
4993 79 : String errmsg;
4994 :
4995 : //didAnything = true;
4996 :
4997 79 : if(TableUtil::canDeleteTable(errmsg, tempCLs[selspw]))
4998 79 : 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 79 : }
5008 : }
5009 :
5010 65 : } // 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 33 : retval.define("format","{field Id: {spw Id: {fluxd: [I,Q,U,V] in Jy}, 'fieldName':field name }}");
5014 :
5015 33 : 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 7 : << LogIO::POST;
5020 15 : for(uInt selspw = 0; selspw < nspws; ++selspw)
5021 16 : os << " " << mfreqs[selspw][0].get("GHz").getValue() << " "
5022 16 : << returnFluxes[selspw][0].value(Stokes::I).getValue()
5023 24 : << LogIO::POST;
5024 : }
5025 :
5026 33 : this->writeHistory(os);
5027 33 : this->unlock();
5028 : //return true;
5029 33 : }
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 33 : return retval;
5042 33 : }
5043 :
5044 3 : 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 3 : Bool foundSrc = false;
5050 3 : logSink_p.clearLocally();
5051 6 : LogIO os(LogOrigin("imager", "setjy()"), logSink_p);
5052 :
5053 3 : Vector<String> clistnames(1);
5054 : try{
5055 : FluxStandard::FluxScale fluxScaleEnum;
5056 3 : String fluxScaleName("user-specified");
5057 :
5058 3 : if(!FluxStandard::matchStandard(standard, fluxScaleEnum, fluxScaleName))
5059 0 : throw(AipsError(standard + " is not a recognized flux density scale"));
5060 :
5061 3 : FluxStandard fluxStd(fluxScaleEnum);
5062 :
5063 3 : Vector<Vector<Flux<Double> > > returnFluxes(1), returnFluxErrs(1);
5064 3 : Vector<Vector<MFrequency> > mfreqs(1);
5065 3 : uInt nfreqs = freqv.nelements();
5066 :
5067 3 : mfreqs[0] = freqv;
5068 3 : returnFluxes[0].resize(nfreqs);
5069 3 : returnFluxErrs[0].resize(nfreqs);
5070 :
5071 3 : MDirection objDir;
5072 :
5073 3 : if (fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2013 ||
5074 3 : fluxScaleEnum==FluxStandard::PERLEY_BUTLER_2017)
5075 : {
5076 0 : fluxStd.setInterpMethod("nearest");
5077 : }
5078 3 : foundSrc = fluxStd.computeCL(objName, mfreqs, mtime, objDir,
5079 : returnFluxes, returnFluxErrs,
5080 : clistnames, prefix);
5081 18 : }
5082 3 : catch(AipsError x){
5083 3 : os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
5084 3 : RETHROW(x);
5085 6 : }
5086 0 : return foundSrc ? clistnames[0] : "";
5087 6 : }
5088 :
5089 33 : 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 33 : const Unit freqUnit(spwcols.chanFreqQuant().getUnits()[0]);
5102 :
5103 33 : IPosition ipos(1, 0);
5104 :
5105 33 : tempCLs.resize(nspws);
5106 120 : for(uInt selspw = 0; selspw < nspws; ++selspw){
5107 87 : Int rawspwid = selToRawSpwIds[selspw];
5108 :
5109 87 : if(chanDep){
5110 63 : mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid);
5111 63 : uInt nchan = mfreqs[selspw].nelements();
5112 63 : returnFluxes[selspw].resize(nchan);
5113 63 : returnFluxErrs[selspw].resize(nchan);
5114 : }
5115 : else{
5116 24 : mfreqs[selspw].resize(1);
5117 24 : returnFluxes[selspw].resize(1);
5118 24 : returnFluxErrs[selspw].resize(1);
5119 :
5120 : // Determine spectral window center frequency
5121 24 : Double medianFreq = median(spwcols.chanFreq()(rawspwid));
5122 24 : mfreqs[selspw] = spwcols.chanFreqMeas()(rawspwid)(ipos);
5123 24 : mfreqs[selspw].set(MVFrequency(Quantum<Double>(medianFreq, freqUnit)));
5124 : }
5125 : // initialize fluxUsed to 0
5126 87 : Vector<Double> iquvF(4,0.0);
5127 87 : fluxUsed[selspw]=iquvF;
5128 87 : }
5129 :
5130 66 : return freqUnit;
5131 33 : }
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 87 : 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 87 : Bool made_visibilities = false;
5147 :
5148 : // Select the uv-data for this field and spw. id.;
5149 : // all frequency channels selected.
5150 87 : 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 87 : selectSpw[0] = rawspwid;
5157 87 : selectField[0] = fldid;
5158 87 : String msSelectString = "";
5159 87 : Vector<Int> numDeChan(1);
5160 87 : numDeChan[0] = 0;
5161 87 : Vector<Int> begin(1);
5162 87 : begin[0] = 0;
5163 87 : Vector<Int> stepsize(1);
5164 87 : stepsize[0] = 1;
5165 : //TempImage<Float> tmodimage = tmodimages[0];
5166 87 : if(tmodimage || clname != "") {
5167 : //if(!tmodimages[0].null() || clname != "")
5168 348 : setdata("channel", numDeChan, begin, stepsize, MRadialVelocity(),
5169 174 : MRadialVelocity(),
5170 : selectSpw, selectField, msSelectString, timerange, "",
5171 174 : Vector<Int>(), "", "", "", scanstr, intentstr, obsidstr, true, true);
5172 : }
5173 87 : if(!nullSelect_p){
5174 : // Use ft to form visibilities
5175 73 : Vector<String> modelv;
5176 :
5177 73 : if(tmodimage){
5178 : //if(!tmodimages[0].null()){
5179 : //for (uInt imod=0; imod<tmodimages.nelements();imod++) {
5180 : //if(!tmodimages[imod].null()) {
5181 6 : if(sm_p)
5182 0 : destroySkyEquation();
5183 : // do if for each spw?
5184 6 : if(freqsOfScale.nelements() > 0){
5185 : //if(freqsOfScales[imod].nelements() > 0){
5186 4 : delete ft_p;
5187 4 : ft_p=NULL;
5188 4 : ftmachine_p="SetJyGridFT";
5189 4 : createFTMachine();
5190 4 : (static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScale, freqscaling);
5191 : //(static_cast<SetJyGridFT*>(ft_p))->setScale(freqsOfScales[imod], freqscalings[imod]);
5192 : }
5193 6 : if(!ft_p)
5194 2 : createFTMachine();
5195 6 : sm_p = new CleanImageSkyModel();
5196 : // loop over for multiple spw model images
5197 6 : 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 6 : setSkyEquation();
5204 6 : se_p->predict(false);
5205 6 : destroySkyEquation();
5206 :
5207 6 : made_visibilities = true;
5208 : }
5209 67 : else if(clname != ""){
5210 : //made_visibilities = ft(modelv, clname, false);
5211 67 : made_visibilities = ft(modelv, clname, false);
5212 67 : 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 73 : }
5221 87 : return made_visibilities;
5222 87 : }
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 23 : 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 23 : Bool foundSrc = false;
5267 :
5268 23 : Double meantime = msc.time()(0);
5269 23 : meantime += 0.5 * (msc.time()(msc.nrow() - 1) - meantime);
5270 23 : MEpoch mtime(msc.timeMeas()(0));
5271 23 : mtime.set(Quantity(meantime, "s"));
5272 23 : if(model != ""){
5273 : // Just get the fluxes and their uncertainties for scaling the image.
5274 : //foundSrc = fluxStd.compute(fieldName, mfreqs, returnFluxes,
5275 : // returnFluxErrs);
5276 6 : 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 17 : aveEpoch=mtime;
5298 :
5299 17 : foundSrc = fluxStd.computeCL(fieldName, mfreqs, mtime, fieldDir,
5300 : returnFluxes, returnFluxErrs,
5301 34 : tempCLs, ms_p->tableName()+"_setjy_");
5302 : }
5303 23 : 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 93 : for (uInt selspw=0; selspw<selToRawSpwIds.nelements(); selspw++) {
5385 70 : returnFluxes[selspw][0].value(fluxUsed[selspw]);
5386 : // Log flux density found for this field and spectral window
5387 70 : os.output().width(12);
5388 70 : os << fieldName;
5389 70 : os.output().width(2);
5390 70 : os << " (fld ind " << fldid << ") spw ";
5391 70 : os << selToRawSpwIds[selspw] << " ";
5392 70 : os.output().width(0);
5393 70 : os.output().precision(5);
5394 70 : os << LogIO::NORMAL << "[I=" << fluxUsed(selspw)(0) << ", "; // Loglevel INFO
5395 70 : os << "Q=" << fluxUsed(selspw)(1) << ", ";
5396 70 : os << "U=" << fluxUsed(selspw)(2) << ", ";
5397 70 : os << "V=" << fluxUsed(selspw)(3) << "] Jy @ ";
5398 70 : os << mfreqs(selspw)(0).getValue()<<"Hz, ";
5399 70 : os << ("(" + fluxScaleName + ")") << LogIO::POST;
5400 70 : writeHistory(os);
5401 : }
5402 : }
5403 23 : return foundSrc;
5404 23 : }
5405 :
5406 : //make componentlist(s) with user specified flux density
5407 10 : 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 27 : 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 17 : Flux<Double> fluxval;
5441 17 : Flux<Double> fluxerr;
5442 17 : 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 17 : PointShape point(fieldDir);
5447 :
5448 17 : Bool useTabularFlux(false);
5449 : //check if to use tabular form or SpectralIndex model
5450 17 : if ( spix.nelements() > 1 ) {
5451 3 : useTabularFlux=true;
5452 : }
5453 : else {
5454 : //if (pipars.nelements() > 1 || papars.nelements() > 1 || rotMeas != 0.0) {
5455 14 : if (pipars.nelements() > 1 || papars.nelements() > 1 ) {
5456 2 : useTabularFlux=true;
5457 : }
5458 : }
5459 17 : SpectralIndex siModel;
5460 : //Vector<Double> iflux;
5461 : //Vector<Double> qflux;
5462 : //Vector<Double> uflux;
5463 17 : Vector<Flux<Double> > fluxvalvec;
5464 17 : Bool gotQUFlux(false);
5465 17 : Bool useFluxAsIs(false);
5466 : //
5467 17 : 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 17 : MeasFrame mFrame(mtime, mLocation_p, fieldDir);
5472 34 : MFrequency::Convert cvt(mfreqs[selspw][0].getRef(), MFrequency::Ref(MFrequency::castType(reffreq.getRef().getType()), mFrame));
5473 17 : siModel.setRefFrequency(reffreq);
5474 : // if spix is not array of double,do this otherwise need to set flux densities by tabular...
5475 : //
5476 17 : Int nchn = mfreqs[selspw].nelements();
5477 17 : fluxvalvec.resize(nchn);
5478 17 : Vector<Double> iflux(nchn);
5479 17 : Vector<Double> qflux(nchn);
5480 17 : Vector<Double> uflux(nchn);
5481 17 : Vector<Double> vflux(nchn,0.0);
5482 : // circular polarization fraction
5483 17 : Double circpolFraction=0.0;
5484 17 : if ( fluxUsed[0] !=0.0 && fluxUsed[3] != 0.0 ) {
5485 0 : circpolFraction = fluxUsed[3]/fluxUsed[0];
5486 : }
5487 :
5488 17 : if (spix.nelements()==1) {
5489 : //siModel.setIndex(spix[0]);
5490 14 : Vector<Double> stokesindex(4);
5491 14 : stokesindex[0]=spix[0];
5492 14 : stokesindex[1]=0.0;
5493 14 : stokesindex[2]=rotMeas!=0.0? rotMeas: 0.0;
5494 14 : stokesindex[3]=0.0;
5495 14 : siModel.setStokesIndex(stokesindex);
5496 : // still use iflux if q,u flux=0 but polindex and polangle is set
5497 528 : for (uInt ichn = 0; ichn < uInt(nchn); ichn++) {
5498 514 : iflux[ichn] = fluxUsed[0] * siModel.sample(cvt(mfreqs[selspw][ichn]));
5499 : }
5500 14 : }
5501 : else {
5502 : // tabular case
5503 3 : sjy_calciflux(mfreqs[selspw],reffreq,fluxUsed[0],spix,iflux);
5504 : }
5505 : // linear pol
5506 17 : Vector<Double> inpipars;
5507 17 : Vector<Double> inpapars;
5508 17 : if ( pipars.nelements() > 0 || papars.nelements() > 0 ) {
5509 4 : inpipars.resize(pipars.nelements());
5510 4 : inpipars=pipars;
5511 4 : inpapars.resize(papars.nelements());
5512 4 : inpapars=papars;
5513 : }
5514 :
5515 : // Either Q or U non-zero, so use them
5516 17 : if (fluxUsed[1] != 0.0 || fluxUsed[2] != 0.0) {
5517 : // if Q U flux densities are given use that as 0th coefficient
5518 5 : Double pi0 = sqrt(fluxUsed[1] * fluxUsed[1] + fluxUsed[2] * fluxUsed[2]) / fluxUsed[0];
5519 5 : Double pa0 = 0.5 * atan2(fluxUsed[2],fluxUsed[1]);
5520 : os<<LogIO::DEBUG1<<"Polindex c0="<<pi0<<", polangle c0="<<pa0
5521 5 : <<" determined from input flux densities are used"<<LogIO::POST;
5522 5 : if ( pipars.nelements() == 0 || papars.nelements() == 0 ) {
5523 1 : inpipars.resize(1);
5524 1 : inpapars.resize(1);
5525 : }
5526 5 : inpipars[0] = pi0;
5527 5 : inpapars[0] = pa0;
5528 : }
5529 : //if (useTabularFlux) {
5530 17 : if (inpipars.nelements()!=0 && inpapars.nelements()!=0) {
5531 : // cerr<<"running sjy_calcquflux...."<<endl;
5532 : // - returns qflux and uflux
5533 5 : gotQUFlux = sjy_calcquflux(inpipars, inpapars, iflux, rotMeas, mfreqs[selspw], reffreq, qflux, uflux);
5534 : }
5535 12 : 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 722 : for (uInt ichn=0; ichn < iflux.nelements(); ichn++) {
5548 705 : if (!gotQUFlux) {
5549 385 : qflux[ichn] = 0.0;
5550 385 : uflux[ichn] = 0.0;
5551 : }
5552 320 : else if(useFluxAsIs) {
5553 0 : qflux[ichn] = fluxUsed[1];
5554 0 : uflux[ichn] = fluxUsed[2];
5555 0 : vflux[ichn] = fluxUsed[3];
5556 : }
5557 705 : if ( circpolFraction != 0.0) vflux[ichn] = iflux[ichn]*circpolFraction;
5558 705 : Flux<Double> iquvflux(iflux[ichn],qflux[ichn],uflux[ichn],vflux[ichn]);
5559 705 : fluxvalvec[ichn] = iquvflux;
5560 705 : }
5561 17 : returnFluxes[selspw][0]=fluxvalvec[0];
5562 17 : }
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 17 : if ( useTabularFlux ) {
5577 10 : tempCLs[selspw] = FluxStandard::makeComponentList(fieldName,
5578 : mfreqs[selspw],
5579 : mtime, fluxvalvec, point,
5580 5 : ms_p->tableName() +
5581 10 : "_setjy_spw" +
5582 20 : String::toString(selspw) +
5583 5 : "_");
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 12 : MFrequency thefreq = reffreq;
5593 12 : if ( gotQUFlux) {
5594 1 : fluxval=fluxvalvec[0];
5595 1 : thefreq=mfreqs[selspw][0];
5596 : }
5597 24 : 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 12 : ms_p->tableName() +
5604 24 : "_setjy_spw" +
5605 48 : String::toString(selspw) +
5606 12 : "_");
5607 12 : }
5608 17 : }
5609 10 : }
5610 :
5611 : // modified the input model image by regridding, scaling with a flux standard
5612 6 : 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 6 : TempImage<Float>* tmodimage = NULL;
5632 :
5633 : Double freqMax, freqMin;
5634 6 : Vector<Vector<Int> >dummy;
5635 : // TT for MMS this may not work
5636 : //String msname=mssel_p->antenna().tableName();
5637 : //msname.erase(msname.length()-8);
5638 6 : String msname=ms_p->tableName();
5639 : //adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, String::toString(rawspwid));
5640 : // Get freqmin and freqmax in LSRK for the entire span of the selected spws
5641 6 : String selSpwsStr;
5642 14 : for (uInt ispw=0; ispw < rawspwids.nelements(); ispw++) {
5643 8 : if (selSpwsStr!="") selSpwsStr += ", ";
5644 8 : selSpwsStr += String::toString(rawspwids(ispw));
5645 : }
5646 6 : adviseChanSelex(freqMin, freqMax, 0.0, MFrequency::LSRK, dummy, dummy, dummy, msname, fieldId, true, selSpwsStr);
5647 :
5648 : // Find min channel width to increment to construct freqsofScale
5649 6 : Double freqWidth = 0;
5650 : //
5651 14 : for (uInt ispw = 0; ispw<rawspwids.nelements(); ispw++) {
5652 8 : Vector<Double> freqWidths = spwcols.chanWidth()(rawspwids(ispw));
5653 :
5654 8 : Double minChanWidth = min(fabs(freqWidths));
5655 : // freqWidth init....
5656 8 : if (freqWidth == 0)
5657 6 : freqWidth = minChanWidth;
5658 : else
5659 2 : freqWidth = min(freqWidth,minChanWidth);
5660 8 : }
5661 :
5662 : // ADDED for debug
5663 : //Int rawspwid = rawspwids[0];
5664 : //Vector<Double> freqArray = spwcols.chanFreq()(rawspwid);
5665 : //Int nchan=freqArray.shape()[0] ;
5666 6 : Int nchan = Int(ceil(fabs(freqMax - freqMin)/freqWidth))+1;
5667 : //cerr<<"nchan="<<nchan<<" freqMax="<<freqMax<<" freqMin="<<freqMin<<" freqWidth="<<freqWidth<<endl;
5668 : //Filling it with the LSRK values
5669 : // SetJyGridFT will trigger nearestNeighbour interpolation for nchan>=2
5670 6 : Vector<Double> freqArray(nchan);
5671 6 : if (nchan==1) {
5672 0 : freqArray[0] = freqMin;
5673 : }
5674 6 : else if (nchan==2) {
5675 0 : freqArray[0] = freqMin;
5676 0 : freqArray[1] = freqMax;
5677 : }
5678 6 : else if (nchan==3) {
5679 0 : freqArray[0] = freqMin - freqWidth;
5680 0 : freqArray[1] = freqMin;
5681 0 : freqArray[2] = freqMin + freqWidth;
5682 : }
5683 : else {
5684 239 : for (Int k =0;k < nchan; ++k){
5685 233 : freqArray[k]=freqMin+k*freqWidth;
5686 : }
5687 : }
5688 : //Vector<Double> freqInc = spwcols.chanWidth()(rawspwid);
5689 6 : Double medianFreq = median(freqArray);
5690 6 : freqsOfScale.resize();
5691 6 : freqscale.resize();
5692 :
5693 : // 2 bw channel extra
5694 : // UNCOMMENTED for debug
5695 : //freqWidth = fabs(freqMax - freqMin) + 2 * max(freqInc);
5696 6 : Matrix<Double> fluxUsedPerChan; // 4 rows nchan col ...will resize when needed
5697 :
5698 : // Set fluxUsedPerChan to the flux densities for each chan.
5699 6 : if(chanDep || (spix[0] != 0.0 && fluxdens[0] != 0.0)){
5700 4 : IPosition whichChan(1, 0);
5701 4 : Flux<Double> returnFlux;
5702 4 : Flux<Double> returnFluxErr;
5703 4 : Double reffreqInGHz = 1.0;
5704 :
5705 4 : Unit ghz("GHz");
5706 4 : if(!precompute)
5707 0 : reffreqInGHz = reffreq.get(ghz).getValue();
5708 :
5709 4 : fluxUsedPerChan.resize(4, freqArray.nelements());
5710 51 : for(uInt k = 0; k < freqArray.nelements(); ++k){
5711 47 : whichChan[0] = k;
5712 47 : if(precompute){
5713 : //fluxStd.compute(fieldName, spwcols.chanFreqMeas()(rawspwid)(whichChan),
5714 : // returnFlux, returnFluxErr);
5715 47 : fluxStd.compute(fieldName, fieldDir, MFrequency(Quantity(freqArray[k], "Hz"), MFrequency::LSRK),
5716 : aveEpoch, returnFlux, returnFluxErr);
5717 47 : returnFlux.value(fluxUsed);
5718 : }
5719 : else{
5720 : // spix: index = c0 + c1*log(f/fo) + c2*log(f/fo)^2+ ...
5721 : // = log(So) + alpha*log(f/fo) + curv1*log(f/f0)^2 ....
5722 0 : uInt order = spix.nelements();
5723 0 : Polynomial<Double> spixfunc(order);
5724 0 : Vector<Double> coeffs(order+1);
5725 0 : coeffs[0] = log10(fluxdens[0]);
5726 0 : for (uInt ispix = 1; ispix < order+1; ispix++) {
5727 0 : coeffs[ispix] = spix[ispix-1];
5728 : }
5729 0 : spixfunc.setCoefficients(coeffs);
5730 :
5731 : //Double freq = spwcols.chanFreqMeas()(rawspwids(0))(whichChan).get(ghz).getValue();
5732 : //Double specfac = pow(freq / reffreqInGHz, spix);
5733 : // TT mod-06/11/14
5734 : // freqArray may or may not be exactly match with data chan frequencies
5735 : // so probably make sense to use freqArray instead
5736 : //Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spix);
5737 0 : Double specfac = pow((freqArray[k]/1.e+09) / reffreqInGHz, spixfunc(freqArray[k]));
5738 :
5739 0 : for(uInt stokes = 0; stokes < 4; ++stokes)
5740 0 : fluxUsed[stokes] = fluxdens[stokes] * specfac;
5741 0 : }
5742 47 : fluxUsedPerChan.column(k) = fluxUsed;
5743 : }
5744 4 : }
5745 6 : PagedImage<Float> modimage(model);
5746 6 : modimage.table().unmarkForDelete();
5747 6 : IPosition imshape = modimage.shape();
5748 6 : CoordinateSystem csys(modimage.coordinates());
5749 6 : Int freqAxis = CoordinateUtil::findSpectralAxis(csys);
5750 6 : Vector<Stokes::StokesTypes> whichPols;
5751 6 : Int polAxis = CoordinateUtil::findStokesAxis(whichPols, csys);
5752 6 : Int icoord = csys.findCoordinate(Coordinate::SPECTRAL);
5753 6 : SpectralCoordinate spcsys = csys.spectralCoordinate(icoord);
5754 6 : MEpoch elEpoch; MDirection elDir; MFrequency::Types elTypes; MPosition elPos;
5755 6 : spcsys.getReferenceConversion(elTypes, elEpoch, elPos, elDir);
5756 6 : spcsys.setReferenceConversion(MFrequency::LSRK, aveEpoch, elPos, elDir);
5757 6 : spcsys.setReferenceValue(Vector<Double>(1, medianFreq));
5758 6 : spcsys.setReferencePixel(Vector<Double>(1, 0.0));
5759 6 : spcsys.setWorldAxisUnits(Vector<String>(1,
5760 : //mfreqs[selspw][0].getUnit().getName()));
5761 6 : mfreqs[0][0].getUnit().getName()));
5762 : //make image freq. width wide enough for FTMachine to work correctly
5763 6 : spcsys.setIncrement(Vector<Double>(1, 2*fabs(freqMax-freqMin)));
5764 : // make a cube model if the model is a cube already
5765 6 : if(modimage.shape()(freqAxis) >1){
5766 : // model image is a cube...just regrid it then
5767 : os << LogIO::NORMAL
5768 : << "The model image is a cube, so it is being regridded but without scaling the flux density."
5769 0 : << LogIO::POST;
5770 0 : spcsys = SpectralCoordinate(
5771 : //MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
5772 0 : MFrequency::castType(mfreqs[0][0].getRef().getType()),
5773 0 : freqArray, spcsys.restFrequency());
5774 0 : imshape(freqAxis)=freqArray.nelements();
5775 0 : csys.replaceCoordinate(spcsys, icoord);
5776 0 : tmodimage = new TempImage<Float>(imshape, csys);
5777 0 : sjy_regridCubeChans(tmodimage, modimage, freqAxis);
5778 : //return from here itself
5779 0 : return tmodimage;
5780 : }
5781 :
5782 6 : if(chanDep && (fluxUsedPerChan.ncolumn() > 1)){
5783 : //spcsys = SpectralCoordinate(
5784 : // MFrequency::castType(mfreqs[selspw][0].getRef().getType()),
5785 : // freqArray, spcsys.restFrequency());
5786 4 : if(freqAxis < 2 || polAxis < 2)
5787 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"));
5788 4 : freqscale.resize(freqArray.nelements());
5789 4 : freqsOfScale.resize(freqArray.nelements());
5790 4 : freqsOfScale=freqArray;
5791 4 : freqscale=1.0;
5792 4 : if(freqAxis == 2) {//pol and freq are swapped
5793 4 : imshape[2]=imshape[3];
5794 4 : imshape[3] = 1;
5795 4 : Vector<Int> trans(4);
5796 4 : trans[0] = 0; trans[1] = 1; trans[2] = 3; trans[3] = 2;
5797 4 : csys.transpose(trans, trans);
5798 4 : }
5799 : else{
5800 0 : imshape(freqAxis) = 1;
5801 : }
5802 : }
5803 6 : csys.replaceCoordinate(spcsys, icoord);
5804 6 : tmodimage = new TempImage<Float>(imshape, csys);
5805 6 : IPosition blcin(modimage.shape().nelements(), 0);
5806 6 : IPosition trcin=modimage.shape()-1;
5807 6 : IPosition blcout(imshape.nelements(), 0);
5808 6 : IPosition trcout=imshape-1;
5809 :
5810 12 : for (uInt ipol=0; ipol < imshape[2]; ++ipol){
5811 6 : blcin[polAxis]=ipol;
5812 6 : trcin[polAxis]=ipol;
5813 6 : blcout[2]=ipol;
5814 6 : trcout[2]=ipol;
5815 6 : Slicer slin(blcin, trcin, Slicer::endIsLast);
5816 6 : Slicer slout(blcout, trcout, Slicer::endIsLast);
5817 6 : SubImage<Float> subimout(*tmodimage, slout, true);
5818 6 : SubImage<Float> subimin(modimage, slin, false);
5819 6 : subimout.copyData(subimin);
5820 6 : }
5821 : os << LogIO::DEBUG1
5822 : << "freqUnit.getName() = " << freqUnit.getName()
5823 6 : << LogIO::POST;
5824 : os << LogIO::DEBUG1
5825 : //<< "mfreqs[selspw].get(freqUnit).getValue() = "
5826 : //<< mfreqs[selspw][0].get(freqUnit).getValue()
5827 : << "mfreqs[0][0].get(freqUnit).getValue() = "
5828 12 : << mfreqs[0][0].get(freqUnit).getValue()
5829 12 : << LogIO::POST;
5830 :
5831 : // Check direction consistency (reported in log message below)
5832 6 : String err;
5833 6 : if(!CoordinateUtil::setDirectionConversion(err, csys, fieldDir.getRefString())){
5834 : os << "LogIO::WARN "
5835 : << "Could not set direction conversion between flux image and "
5836 0 : << fieldDir.getRefString() << LogIO::POST;
5837 : }
5838 6 : Int dircoord(csys.findCoordinate(Coordinate::DIRECTION));
5839 6 : DirectionCoordinate dircsys=csys.directionCoordinate(dircoord);
5840 6 : MVDirection mvd;
5841 6 : dircsys.toWorld(mvd,dircsys.referencePixel());
5842 6 : Double sep = fieldDir.getValue().separation(mvd,"\"").getValue();
5843 :
5844 : //Apply radius limit for 3C286,3C48,3C147 and 3C138
5845 6 : sjy_setRadiusLimit(tmodimage, modimage, model, dircsys);
5846 :
5847 : // for debugging
5848 : //PagedImage<Float> checkIm(TiledShape(modimage.shape(),
5849 : // modimage.niceCursorShape()),
5850 : // modimage.coordinates(),
5851 : // "checkImage");
5852 : //checkIm.copyData((LatticeExpr<Float>)(*tmodimage));
5853 :
5854 6 : if(fluxdens[0] != 0.0){
5855 6 : Float sumI = 1.0;
5856 :
5857 : // ?: can't handle the different return types.
5858 6 : if(whichPols.nelements() > 1)
5859 : //sumI = sum(ImagePolarimetry(modimage).stokesI()).getFloat();
5860 0 : sumI = sum(ImagePolarimetry(*tmodimage).stokesI()).getFloat();
5861 : else
5862 : //sumI = sum(modimage).getFloat();
5863 6 : sumI = sum(*tmodimage).getFloat();
5864 :
5865 : //if(selspw == 0)
5866 : os << LogIO::NORMAL
5867 6 : << "Using model image " << modimage.name() // Loglevel INFO
5868 6 : << LogIO::POST;
5869 :
5870 : // scale the image
5871 6 : if(freqscale.nelements() > 0){
5872 4 : Int midchan = freqArray.nelements()/2;
5873 4 : if(modimage.shape()(freqAxis) == 1){
5874 : // IPosition blc(imshape.nelements(), 0);
5875 : //IPosition trc = imshape - 1;
5876 : os << LogIO::NORMAL
5877 : //<< "Scaling spw " << selspw << "'s model image by channel to I = "
5878 0 : << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image by channel to I = "
5879 8 : << fluxUsedPerChan.row(0)(0)<<", "
5880 8 : << fluxUsedPerChan.row(0)(midchan)<<", "
5881 8 : << fluxUsedPerChan.row(0)(nchan-1)
5882 : << " Jy @("
5883 8 : << freqArray(0)<<", "
5884 8 : << freqArray(midchan)<<", "
5885 8 : << freqArray(nchan-1)
5886 : <<")Hz (LSRK) for visibility prediction (a few representative values are shown)."
5887 16 : << LogIO::POST;
5888 4 : writeHistory(os);
5889 51 : for(uInt k = 0; k < fluxUsedPerChan.ncolumn(); ++k){
5890 47 : freqscale[k] = fluxUsedPerChan.column(k)(0)/sumI;
5891 : //blc[3] = k;
5892 : //trc[3] = k;
5893 : //Slicer sl(blc, trc, Slicer::endIsLast);
5894 : //SubImage<Float> subim(*tmodimage, sl, true);
5895 : //subim.copyData((LatticeExpr<Float>)(modimage*scale));
5896 : }
5897 : // for debug
5898 : //cerr<<"freqscale="<<freqscale<<endl;
5899 : //cerr<<"freqsOfScale="<<freqsOfScale<<endl;
5900 : }
5901 : }
5902 : else{
5903 : // Scale factor
5904 2 : Float scale = fluxUsed[0] / sumI;
5905 : //for addition of sjy_setRadiusLimit
5906 : //tmodimage->copyData( (LatticeExpr<Float>)(modimage * scale) );
5907 2 : tmodimage->copyData( (LatticeExpr<Float>)(*tmodimage * scale) );
5908 : os << LogIO::NORMAL
5909 : // << "Scaling spw " << selspw << "'s model image to I = "
5910 2 : << "Scaling spw(s) " << String::toString(rawspwids) << "'s model image to I = "
5911 4 : << fluxUsed[0] // Loglevel INFO
5912 : << " Jy @ "
5913 : //<< mfreqs[0][0].getValue()
5914 4 : << freqArray(0)
5915 : << "Hz (LSRK) for visibility prediction."
5916 2 : << LogIO::POST;
5917 2 : writeHistory(os);
5918 : }
5919 : }
5920 : else{
5921 : os << LogIO::NORMAL // Loglevel INFO
5922 : << "Using the model image's original unscaled flux density for visibility prediction."
5923 0 : << LogIO::POST;
5924 0 : writeHistory(os);
5925 : // included in sjy_setRadiusLimit
5926 : //tmodimage->copyData( (LatticeExpr<Float>)(modimage) );
5927 : }
5928 :
5929 : //if(selspw == 0){
5930 : os << LogIO::NORMAL // Loglevel INFO
5931 : << "The model image's reference pixel is " << sep
5932 : << " arcsec from " << fieldName << "'s phase center."
5933 6 : << LogIO::POST;
5934 6 : writeHistory(os);
5935 : //}
5936 :
5937 6 : return tmodimage;
5938 6 : }
5939 :
5940 0 : Bool Imager::sjy_regridCubeChans(TempImage<Float>* tmodimage,
5941 : PagedImage<Float>& modimage, Int freqAxis)
5942 : {
5943 0 : if(freqAxis != 3)
5944 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"));
5945 0 : ImageRegrid<Float> ir;
5946 0 : IPosition axes(1, freqAxis); // regrid the spectral only
5947 0 : ir.regrid(*tmodimage, Interpolate2D::LINEAR, axes, modimage);
5948 0 : return true;
5949 0 : }
5950 :
5951 6 : Bool Imager::sjy_setRadiusLimit(TempImage<Float>* tmodimage,
5952 : PagedImage<Float>& modimage, const String& model, DirectionCoordinate& dircsys)
5953 : {
5954 6 : Path path(model);
5955 6 : String basename=path.baseName();
5956 : Float arad;
5957 : // radius limit in arcsec from AIPS
5958 6 : if (basename.find("3C286")==0) {
5959 1 : arad=3.0;
5960 : }
5961 5 : else if (basename.find("3C48")==0) {
5962 1 : arad=0.95;
5963 : }
5964 4 : else if (basename.find("3C147")==0) {
5965 3 : arad=0.85;
5966 : }
5967 1 : else if (basename.find("3C138")==0) {
5968 1 : arad=0.75;
5969 : }
5970 : else {
5971 0 : arad=0;
5972 0 : tmodimage->copyData(modimage);
5973 0 : return true;
5974 : }
5975 : try {
5976 6 : Quantity qrad(arad,"arcsec");
5977 6 : Float prad=Float(qrad.get(Unit("rad")).getValue()/abs(dircsys.increment()(0)));
5978 6 : Float radius = (prad >0.5 ? prad: 0.5);
5979 : //Add current ms name to avoid file access clash for MMS processing
5980 6 : String tempmaskname=ms_p->tableName()+"__tmp_mask_setjy_radiuslimit";
5981 12 : PagedImage<Float> maskImage(TiledShape(modimage.shape(),
5982 0 : modimage.niceCursorShape()),
5983 12 : modimage.coordinates(), tempmaskname);
5984 6 : maskImage.table().markForDelete();
5985 6 : Matrix<Float> circ(1,3);
5986 6 : Record *imrec=0;
5987 6 : Matrix<Quantity> blctrcs;
5988 6 : circ(0,0)=radius;
5989 6 : circ(0,1)=dircsys.referencePixel()(0);
5990 6 : circ(0,2)=dircsys.referencePixel()(1);
5991 6 : Imager::regionToImageMask(tempmaskname,imrec,blctrcs,circ,1.0);
5992 6 : PagedImage<Float> tmpmask(tempmaskname);
5993 6 : tmpmask.table().markForDelete();
5994 6 : tmodimage->copyData( (LatticeExpr<Float>)(tmpmask*modimage));
5995 6 : }
5996 0 : catch (...) {
5997 0 : return false;
5998 0 : }
5999 6 : return true;
6000 6 : }
6001 :
6002 3 : Bool Imager::sjy_calciflux(const Vector<MFrequency>& freqs, const MFrequency& reffreq,
6003 : const Double refflux, const Vector<Double>& vspix, Vector<Double>& iflux)
6004 : {
6005 : try {
6006 : // assume polynomical is log(S) = c0 + alpha*log(f/fo) + curv1*log(f/fo)^2+
6007 : // vspix should contains [alpha, curv1, etc..] and c0 is calculated from refflux
6008 3 : uInt porder = vspix.nelements();
6009 3 : Polynomial<Double> lf(porder);
6010 3 : Vector<Double> coeffs(porder+1);
6011 3 : coeffs[0] = log10(refflux);
6012 9 : for (uInt i = 1; i < vspix.nelements()+1; i++ ) {
6013 6 : coeffs[i] = vspix[i-1];
6014 : }
6015 3 : lf.setCoefficients(coeffs);
6016 3 : Int nf = freqs.nelements();
6017 3 : iflux.resize(nf);
6018 3 : Unit frequnit("GHz");
6019 3 : Double reffreqval = reffreq.get(frequnit).getValue();
6020 194 : for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
6021 191 : iflux[cfidx] = pow(10.0,lf(log10(freqs[cfidx].get(frequnit).getValue()/reffreqval)));
6022 : }
6023 3 : }
6024 0 : catch (...) {
6025 0 : return false;
6026 0 : }
6027 3 : return true;
6028 : }
6029 :
6030 5 : Bool Imager::sjy_calcquflux(const Vector<Double>& pipars, const Vector<Double>& papars,
6031 : const Vector<Double>& iflux, const Double rotMeas,
6032 : const Vector<MFrequency>& freqs,
6033 : const MFrequency& reffreq, Vector<Double>& qflux,
6034 : Vector<Double>& uflux)
6035 : {
6036 :
6037 : try {
6038 5 : Int nf = freqs.nelements();
6039 : //polindex
6040 : // of the form, pi_o + c1*(f-fo)/fo + c2*(f-fo)/fo
6041 5 : Polynomial<Double> pipoly(pipars.nelements());
6042 5 : pipoly.setCoefficients(pipars);
6043 : //pangle
6044 5 : Polynomial<Double> papoly(papars.nelements());
6045 5 : papoly.setCoefficients(papars);
6046 5 : qflux.resize(nf);
6047 5 : uflux.resize(nf);
6048 5 : Unit ghz("Hz");
6049 5 : Double f0 = reffreq.get(ghz).getValue();
6050 :
6051 325 : for (uInt cfidx = 0; cfidx < (uInt)nf; cfidx++) {
6052 320 : Double f = freqs[cfidx].get(ghz).getValue();
6053 320 : Double ipi = pipoly((f-f0)/f0);
6054 320 : Double ipa = papoly((f-f0)/f0);
6055 320 : Double iiflux = iflux[cfidx];
6056 320 : Double qfluxval = ipi * iiflux * cos(2.0*ipa);
6057 320 : Double ufluxval = ipi * iiflux * sin(2.0*ipa);
6058 : //debug
6059 : //if (cfidx<10) cerr<<"sjy_calcquflux:: poli="<<ipi<<" pola="<<ipa<<" qflux="<<qfluxval<<" uflux="<<ufluxval<<endl;
6060 320 : if (rotMeas!=0.0 ) {
6061 128 : Double rotangle = 2*rotMeas * C::c * C::c * (f0*f0-f*f)/(f*f*f0*f0);
6062 : //if (cfidx<10) cerr<<"rotangle="<<rotangle<<endl;
6063 128 : qflux[cfidx] = qfluxval*cos(rotangle) - ufluxval*sin(rotangle);
6064 128 : uflux[cfidx] = qfluxval*sin(rotangle) + ufluxval*cos(rotangle);
6065 : }
6066 : else {
6067 192 : qflux[cfidx] = qfluxval;
6068 192 : uflux[cfidx] = ufluxval;
6069 : }
6070 : //if (cfidx<10) cerr<<"uflux/qflux["<<cfidx<<"]="<<uflux[cfidx]/qflux[cfidx]<<endl;
6071 : }
6072 5 : }
6073 0 : catch (...) {
6074 0 : return false;
6075 0 : }
6076 5 : return true;
6077 : }
6078 :
6079 :
6080 0 : Bool Imager::clone(const String& imageName, const String& newImageName)
6081 : {
6082 : //if(!valid()) return false;
6083 : // This is not needed if(!assertDefinedImageParameters()) return false;
6084 0 : LogIO os(LogOrigin("imager", "clone()", WHERE));
6085 : try {
6086 0 : PagedImage<Float> oldImage(imageName);
6087 0 : PagedImage<Float> newImage(TiledShape(oldImage.shape(),
6088 0 : oldImage.niceCursorShape()), oldImage.coordinates(),
6089 0 : newImageName);
6090 0 : newImage.set(0.0);
6091 0 : newImage.table().flush(true, true);
6092 0 : } catch (AipsError x) {
6093 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6094 0 : return false;
6095 0 : }
6096 0 : return true;
6097 0 : }
6098 :
6099 : // Make an empty image
6100 270 : Bool Imager::make(const String& model)
6101 : {
6102 :
6103 270 : if(!valid())
6104 : {
6105 0 : return false;
6106 : }
6107 540 : LogIO os(LogOrigin("imager", "make()", WHERE));
6108 :
6109 270 : this->lock();
6110 : try {
6111 270 : if(!assertDefinedImageParameters())
6112 : {
6113 0 : return false;
6114 : }
6115 :
6116 : // Make an image with the required shape and coordinates
6117 270 : String modelName(model);
6118 270 : if(modelName=="") modelName=imageName()+".model";
6119 : os << LogIO::DEBUG1
6120 270 : << "Making empty image: " << modelName << LogIO::POST;
6121 :
6122 270 : removeTable(modelName);
6123 270 : CoordinateSystem coords;
6124 : //if(!imagecoordinates(coords, false))
6125 270 : if(!imagecoordinates2(coords, false))
6126 : {
6127 0 : this->unlock();
6128 0 : return false;
6129 : }
6130 270 : this->makeEmptyImage(coords, modelName, fieldid_p);
6131 270 : this->unlock();
6132 :
6133 270 : return true;
6134 270 : } catch (AipsError x) {
6135 0 : this->unlock();
6136 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6137 :
6138 0 : return false;
6139 :
6140 0 : }
6141 : this->unlock();
6142 :
6143 : return true;
6144 270 : }
6145 :
6146 : // Fit the psf. If psf is blank then make the psf first.
6147 14 : Bool Imager::fitpsf(const String& psf, ImageBeamSet& mbeam) {
6148 :
6149 14 : if(!valid())
6150 : {
6151 0 : return false;
6152 : }
6153 28 : LogIO os(LogOrigin("imager", "fitpsf()", WHERE));
6154 :
6155 14 : this->lock();
6156 : try {
6157 14 : if(!assertDefinedImageParameters())
6158 : {
6159 0 : this->unlock();
6160 0 : return false;
6161 : }
6162 :
6163 14 : os << LogIO::NORMAL << "Fitting to psf" << LogIO::POST; // Loglevel PROGRESS
6164 :
6165 14 : String lpsf; lpsf=psf;
6166 14 : if(lpsf=="") {
6167 0 : lpsf=imageName()+".psf";
6168 0 : makeimage("psf", lpsf);
6169 : }
6170 :
6171 14 : if(!Table::isReadable(lpsf)) {
6172 0 : this->unlock();
6173 : os << LogIO::SEVERE << "PSF image " << lpsf << " does not exist"
6174 0 : << LogIO::POST;
6175 :
6176 0 : return false;
6177 : }
6178 :
6179 14 : PagedImage<Float> psfImage(lpsf);
6180 14 : StokesImageUtil::FitGaussianPSF(psfImage, mbeam);
6181 14 : beam_p = mbeam;
6182 14 : beamValid_p=true;
6183 :
6184 14 : GaussianBeam elbeam=beam_p(0,0);
6185 : os << LogIO::NORMAL // Loglevel INFO
6186 : << " Beam fit: " << elbeam.getMajor("arcsec") << " by "
6187 : << elbeam.getMinor("arcsec") << " (arcsec) at pa "
6188 14 : << elbeam.getPA(Unit("deg")) << " (deg) " << endl;
6189 :
6190 14 : this->unlock();
6191 :
6192 14 : return true;
6193 14 : } catch (AipsError x) {
6194 0 : this->unlock();
6195 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6196 :
6197 0 : return false;
6198 0 : }
6199 : this->unlock();
6200 :
6201 : return true;
6202 14 : }
6203 :
6204 :
6205 0 : Bool Imager::setscales(const String& scaleMethod,
6206 : const Int inscales,
6207 : const Vector<Float>& userScaleSizes)
6208 : {
6209 0 : scaleMethod_p = scaleMethod;
6210 0 : userScaleSizes_p.resize(userScaleSizes.nelements());
6211 0 : userScaleSizes_p = userScaleSizes;
6212 0 : if (scaleMethod_p == "uservector") {
6213 0 : nscales_p = userScaleSizes.nelements();
6214 : } else {
6215 0 : nscales_p = inscales;
6216 : }
6217 : //Force the creation of a new sm_p with the new scales
6218 0 : destroySkyEquation();
6219 0 : scaleInfoValid_p = true;
6220 0 : return true;
6221 : };
6222 :
6223 0 : Bool Imager::setSmallScaleBias(const Float inbias)
6224 : {
6225 0 : smallScaleBias_p = inbias;
6226 0 : return true;
6227 : }
6228 :
6229 : // Added for wb algo.
6230 0 : Bool Imager::settaylorterms(const Int intaylor,const Double inreffreq)
6231 : {
6232 0 : ntaylor_p = intaylor;
6233 0 : reffreq_p = inreffreq;
6234 0 : return true;
6235 : };
6236 :
6237 : // Set the beam
6238 0 : Bool Imager::setbeam(const ImageBeamSet& mbeam)
6239 : {
6240 0 : if(!valid()) return false;
6241 :
6242 0 : LogIO os(LogOrigin("imager", "setbeam()", WHERE));
6243 0 : beam_p = ImageBeamSet(mbeam);
6244 0 : beamValid_p=true;
6245 :
6246 0 : return true;
6247 0 : }
6248 :
6249 : // Plot the uv plane
6250 0 : Bool Imager::plotuv(const Bool rotate)
6251 : {
6252 :
6253 0 : if(!valid()) return false;
6254 :
6255 0 : LogIO os(LogOrigin("imager", "plotuv()", WHERE));
6256 :
6257 0 : this->lock();
6258 : try {
6259 : os << LogIO::NORMAL // Loglevel PROGRESS
6260 0 : << "Plotting uv coverage for currently selected data" << LogIO::POST;
6261 :
6262 0 : ROVisIter& vi(*rvi_p);
6263 0 : VisBuffer vb(vi);
6264 :
6265 0 : uInt nVis = count_visibilities(rvi_p, true, true);
6266 :
6267 0 : if(nVis==0) {
6268 0 : this->unlock();
6269 0 : os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
6270 0 : return false;
6271 : }
6272 :
6273 0 : if(rotate) {
6274 : os << LogIO::NORMAL // Loglevel INFO
6275 0 : << "UVW will be rotated to specified phase center" << LogIO::POST;
6276 : }
6277 :
6278 :
6279 0 : Vector<Float> u(nVis); u=0.0;
6280 0 : Vector<Float> v(nVis); v=0.0;
6281 0 : Vector<Float> uRotated(nVis); uRotated=0.0;
6282 0 : Vector<Float> vRotated(nVis); vRotated=0.0;
6283 0 : Float maxAbsUV=0.0;
6284 :
6285 0 : Int iVis=0;
6286 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6287 0 : for (vi.origin();vi.more();vi++) {
6288 0 : Int nRow=vb.nRow();
6289 0 : Int nChan=vb.nChannel();
6290 0 : Vector<Double> uvwRotated(3);
6291 0 : MeasFrame mFrame((MEpoch(Quantity(vb.time()(0), "s"))), mLocation_p);
6292 0 : UVWMachine uvwMachine(phaseCenter_p, vb.phaseCenter(), mFrame);
6293 0 : for (Int row=0; row<nRow; ++row) {
6294 0 : if(rotate) {
6295 0 : for (Int dim=0;dim<3;++dim) {
6296 0 : uvwRotated(dim)=vb.uvw()(row)(dim);
6297 : }
6298 0 : uvwMachine.convertUVW(uvwRotated);
6299 : }
6300 :
6301 0 : for (Int chn=0; chn<nChan; ++chn) {
6302 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6303 0 : Float f=vb.frequency()(chn)/C::c;
6304 0 : u(iVis)=vb.uvw()(row)(0)*f;
6305 0 : v(iVis)=vb.uvw()(row)(1)*f;
6306 0 : if(abs(u(iVis))>maxAbsUV) maxAbsUV=abs(u(iVis));
6307 0 : if(abs(v(iVis))>maxAbsUV) maxAbsUV=abs(v(iVis));
6308 0 : if(rotate) {
6309 0 : uRotated(iVis)=uvwRotated(0)*f;
6310 0 : vRotated(iVis)=uvwRotated(1)*f;
6311 0 : if(abs(uRotated(iVis))>maxAbsUV) maxAbsUV=abs(uRotated(iVis));
6312 0 : if(abs(vRotated(iVis))>maxAbsUV) maxAbsUV=abs(vRotated(iVis));
6313 : }
6314 0 : ++iVis;
6315 : }
6316 : }
6317 : }
6318 0 : }
6319 : }
6320 :
6321 0 : if(maxAbsUV==0.0) {
6322 0 : this->unlock();
6323 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6324 0 : return false;
6325 : }
6326 : else {
6327 0 : Quantity cell(0.5/maxAbsUV, "rad");
6328 : os << LogIO::NORMAL // Loglevel INFO
6329 0 : << "Maximum uv distance = " << maxAbsUV << " wavelengths" << endl;
6330 : os << LogIO::NORMAL // Loglevel INFO
6331 0 : << "Recommended cell size < " << cell.get("arcsec").getValue()
6332 0 : << " arcsec" << LogIO::POST;
6333 0 : }
6334 :
6335 :
6336 0 : return false;
6337 :
6338 : this->unlock();
6339 :
6340 0 : }
6341 0 : catch (AipsError x) {
6342 0 : this->unlock();
6343 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6344 0 : return false;
6345 :
6346 0 : }
6347 0 : catch (...) {
6348 0 : this->unlock();
6349 0 : }
6350 0 : this->unlock();
6351 :
6352 :
6353 :
6354 0 : return true;
6355 0 : }
6356 :
6357 : // Plot the visibilities
6358 0 : Bool Imager::plotvis(const String& type, const Int increment)
6359 : {
6360 :
6361 0 : if(!valid()) return false;
6362 0 : LogIO os(LogOrigin("imager", "plotvis()", WHERE));
6363 :
6364 0 : this->lock();
6365 : try {
6366 :
6367 : os << LogIO::NORMAL // Loglevel PROGRESS
6368 : << "Plotting Stokes I visibility for currently selected data"
6369 0 : << LogIO::POST;
6370 :
6371 :
6372 0 : MSColumns msc(*mssel_p);
6373 0 : Bool hasCorrected=!(msc.correctedData().isNull());
6374 0 : Bool hasModel= true; //with virtual model data service model data is always there
6375 : //why bother if it is not requested
6376 0 : if(!((type == "all") || (type=="model") || (type == "residual")))
6377 0 : hasModel=false;
6378 0 : if(!((type == "all") || (type=="corrected") || (type == "residual")))
6379 0 : hasCorrected=false;
6380 :
6381 :
6382 :
6383 0 : Bool twoPol=true;
6384 0 : Vector<String> polType=msc.feed().polarizationType()(0);
6385 0 : if (polType(0)!="X" && polType(0)!="Y" &&
6386 0 : polType(0)!="R" && polType(0)!="L") {
6387 0 : twoPol=false;
6388 : }
6389 :
6390 0 : ROVisIter& vi(*rvi_p);
6391 0 : VisBuffer vb(vi);
6392 :
6393 0 : Int nVis=0;
6394 0 : Int counter=0;
6395 0 : Float maxWeight=0;
6396 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6397 0 : for (vi.origin();vi.more();vi++) {
6398 0 : Int nRow=vb.nRow();
6399 0 : Int nChan=vb.nChannel();
6400 0 : maxWeight=max(maxWeight, max(vb.imagingWeight()));
6401 0 : for (Int row=0; row<nRow; ++row) {
6402 0 : for (Int chn=0; chn<nChan; ++chn) {
6403 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6404 0 : ++counter;
6405 0 : if(counter==increment) {
6406 0 : counter=0;
6407 0 : ++nVis;
6408 : }
6409 : }
6410 : }
6411 : }
6412 : }
6413 : }
6414 :
6415 0 : if(nVis==0) {
6416 0 : os << LogIO::SEVERE << "No unflagged visibilities" << LogIO::POST;
6417 0 : if(maxWeight <=0){
6418 : os << LogIO::SEVERE << "Max of imaging-weight is " << maxWeight
6419 0 : << LogIO::POST;
6420 : os << LogIO::SEVERE << "Try setting it with the function weight"
6421 0 : << LogIO::POST;
6422 : }
6423 0 : this->unlock();
6424 0 : return false;
6425 : }
6426 :
6427 0 : if(increment>1) {
6428 : os << LogIO::NORMAL << "For increment = " << increment << ", found " << nVis // Loglevel INFO
6429 0 : << " points for plotting" << endl;
6430 : }
6431 : else {
6432 0 : os << LogIO::NORMAL << "Found " << nVis << " points for plotting" << endl; // Loglevel INFO
6433 : }
6434 0 : Vector<Float> amp(nVis); amp=0.0;
6435 0 : Vector<Float> correctedAmp(nVis); correctedAmp=0.0;
6436 0 : Vector<Float> modelAmp(nVis); modelAmp=0.0;
6437 0 : Vector<Float> residualAmp(nVis); residualAmp=0.0;
6438 0 : Vector<Float> uvDistance(nVis); uvDistance=0.0;
6439 :
6440 0 : if(!hasModel)
6441 0 : modelAmp.resize();
6442 0 : if(!hasCorrected)
6443 0 : correctedAmp.resize();
6444 0 : if(!hasCorrected || !hasModel)
6445 0 : residualAmp.resize();
6446 :
6447 :
6448 0 : Float maxuvDistance=0.0;
6449 0 : Float maxAmp=0.0;
6450 0 : Float maxCorrectedAmp=0.0;
6451 0 : Float maxModelAmp=0.0;
6452 0 : Float maxResidualAmp=0.0;
6453 0 : Int iVis=0;
6454 0 : counter=0;
6455 0 : vi.originChunks();
6456 0 : vi.origin();
6457 0 : uInt numCorrPol=vb.nCorr();
6458 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6459 0 : for (vi.origin();vi.more();vi++) {
6460 0 : Int nRow=vb.nRow();
6461 0 : Int nChan=vb.nChannel();
6462 0 : for (Int row=0; row<nRow; ++row) {
6463 0 : for (Int chn=0; chn<nChan; ++chn) {
6464 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6465 0 : ++counter;
6466 0 : if(counter==increment) {
6467 0 : counter=0;
6468 0 : Float f=vb.frequency()(chn)/C::c;
6469 0 : Float u=vb.uvw()(row)(0)*f;
6470 0 : Float v=vb.uvw()(row)(1)*f;
6471 0 : uvDistance(iVis)=sqrt(square(u)+square(v));
6472 0 : if(twoPol) {
6473 0 : amp(iVis)=sqrt((square(abs(vb.visCube()(0,chn,row)))+
6474 0 : square(abs(vb.visCube()(numCorrPol,chn,row))))/2.0);
6475 0 : if(hasCorrected)
6476 0 : correctedAmp(iVis)=
6477 0 : sqrt((square(abs(vb.correctedVisCube()(0,chn,row)))+
6478 0 : square(abs(vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6479 0 : if(hasModel)
6480 0 : modelAmp(iVis)=
6481 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)))+
6482 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row))))/2.0);
6483 0 : if(hasCorrected && hasModel)
6484 0 : residualAmp(iVis)=
6485 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
6486 0 : vb.correctedVisCube()(0,chn,row)))+
6487 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
6488 0 : vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6489 : }
6490 : else {
6491 0 : amp(iVis)=abs(vb.visCube()(0,chn,row));
6492 0 : if(hasCorrected)
6493 0 : correctedAmp(iVis)=abs(vb.correctedVisCube()(0,chn,row));
6494 0 : if(hasModel)
6495 0 : modelAmp(iVis)=abs(vb.modelVisCube()(0,chn,row));
6496 0 : if(hasCorrected && hasModel)
6497 0 : residualAmp(iVis)=
6498 0 : abs(vb.modelVisCube()(0,chn,row)-
6499 0 : vb.correctedVisCube()(0,chn,row));
6500 : }
6501 0 : if(uvDistance(iVis)>maxuvDistance) {
6502 0 : maxuvDistance=uvDistance(iVis);
6503 : }
6504 0 : if(amp(iVis)>maxAmp) {
6505 0 : maxAmp=amp(iVis);
6506 : }
6507 0 : if(hasCorrected && (correctedAmp(iVis)>maxCorrectedAmp)) {
6508 0 : maxCorrectedAmp=correctedAmp(iVis);
6509 : }
6510 0 : if(hasModel && (modelAmp(iVis)>maxModelAmp)) {
6511 0 : maxModelAmp=modelAmp(iVis);
6512 : }
6513 0 : if((hasModel&&hasCorrected) && (residualAmp(iVis)>maxResidualAmp)) {
6514 0 : maxResidualAmp=residualAmp(iVis);
6515 : }
6516 0 : ++iVis;
6517 : }
6518 : }
6519 : }
6520 : }
6521 : }
6522 : }
6523 :
6524 :
6525 :
6526 0 : if(maxuvDistance==0.0) {
6527 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6528 0 : this->unlock();
6529 0 : return false;
6530 : }
6531 :
6532 :
6533 :
6534 :
6535 :
6536 0 : Float Ymax(0.0);
6537 :
6538 0 : if (type.contains("corrected") && hasCorrected)
6539 0 : if(maxCorrectedAmp>Ymax) Ymax = maxCorrectedAmp;
6540 :
6541 0 : if (type.contains("model") && hasModel)
6542 0 : if(maxModelAmp>Ymax) Ymax = maxModelAmp;
6543 :
6544 0 : if (type.contains("residual") && (hasModel && hasCorrected))
6545 0 : if(maxResidualAmp>Ymax) Ymax = maxResidualAmp;
6546 :
6547 0 : if (type.contains("observed"))
6548 0 : if(maxAmp>Ymax) Ymax = maxAmp;
6549 :
6550 0 : if ((type=="all") || (type == ""))
6551 : {
6552 0 : if (maxAmp > Ymax) Ymax = maxAmp;
6553 0 : if(hasCorrected && (maxCorrectedAmp>Ymax)) Ymax = maxCorrectedAmp;
6554 0 : if(hasModel && (maxModelAmp>Ymax)) Ymax = maxModelAmp;
6555 0 : if((hasModel && hasCorrected) && maxResidualAmp>Ymax) Ymax = maxResidualAmp;
6556 : }
6557 :
6558 :
6559 0 : return false;
6560 :
6561 :
6562 : this->unlock();
6563 : return true;
6564 0 : } catch (AipsError x) {
6565 0 : this->unlock();
6566 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6567 0 : return false;
6568 0 : }
6569 : this->unlock();
6570 :
6571 : return true;
6572 0 : }
6573 :
6574 : // Plot the weights
6575 0 : Bool Imager::plotweights(const Bool gridded, const Int increment)
6576 : {
6577 :
6578 0 : if(!valid()) return false;
6579 0 : LogIO os(LogOrigin("imager", "plotweights()", WHERE));
6580 :
6581 0 : this->lock();
6582 : try {
6583 :
6584 :
6585 : os << LogIO::NORMAL // Loglevel PROGRESS
6586 : << "Plotting imaging weights for currently selected data"
6587 0 : << LogIO::POST;
6588 :
6589 0 : ROVisIter& vi(*rvi_p);
6590 0 : VisBuffer vb(vi);
6591 :
6592 0 : if(gridded) {
6593 0 : if(!assertDefinedImageParameters()) {this->unlock(); return false;}
6594 : // First find the gridded weights
6595 : Float uscale, vscale;
6596 : Int uorigin, vorigin;
6597 0 : uscale=(nx_p*mcellx_p.get("rad").getValue())/2.0;
6598 0 : vscale=(ny_p*mcelly_p.get("rad").getValue())/2.0;
6599 0 : uorigin=nx_p/2;
6600 0 : vorigin=ny_p/2;
6601 :
6602 : // Simply declare a big matrix
6603 0 : Float maxWeight=0.0;
6604 0 : Matrix<Float> gwt(nx_p,ny_p);
6605 0 : gwt=0.0;
6606 :
6607 : Float u, v;
6608 0 : Float sumwt=0.0;
6609 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6610 0 : for (vi.origin();vi.more();vi++) {
6611 0 : Int nRow=vb.nRow();
6612 0 : Int nChan=vb.nChannel();
6613 0 : for (Int row=0; row<nRow; ++row) {
6614 0 : for (Int chn=0; chn<nChan; ++chn) {
6615 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6616 0 : Float f=vb.frequency()(chn)/C::c;
6617 0 : u=vb.uvw()(row)(0)*f;
6618 0 : v=vb.uvw()(row)(1)*f;
6619 0 : Int ucell=Int(uscale*u+uorigin);
6620 0 : Int vcell=Int(vscale*v+vorigin);
6621 0 : if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
6622 0 : gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
6623 0 : sumwt+=vb.imagingWeight()(chn,row);
6624 0 : if(vb.imagingWeight()(chn,row)>maxWeight) {
6625 0 : maxWeight=vb.imagingWeight()(chn,row);
6626 : }
6627 : }
6628 0 : ucell=Int(-uscale*u+uorigin);
6629 0 : vcell=Int(-vscale*v+vorigin);
6630 0 : if((ucell>0)&&(ucell<nx_p)&&(vcell>0)&&(vcell<ny_p)) {
6631 0 : gwt(ucell,vcell)+=vb.imagingWeight()(chn,row);
6632 : }
6633 : }
6634 : }
6635 : }
6636 : }
6637 : }
6638 :
6639 0 : if(sumwt>0.0) {
6640 0 : os << LogIO::NORMAL << "Sum of weights = " << sumwt << endl; // Loglevel INFO
6641 : }
6642 : else {
6643 0 : this->unlock();
6644 : os << LogIO::SEVERE << "Sum of weights is zero: perhaps you need to weight the data"
6645 0 : << LogIO::POST;
6646 0 : return false;
6647 : }
6648 :
6649 :
6650 : //Float umax=Float(nx_p/2)/uscale;
6651 : //Float vmax=Float(ny_p/2)/vscale;
6652 :
6653 :
6654 0 : return false;
6655 0 : }
6656 : else {
6657 :
6658 : // Now do the points plot
6659 0 : Int nVis=0;
6660 0 : Int counter=0;
6661 0 : Float maxWeight=0.0;
6662 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6663 0 : for (vi.origin();vi.more();vi++) {
6664 0 : Int nRow=vb.nRow();
6665 0 : Int nChan=vb.nChannel();
6666 0 : for (Int row=0; row<nRow; ++row) {
6667 0 : for (Int chn=0; chn<nChan; ++chn) {
6668 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6669 0 : ++counter;
6670 0 : if(counter==increment) {
6671 0 : counter=0;
6672 0 : ++nVis;
6673 : }
6674 : }
6675 : }
6676 : }
6677 : }
6678 : }
6679 :
6680 0 : if(increment>1) {
6681 : os << LogIO::NORMAL // Loglevel INFO
6682 : << "For increment = " << increment << ", found " << nVis
6683 0 : << " points for plotting" << endl;
6684 : }
6685 : else {
6686 : os << LogIO::NORMAL // Loglevel INFO
6687 0 : << "Found " << nVis << " points for plotting" << endl;
6688 : }
6689 :
6690 0 : Float maxuvDistance=0.0;
6691 0 : Vector<Float> weights(nVis);
6692 0 : Vector<Float> uvDistance(nVis);
6693 0 : weights=0.0;
6694 0 : uvDistance=0.0;
6695 :
6696 0 : Int iVis=0;
6697 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6698 0 : for (vi.origin();vi.more();vi++) {
6699 0 : Int nRow=vb.nRow();
6700 0 : Int nChan=vb.nChannel();
6701 0 : for (Int row=0; row<nRow; ++row) {
6702 0 : for (Int chn=0; chn<nChan; ++chn) {
6703 0 : if(!vb.flag()(chn,row)&&vb.imagingWeight()(chn,row)>0.0) {
6704 0 : ++counter;
6705 0 : if(counter==increment) {
6706 0 : Float f=vb.frequency()(chn)/C::c;
6707 0 : Float u=vb.uvw()(row)(0)*f;
6708 0 : Float v=vb.uvw()(row)(1)*f;
6709 0 : uvDistance(iVis)=sqrt(square(u)+square(v));
6710 0 : weights(iVis)=vb.imagingWeight()(chn,row);
6711 0 : if(vb.imagingWeight()(chn,row)>maxWeight) {
6712 0 : maxWeight=vb.imagingWeight()(chn,row);
6713 : }
6714 0 : if(uvDistance(iVis)>maxuvDistance) {
6715 0 : maxuvDistance=uvDistance(iVis);
6716 : }
6717 0 : counter=0;
6718 0 : ++iVis;
6719 : }
6720 : }
6721 : }
6722 : }
6723 : }
6724 : }
6725 :
6726 0 : if(maxuvDistance==0.0) {
6727 0 : this->unlock();
6728 0 : os << LogIO::SEVERE << "Maximum uv distance is zero" << LogIO::POST;
6729 0 : return false;
6730 : }
6731 :
6732 :
6733 0 : return false;
6734 0 : }
6735 :
6736 :
6737 :
6738 : this->unlock();
6739 : return true;
6740 0 : } catch (AipsError x) {
6741 0 : this->unlock();
6742 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6743 0 : return false;
6744 0 : }
6745 : this->unlock();
6746 :
6747 : return true;
6748 0 : }
6749 :
6750 0 : Bool Imager::clipvis(const Quantity& threshold)
6751 : {
6752 :
6753 0 : if(!valid()) return false;
6754 :
6755 0 : LogIO os(LogOrigin("imager", "clipvis()", WHERE));
6756 :
6757 0 : this->lock();
6758 : try {
6759 :
6760 0 : Float thres=threshold.get("Jy").getValue();
6761 :
6762 : os << LogIO::NORMAL // Loglevel PROGRESS
6763 : << "Clipping visibilities where residual visibility > "
6764 0 : << thres << " Jy" << LogIO::POST;
6765 0 : if(!wvi_p){
6766 : os << LogIO::WARN
6767 : << "Cannot clip visibilities in read only mode of ms"
6768 0 : << LogIO::POST;
6769 0 : return false;
6770 : }
6771 0 : VisIter& vi(*wvi_p);
6772 0 : VisBuffer vb(vi);
6773 :
6774 :
6775 0 : vi.originChunks();
6776 0 : vi.origin();
6777 : // Making sure picking LL for [RR RL LR LL] correlations or [RR LL]
6778 0 : uInt numCorrPol=vb.modelVisCube().shape()(0) - 1 ;
6779 0 : Int nBad=0;
6780 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6781 0 : for (vi.origin();vi.more();vi++) {
6782 0 : Int nRow=vb.nRow();
6783 0 : Int nChan=vb.nChannel();
6784 0 : for (Int row=0; row<nRow; ++row) {
6785 0 : for (Int chn=0; chn<nChan; ++chn) {
6786 0 : if(!vb.flag()(chn,row)) {
6787 : Float residualAmp=
6788 0 : sqrt((square(abs(vb.modelVisCube()(0,chn,row)-
6789 0 : vb.correctedVisCube()(0,chn,row)))+
6790 0 : square(abs(vb.modelVisCube()(numCorrPol,chn,row)-
6791 0 : vb.correctedVisCube()(numCorrPol,chn,row))))/2.0);
6792 0 : if(residualAmp>thres) {
6793 0 : vb.flag()(chn,row)=true;
6794 0 : ++nBad;
6795 : }
6796 : }
6797 : }
6798 : }
6799 0 : vi.setFlag(vb.flag());
6800 : }
6801 : }
6802 :
6803 0 : os << LogIO::NORMAL << "Flagged " << nBad << " points" << LogIO::POST; // Loglevel INFO
6804 :
6805 0 : this->unlock();
6806 0 : return true;
6807 0 : } catch (AipsError x) {
6808 0 : this->unlock();
6809 0 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6810 0 : }
6811 0 : this->unlock();
6812 :
6813 0 : return true;
6814 0 : }
6815 :
6816 : // Plot various ids
6817 0 : Bool Imager::plotsummary()
6818 : {
6819 :
6820 0 : if(!valid()) return false;
6821 :
6822 0 : LogIO os(LogOrigin("imager", "plotsummary()", WHERE));
6823 :
6824 0 : os << LogIO::WARN << "NOT implemented " << LogIO::POST;
6825 0 : return false;
6826 :
6827 : this->lock();
6828 : try {
6829 : /*
6830 : os << "Plotting field and spectral window ids for currently selected data" << LogIO::POST;
6831 :
6832 : ROVisIter& vi(*rvi_p);
6833 : VisBuffer vb(vi);
6834 :
6835 : Int nVis=0;
6836 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6837 : for (vi.origin();vi.more();vi++) {
6838 : Int nRow=vb.nRow();
6839 : for (Int row=0; row<nRow; ++row) {
6840 : ++nVis;
6841 : }
6842 : }
6843 : }
6844 :
6845 : os << "Found " << nVis << " selected records" << LogIO::POST;
6846 :
6847 : Vector<Float> fieldId(nVis);
6848 : Vector<Float> spectralWindowId(nVis);
6849 : Vector<Double> t(nVis);
6850 :
6851 : Int maxFieldId=0;
6852 : Int maxSpectralWindowId=0;
6853 : Int iVis=0;
6854 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
6855 : for (vi.origin();vi.more();vi++) {
6856 : Int nRow=vb.nRow();
6857 : for (Int row=0; row<nRow; ++row) {
6858 : t(iVis)=vb.time()(row);
6859 : fieldId(iVis)=vb.fieldId()+1.0;
6860 : spectralWindowId(iVis)=vb.spectralWindow()+1.003;
6861 : if(Int(fieldId(iVis))>maxFieldId) maxFieldId=Int(fieldId(iVis));
6862 : if(Int(spectralWindowId(iVis))>maxSpectralWindowId)
6863 : maxSpectralWindowId=Int(spectralWindowId(iVis));
6864 : ++iVis;
6865 : }
6866 : }
6867 : }
6868 :
6869 : Double tStart=t(0);
6870 : Vector<Float> timeFloat(nVis);
6871 : for(Int i=0;i<nVis;++i) {
6872 : timeFloat(i)=Float(t(i)-tStart);
6873 : }
6874 :
6875 : MSColumns msc(*ms_p);
6876 : PGPlotter plotter=getPGPlotter();
6877 : plotter.subp(1, 2);
6878 : plotter.page();
6879 : plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0, Float(maxFieldId)*1.1);
6880 : plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
6881 : String xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
6882 : plotter.lab(xLabel, "ID", "Field IDs for " +imageName());
6883 : plotter.sci(1);
6884 : for (Int fid=0;fid<maxFieldId;++fid) {
6885 : String fieldName=msc.field().name()(fid);
6886 : plotter.text(1.02*timeFloat(nVis-1), Float(fid+1), fieldName);
6887 : }
6888 : plotter.pt(timeFloat,fieldId,-1);
6889 : plotter.page();
6890 : plotter.swin(timeFloat(0), timeFloat(nVis-1)*1.20, 0,
6891 : Float(maxSpectralWindowId)*1.1);
6892 : plotter.tbox("BCSNTZHFO", 0.0, 0, "ABCNTS", 0.0, 0);
6893 : xLabel="Time (offset from " + MVTime(tStart/86400.0).string() + ")";
6894 : plotter.lab(xLabel, "ID", "Spectral Window IDs for " +imageName());
6895 : plotter.sci(1);
6896 : for(Int spwId=0;spwId<maxSpectralWindowId;++spwId) {
6897 : Vector<Double> chanFreq=msc.spectralWindow().chanFreq()(spwId);
6898 : ostringstream spwString;
6899 : spwString<<chanFreq(0)/1.0e9<<" GHz";
6900 : plotter.text(1.02*timeFloat(nVis-1), Float(spwId+1),
6901 : spwString);
6902 : }
6903 : plotter.pt(timeFloat,spectralWindowId,-1);
6904 : plotter.iden();
6905 : this->unlock();
6906 : return true;
6907 : */
6908 : } catch (AipsError x) {
6909 : this->unlock();
6910 : os << LogIO::SEVERE << "Exception: " << x.getMesg() << LogIO::POST;
6911 : return false;
6912 : }
6913 :
6914 : this->unlock();
6915 :
6916 : return true;
6917 0 : }
6918 :
6919 :
6920 0 : Bool Imager::detached() const
6921 : {
6922 0 : if (ms_p.null()) {
6923 0 : LogIO os(LogOrigin("imager", "detached()", WHERE));
6924 : os << LogIO::SEVERE <<
6925 : "imager is detached - cannot perform operation." << endl <<
6926 0 : "Call imager.open('filename') to reattach." << LogIO::POST;
6927 0 : return true;
6928 0 : }
6929 0 : return false;
6930 : }
6931 :
6932 0 : Bool Imager::makemodelfromsd(const String& sdImage, const String& modelImage,
6933 : const String& lowPSF, String& maskImage)
6934 : {
6935 :
6936 0 : if(!valid()) return false;
6937 :
6938 0 : LogIO os(LogOrigin("imager", "makemodelfromsd()", WHERE));
6939 :
6940 : try {
6941 :
6942 0 : if(!Table::isReadable(sdImage)){
6943 : os << LogIO::SEVERE << "Single Dish " << sdImage
6944 0 : << " image is not readable" << LogIO::EXCEPTION;
6945 :
6946 0 : return false;
6947 : }
6948 :
6949 : os << LogIO::NORMAL << "Creating an initial model image " << modelImage // Loglevel INFO
6950 0 : << " from single dish image " << sdImage << LogIO::POST;
6951 :
6952 0 : CoordinateSystem coordsys;
6953 : //imagecoordinates(coordsys);
6954 0 : imagecoordinates2(coordsys);
6955 0 : String modelName=modelImage;
6956 0 : this->makeEmptyImage(coordsys, modelName, fieldid_p);
6957 :
6958 0 : PagedImage<Float> model(modelImage);
6959 0 : PagedImage<Float> low0(sdImage);
6960 0 : String sdObs=low0.coordinates().obsInfo().telescope();
6961 :
6962 0 : GaussianBeam lBeam;
6963 0 : ImageInfo lowInfo=low0.imageInfo();
6964 0 : lBeam=lowInfo.restoringBeam();
6965 :
6966 0 : Float beamFactor=-1.0;
6967 :
6968 :
6969 : // regrid the single dish image
6970 : {
6971 0 : ImageRegrid<Float> ir;
6972 0 : IPosition axes(3,0,1,3); // if its a cube, regrid the spectral too
6973 0 : ir.regrid(model, Interpolate2D::LINEAR, axes, low0);
6974 0 : }
6975 :
6976 :
6977 :
6978 : // Will need to make a complex image to apply the beam
6979 0 : TempImage<Complex> ctemp(model.shape(), model.coordinates());
6980 0 : if(lowPSF=="") {
6981 : os << LogIO::NORMAL // Loglevel INFO
6982 : << "Using primary beam of single dish to determine flux scale"
6983 0 : << LogIO::POST;
6984 :
6985 0 : TempImage<Float> beamTemp(model.shape(), model.coordinates());
6986 : //Make the PB accordingly
6987 0 : if(lBeam.isNull()) {
6988 :
6989 0 : if (doDefaultVP_p) {
6990 0 : if(telescope_p!=""){
6991 0 : ObsInfo myobsinfo=this->latestObsInfo();
6992 0 : myobsinfo.setTelescope(telescope_p);
6993 0 : coordsys.setObsInfo(myobsinfo);
6994 :
6995 0 : }
6996 : else{
6997 0 : if(sdObs != ""){
6998 0 : telescope_p=sdObs;
6999 0 : ObsInfo myobsinfo=this->latestObsInfo();
7000 0 : myobsinfo.setTelescope(telescope_p);
7001 0 : coordsys.setObsInfo(myobsinfo);
7002 0 : }
7003 : else{
7004 0 : telescope_p=coordsys.obsInfo().telescope();
7005 : }
7006 : }
7007 0 : beamTemp.setCoordinateInfo(coordsys);
7008 0 : this->makePBImage(beamTemp);
7009 :
7010 : }
7011 : else{
7012 0 : Table vpTable(vpTableStr_p);
7013 0 : this->makePBImage(vpTable, beamTemp);
7014 0 : }
7015 0 : StokesImageUtil::FitGaussianPSF(beamTemp, lBeam);
7016 0 : LatticeExprNode sumImage = sum(beamTemp);
7017 0 : beamFactor=sumImage.getFloat();
7018 :
7019 0 : }
7020 :
7021 :
7022 0 : }
7023 : else {
7024 : os << LogIO::NORMAL // Loglevel INFO
7025 : << "Using specified low resolution PSF to determine sd flux scale"
7026 0 : << LogIO::POST;
7027 : // regrid the single dish psf
7028 0 : PagedImage<Float> lowpsf0(lowPSF);
7029 0 : TempImage<Float> lowpsf(model.shape(), model.coordinates());
7030 : {
7031 0 : ImageRegrid<Float> ir;
7032 0 : IPosition axes(2,0,1); //
7033 0 : ir.regrid(lowpsf, Interpolate2D::LINEAR, axes, lowpsf0);
7034 0 : }
7035 0 : LatticeExprNode sumImage = sum(lowpsf);
7036 0 : beamFactor=sumImage.getFloat();
7037 0 : if(lBeam.isNull()) {
7038 0 : os << LogIO::NORMAL << "Finding SD beam from given PSF" << LogIO::POST; // Loglevel PROGRESS
7039 0 : StokesImageUtil::FitGaussianPSF(lowpsf0, lBeam);
7040 : }
7041 0 : }
7042 :
7043 :
7044 : // This factor comes from the beam volumes
7045 0 : if(sdScale_p!=1.0)
7046 : os << LogIO::DEBUG1
7047 : << "Multiplying single dish data by user specified factor "
7048 0 : << sdScale_p << LogIO::POST;
7049 0 : Float sdScaling = sdScale_p;
7050 0 : if(! lBeam.isNull()) {
7051 0 : Int directionIndex=model.coordinates().findCoordinate(Coordinate::DIRECTION);
7052 : DirectionCoordinate
7053 0 : directionCoord=model.coordinates().directionCoordinate(directionIndex);
7054 0 : Vector<String> units(2); units.set("arcsec");
7055 0 : directionCoord.setWorldAxisUnits(units);
7056 0 : Vector<Double> incr= directionCoord.increment();
7057 0 : if(beamFactor >0.0) {
7058 0 : beamFactor=1.0/beamFactor;
7059 : }
7060 : else{
7061 : // beamFactor=
7062 : // abs(incr(0)*incr(1))/(lBeam(0).get("arcsec").getValue()*lBeam(1).get("arcsec").getValue()*1.162);
7063 : //Brute Force for now.
7064 0 : IPosition imshape(4, nx_p, ny_p, 1, 1);
7065 0 : TempImage<Float> lowpsf(imshape, coordsys);
7066 0 : lowpsf.set(0.0);
7067 0 : IPosition center(4, Int((nx_p/4)*2), Int((ny_p/4)*2),0,0);
7068 0 : lowpsf.putAt(1.0, center);
7069 0 : StokesImageUtil::Convolve(lowpsf, lBeam, false);
7070 0 : LatticeExprNode sumImage = sum(lowpsf);
7071 0 : beamFactor=1.0/sumImage.getFloat();
7072 :
7073 :
7074 0 : }
7075 : os << LogIO::NORMAL << "Beam volume factor " // Loglevel INFO
7076 0 : << beamFactor << LogIO::POST;
7077 0 : sdScaling*=beamFactor;
7078 0 : }
7079 : else {
7080 0 : os << LogIO::WARN << "Insufficient information to scale correctly" << LogIO::POST;
7081 : }
7082 :
7083 : //Convert to Jy/pixel
7084 0 : model.copyData( (LatticeExpr<Float>)((model * sdScaling)));
7085 0 : model.setUnits(Unit("Jy/pixel"));
7086 :
7087 : //make a mask image
7088 0 : this->makeEmptyImage(coordsys, maskImage, fieldid_p);
7089 0 : PagedImage<Float> mask(maskImage);
7090 0 : mask.set(1.0);
7091 0 : ArrayLattice<Bool> sdMask(model.getMask());
7092 0 : mask.copyData( LatticeExpr<Float> (mask* ntrue(sdMask)*model));
7093 0 : StokesImageUtil::MaskFrom(mask, mask, Quantity(0.0, "Jy"));
7094 0 : model.copyData( LatticeExpr<Float> (mask*model));
7095 0 : return true;
7096 0 : } catch (AipsError x) {
7097 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
7098 0 : << LogIO::POST;
7099 0 : return false;
7100 0 : }
7101 :
7102 : return true;
7103 :
7104 :
7105 0 : }
7106 :
7107 :
7108 0 : Int Imager::interactivemask(const String& image, const String& mask,
7109 : Int& niter, Int& ncycles, String& thresh, const Bool forceReload){
7110 :
7111 0 : LogIO os(LogOrigin("Imager", "interactivemask()", WHERE));
7112 0 : if(Table::isReadable(mask)) {
7113 0 : if (! Table::isWritable(mask)) {
7114 0 : os << LogIO::WARN << "Mask image is not modifiable " << LogIO::POST;
7115 0 : return false;
7116 : }
7117 : //we should regrid here if image and mask do not match
7118 : }
7119 : else{
7120 0 : clone(image, mask);
7121 : }
7122 : #ifdef USE_GRPC
7123 0 : Quantity thr;
7124 0 : if ( ! Quantity::read(thr,thresh) ) thr = Quantity(0,"Jy");
7125 0 : float thold = (float) thr.get("Jy").getValue( );
7126 0 : grpcInteractiveClean::getManager( ).setControls( niter, ncycles, thold);
7127 : #endif
7128 0 : return false;
7129 0 : }
7130 :
7131 0 : Record Imager::iClean(const String& algorithm, const Int niter, const Double gain,
7132 : const Quantity& threshold,
7133 : const Bool displayprogress,
7134 : const Vector<String>& model,
7135 : const Vector<Bool>& keepfixed, const String& complist,
7136 : const Vector<String>& mask,
7137 : const Vector<String>& image,
7138 : const Vector<String>& residual,
7139 : const Vector<String>& psfnames,
7140 : const Bool interactive, const Int npercycle,
7141 : const String& masktemplate)
7142 : {
7143 0 : Record rstat;
7144 :
7145 0 : logSink_p.clearLocally();
7146 0 : LogIO os(LogOrigin("imager", "iClean()"), logSink_p);
7147 :
7148 0 : if(!ms_p.null()) {
7149 : //try
7150 : {
7151 :
7152 0 : Vector<String> amodel(model);
7153 0 : Vector<Bool> fixed(keepfixed);
7154 0 : Vector<String> amask(mask);
7155 0 : Vector<String> aimage(image);
7156 0 : Vector<String> aresidual(residual);
7157 0 : Vector<String> apsf(psfnames);
7158 :
7159 0 : if(String(algorithm) != "msmfs") ntaylor_p=1; /* masks increment by ntaylor_p only for msmfs */
7160 0 : uInt nmods = aresidual.nelements()/ntaylor_p;
7161 :
7162 0 : if( (apsf.nelements()==1) && apsf[0]==String(""))
7163 0 : apsf.resize();
7164 0 : if(!interactive){
7165 0 : rstat = clean(String(algorithm), niter, gain,
7166 : threshold, displayprogress,
7167 0 : amodel, fixed, String(complist), amask,
7168 0 : aimage, aresidual, apsf);
7169 : }
7170 : else{
7171 0 : if((amask.nelements()==0) || (amask[0]==String(""))){
7172 0 : amask.resize(amodel.nelements());
7173 0 : for (uInt k=0; k < amask.nelements(); ++k){
7174 0 : amask[k]=amodel[k]+String(".mask");
7175 : }
7176 : }
7177 0 : Vector<Bool> nointerac(nmods);
7178 0 : nointerac.set(false);
7179 0 : if(fixed.nelements() != nmods){
7180 0 : fixed.resize(nmods);
7181 0 : fixed.set(false);
7182 : }
7183 0 : Bool forceReload=true;
7184 0 : Int nloop=0;
7185 0 : if(npercycle != 0)
7186 0 : nloop=niter/npercycle;
7187 0 : Int continter=0;
7188 0 : Int elniter=npercycle;
7189 0 : ostringstream oos;
7190 0 : threshold.print(oos);
7191 0 : String thresh=String(oos);
7192 0 : if(String(masktemplate) != String("")){
7193 0 : continter=interactivemask(masktemplate, amask[0],
7194 : elniter, nloop, thresh);
7195 : }
7196 : else {
7197 : // do a zero component clean to get started
7198 0 : rstat=clean(String(algorithm), 0, gain,
7199 : threshold, displayprogress,
7200 0 : amodel, fixed, String(complist), amask,
7201 0 : aimage, aresidual, Vector<String>(0), false);
7202 :
7203 0 : for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
7204 0 : if(Table::isReadable(aimage[nIm]) && Table::isWritable(aresidual[nIm]) ){
7205 0 : PagedImage<Float> rest(aimage[nIm]);
7206 0 : PagedImage<Float> resi(aresidual[nIm]);
7207 0 : copyMask(resi, rest, "mask0");
7208 0 : }
7209 0 : forceReload=forceReload || (aresidual.nelements() >1);
7210 0 : continter=interactivemask(aresidual[nIm], amask[nIm],
7211 : elniter, nloop,thresh, forceReload);
7212 0 : forceReload=false;
7213 0 : if(continter>=1)
7214 0 : nointerac(nIm)=true;
7215 0 : if(continter==2)
7216 0 : fixed(nIm)=true;
7217 :
7218 : }
7219 0 : if(allEQ(nointerac, true)){
7220 0 : elniter=niter;
7221 : //make it do one more loop/clean but with all niter
7222 0 : nloop=1;
7223 : }
7224 : }
7225 0 : for (Int k=0; k < nloop; ++k){
7226 :
7227 0 : casacore::Quantity thrsh;
7228 0 : if(!casacore::Quantity::read(thrsh, thresh)){
7229 : os << LogIO::WARN << "Error interpreting threshold"
7230 0 : << LogIO::POST;
7231 0 : thrsh=casacore::Quantity(0, "Jy");
7232 0 : thresh="0.0Jy";
7233 : }
7234 0 : Vector<String> elpsf(0);
7235 : //Need to save psfs in interactive only once and lets do it the
7236 : //first time
7237 0 : if(k==0)
7238 0 : elpsf=apsf;
7239 0 : if(anyEQ(fixed, false)){
7240 0 : rstat = clean(String(algorithm), elniter, gain,
7241 : thrsh,
7242 : displayprogress,
7243 0 : amodel, fixed, String(complist),
7244 : amask,
7245 0 : aimage, aresidual, elpsf, k == 0);
7246 : //if clean converged... equivalent to stop
7247 0 : if(rstat.asBool("converged")){
7248 0 : continter=2;
7249 0 : fixed.set(true);
7250 : }
7251 0 : if(anyEQ(fixed, false) && anyEQ(nointerac,false)){
7252 0 : Int remainloop=nloop-k-1;
7253 0 : for (uInt nIm=0; nIm < nmods; nIm++){ //=ntaylor_p){
7254 0 : if(!nointerac(nIm)){
7255 0 : continter=interactivemask(aresidual[nIm], amask[nIm],
7256 :
7257 : elniter, remainloop,
7258 0 : thresh, (aresidual.nelements() >1));
7259 0 : if(continter>=1)
7260 0 : nointerac(nIm)=true;
7261 0 : if(continter==2)
7262 0 : fixed(nIm)=true;
7263 : }
7264 : }
7265 0 : k=nloop-remainloop-1;
7266 0 : if(allEQ(nointerac,true)){
7267 0 : elniter=niter-(k+1)*npercycle;
7268 : //make it do one more loop/clean but with remaining niter
7269 0 : k=nloop-2;
7270 : }
7271 : }
7272 : }
7273 0 : }
7274 : //Unset the mask in the residual
7275 : // Cause as requested in CAS-1768...
7276 0 : for (uInt nIm=0; nIm < aresidual.nelements(); ++nIm){
7277 0 : if(Table::isWritable(aresidual[nIm]) ){
7278 0 : PagedImage<Float> resi(aresidual[nIm]);
7279 0 : if(resi.hasRegion("mask0", RegionHandler::Masks)){
7280 0 : resi.setDefaultMask("");
7281 : }
7282 0 : }
7283 : }
7284 :
7285 0 : }
7286 :
7287 0 : os << "Restoring Image(s) with the clean-beam" << LogIO::POST;
7288 0 : restoreImages(aimage, (niter>=0) );
7289 0 : this->writeHistory(os);
7290 : try{
7291 : // write data processing history into image logtable
7292 0 : LoggerHolder imagelog (false);
7293 0 : LogSink& sink = imagelog.sink();
7294 0 : LogOrigin lor( String("imager"), String("clean()") );
7295 0 : LogMessage msg(lor);
7296 0 : sink.postLocally(msg);
7297 0 : MSHistoryColumns msHis(ms_p->history());
7298 0 : transferHistory(imagelog, msHis);
7299 0 : for (Int thismodel=0;thismodel<Int(aimage.nelements());++thismodel) {
7300 0 : if(Table::isWritable(aimage(thismodel))){
7301 0 : PagedImage<Float> restoredImage(aimage(thismodel),
7302 0 : TableLock(TableLock::AutoNoReadLocking));
7303 0 : LoggerHolder& log = restoredImage.logger();
7304 0 : log.append(imagelog);
7305 0 : log.flush();
7306 0 : restoredImage.table().relinquishAutoLocks(true);
7307 0 : }
7308 : }
7309 0 : }
7310 0 : catch(exception& x){
7311 :
7312 0 : this->unlock();
7313 0 : destroySkyEquation();
7314 0 : os << LogIO::WARN << "Caught exception: " << x.what()
7315 0 : << LogIO::POST;
7316 : os << LogIO::SEVERE << "This means your MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
7317 0 : <<LogIO::POST;
7318 : //continue and wrap up this function
7319 :
7320 0 : }
7321 0 : catch(...){
7322 0 : this->unlock();
7323 0 : destroySkyEquation();
7324 0 : os << LogIO::WARN << "Caught unknown exception" << LogIO::POST;
7325 : os << LogIO::SEVERE << "The MS/HISTORY table may be corrupted; you may consider deleting all the rows from this table"
7326 0 : <<LogIO::POST;
7327 :
7328 0 : }
7329 :
7330 :
7331 0 : } //catch (AipsError x) {
7332 : //os << LogIO::SEVERE << "Exception Reported: " << x.getMesg() << LogIO::POST;
7333 : // RETHROW(x);
7334 : // }
7335 : } else {
7336 0 : os << LogIO::SEVERE << "No MeasurementSet has been assigned, please run open." << LogIO::POST;
7337 : }
7338 0 : return rstat;
7339 0 : }
7340 :
7341 6 : Bool Imager::adviseChanSelex(Double& freqStart, Double& freqEnd,
7342 : const Double& freqStep, const MFrequency::Types& freqframe,
7343 : Vector< Vector<Int> >& spw, Vector< Vector<Int> >& start,
7344 : Vector< Vector<Int> >& nchan, const String& ms, const Int field_id, const Bool getFreqRange, const String spwselection){
7345 :
7346 12 : LogIO os(LogOrigin("imager", "adviseChanSelex"));
7347 6 : if(ms==String("")){
7348 0 : if(numMS_p < 1 || !rvi_p){
7349 : os << LogIO::SEVERE << "Data selection incomplete"
7350 0 : << LogIO::POST;
7351 0 : return false;
7352 : }
7353 : }
7354 6 : spw.resize();
7355 6 : start.resize();
7356 6 : nchan.resize();
7357 : try {
7358 6 : if(!getFreqRange){
7359 0 : Block<Vector<Int> > bnchan;
7360 0 : Block<Vector<Int> > bstart;
7361 0 : Block<Vector<Int> > bspw;
7362 : Double fS, fE;
7363 0 : fS=freqStart;
7364 0 : fE=freqEnd;
7365 0 : if(freqEnd < freqStart){
7366 0 : fS=freqEnd;
7367 0 : fE=freqStart;
7368 : }
7369 :
7370 0 : if(ms==String("")){
7371 0 : rvi_p->getSpwInFreqRange(bspw, bstart, bnchan, fS, fE, fabs(freqStep), freqframe);
7372 : }
7373 : else{
7374 0 : bnchan.resize(1);
7375 0 : bstart.resize(1);
7376 0 : bspw.resize(1);
7377 0 : MeasurementSet elms(String(ms), TableLock(TableLock::AutoNoReadLocking), Table::Old);
7378 0 : MSUtil::getSpwInFreqRange(bspw[0], bstart[0], bnchan[0], elms, fS, fE, fabs(freqStep), freqframe, field_id);
7379 0 : elms.relinquishAutoLocks(true);
7380 :
7381 0 : }
7382 0 : spw=Vector<Vector<Int> >(bspw.begin( ), bspw.end( ));
7383 0 : start=Vector<Vector<Int> >(bstart.begin( ), bstart.end( ));
7384 0 : nchan=Vector<Vector<Int> >(bnchan.begin( ), bnchan.end( ));
7385 0 : }
7386 : else{
7387 6 : if(ms==String("")){
7388 0 : rvi_p->getFreqInSpwRange(freqStart, freqEnd, freqframe);
7389 : }
7390 : else{
7391 6 : MeasurementSet elms(ms, TableLock(TableLock::AutoNoReadLocking), Table::Old);
7392 6 : MSSelection thisSelection;
7393 6 : String spsel=spwselection;
7394 6 : if(spsel=="")spsel="*";
7395 6 : thisSelection.setSpwExpr(spsel);
7396 6 : TableExprNode exprNode=thisSelection.toTableExprNode(&elms);
7397 6 : Matrix<Int> chanlist=thisSelection.getChanList();
7398 6 : if(chanlist.ncolumn() <3){
7399 0 : freqStart=-1.0;
7400 0 : freqEnd=-1.0;
7401 0 : return false;
7402 : }
7403 6 : Vector<Int> elspw=chanlist.column(0);
7404 6 : Vector<Int> elstart=chanlist.column(1);
7405 12 : Vector<Int> elnchan=Vector<Int> (chanlist.column(2)-elstart)+1;
7406 6 : MSUtil::getFreqRangeInSpw(freqStart, freqEnd, elspw, elstart, elnchan, elms, freqframe, field_id);
7407 6 : }
7408 :
7409 : }
7410 :
7411 :
7412 :
7413 :
7414 0 : } catch (AipsError x) {
7415 : os << LogIO::SEVERE << "Caught exception: " << x.getMesg()
7416 0 : << LogIO::POST;
7417 0 : return false;
7418 0 : }
7419 0 : catch (...){
7420 : os << LogIO::SEVERE << "Unknown exception handled"
7421 0 : << LogIO::POST;
7422 0 : return false;
7423 :
7424 0 : }
7425 :
7426 6 : return true;
7427 :
7428 6 : }
7429 :
7430 :
7431 :
7432 : } //# NAMESPACE CASA - END
7433 :
|