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