Line data Source code
1 : //# Calibrater.cc: Implementation of Calibrater.h
2 : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
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: Calibrater.cc,v 19.37 2006/03/16 01:28:09 gmoellen Exp $
27 :
28 : #include <casacore/tables/Tables/Table.h>
29 : #include <casacore/tables/Tables/TableRecord.h>
30 : #include <casacore/tables/Tables/TableDesc.h>
31 : #include <casacore/tables/Tables/TableLock.h>
32 : #include <casacore/tables/Tables/TableUtil.h>
33 : #include <casacore/tables/TaQL/TableParse.h>
34 : #include <casacore/tables/Tables/ArrColDesc.h>
35 : #include <casacore/tables/DataMan/TiledShapeStMan.h>
36 :
37 : #include <casacore/casa/System/AipsrcValue.h>
38 : #include <casacore/casa/Arrays/ArrayUtil.h>
39 : #include <casacore/casa/Arrays/ArrayLogical.h>
40 : #include <casacore/casa/Arrays/ArrayPartMath.h>
41 : //#include <casa/Arrays/ArrayMath.h>
42 : #include <casacore/ms/MeasurementSets/MSColumns.h>
43 : #include <casacore/ms/MSSel/MSFieldIndex.h>
44 : #include <casacore/ms/MSSel/MSSelection.h>
45 : #include <casacore/ms/MSSel/MSSelectionTools.h>
46 : #include <casacore/ms/MSOper/MSMetaData.h>
47 : #include <casacore/casa/BasicSL/Constants.h>
48 : #include <casacore/casa/Exceptions/Error.h>
49 : #include <iostream>
50 : #include <sstream>
51 : #include <casacore/casa/OS/File.h>
52 : #include <synthesis/MeasurementComponents/Calibrater.h>
53 : #include <synthesis/CalTables/CLPatchPanel.h>
54 : #include <synthesis/MeasurementComponents/CalSolVi2Organizer.h>
55 : #include <synthesis/MeasurementComponents/MSMetaInfoForCal.h>
56 : #include <synthesis/MeasurementComponents/VisCalSolver.h>
57 : #include <synthesis/MeasurementComponents/VisCalSolver2.h>
58 : #include <synthesis/MeasurementComponents/UVMod.h>
59 : #include <synthesis/MeasurementComponents/TsysGainCal.h>
60 : #include <msvis/MSVis/VisSetUtil.h>
61 : #include <msvis/MSVis/VisBuffAccumulator.h>
62 : #include <msvis/MSVis/VisibilityIterator2.h>
63 : #include <msvis/MSVis/VisBuffer2.h>
64 : #include <msvis/MSVis/ViFrequencySelection.h>
65 : #include <casacore/casa/Quanta/MVTime.h>
66 : #include <casacore/casa/Logging/LogMessage.h>
67 : #include <casacore/casa/Logging/LogIO.h>
68 : #include <casacore/casa/Utilities/Assert.h>
69 :
70 : #include <casacore/tables/Tables/SetupNewTab.h>
71 : #include <vector>
72 : using std::vector;
73 : #include <stdcasa/UtilJ.h>
74 :
75 : #ifdef _OPENMP
76 : #include <omp.h>
77 : #endif
78 :
79 : //#define REPORT_CAL_TIMING
80 :
81 : using namespace casacore;
82 : using namespace casa::utilj;
83 :
84 : using namespace casacore;
85 : using namespace casa::vpf;
86 :
87 : using namespace casacore;
88 : namespace casa { //# NAMESPACE CASA - BEGIN
89 :
90 165 : CalCounts::CalCounts():
91 165 : antennaMap_(),
92 165 : spwMap_(),
93 330 : totalMap_()
94 165 : {}
95 :
96 165 : void CalCounts::initCounts(Int NSpw, Int NAnt, Int NPol) {
97 165 : Vector<Int> polShape(NPol, 0);
98 165 : Vector<Int> singleVector(1, 0);
99 :
100 165 : totalMap_["expected"] = polShape;
101 165 : totalMap_["data_unflagged"] = polShape;
102 165 : totalMap_["above_minblperant"] = polShape;
103 165 : totalMap_["above_minsnr"] = polShape;
104 :
105 779 : for (Int spw=0; spw<NSpw; spw++) {
106 : // Init spw map keys
107 614 : spwMap_[spw]["expected"] = polShape;
108 614 : spwMap_[spw]["data_unflagged"] = polShape;
109 614 : spwMap_[spw]["above_minblperant"] = polShape;
110 614 : spwMap_[spw]["above_minsnr"] = polShape;
111 6206 : for (Int ant=0; ant<NAnt; ant++) {
112 : // Init antenna map keys
113 5592 : antennaMap_[spw][ant]["expected"] = polShape;
114 5592 : antennaMap_[spw][ant]["data_unflagged"] = polShape;
115 5592 : antennaMap_[spw][ant]["above_minblperant"] = polShape;
116 5592 : antennaMap_[spw][ant]["above_minsnr"] = polShape;
117 5592 : antennaMap_[spw][ant]["used_as_refant"] = singleVector;
118 : }
119 : }
120 165 : }
121 :
122 19605 : void CalCounts::addAntennaCounts(Int spw, Int NAnt, Int NPol, std::map<Int, std::map<String, Vector<Int>>> resultMap) {
123 : // Add the results to the antenna Map
124 19605 : Vector<Int> spwExp(NPol, 0), spwUnflag(NPol, 0), spwMinsnr(NPol, 0);
125 :
126 201590 : for (Int ant=0; ant<NAnt; ant++) {
127 181985 : if (resultMap.find(ant) == resultMap.end()) {continue;};
128 : // add if used as refant
129 181985 : antennaMap_[spw][ant]["used_as_refant"][0] += resultMap[ant]["used_as_refant"][0];
130 484921 : for (Int pol=0; pol<NPol; pol++) {
131 302936 : antennaMap_[spw][ant]["expected"][pol] += resultMap[ant]["expected"][pol];
132 302936 : antennaMap_[spw][ant]["data_unflagged"][pol] += resultMap[ant]["data_unflagged"][pol];
133 302936 : antennaMap_[spw][ant]["above_minblperant"][pol] += resultMap[ant]["above_minblperant"][pol];
134 302936 : antennaMap_[spw][ant]["above_minsnr"][pol] += resultMap[ant]["above_minsnr"][pol];
135 : // if any antenna value is good add to spw total
136 302936 : if (resultMap[ant]["expected"][pol] == 1) {spwExp[pol] = 1;};
137 302936 : if (resultMap[ant]["data_unflagged"][pol] == 1) {spwUnflag[pol] = 1;};
138 302936 : if (resultMap[ant]["above_minblperant"][pol] == 1) {spwMinsnr[pol] = 1;};
139 302936 : if (resultMap[ant]["above_minsnr"][pol] == 1) {spwMinsnr[pol] = 1;};
140 : }
141 : }
142 : // Add the totals to the spw Map
143 52720 : for (Int pol=0; pol<NPol; pol++) {
144 33115 : spwMap_[spw]["expected"][pol] += spwExp[pol];
145 33115 : spwMap_[spw]["data_unflagged"][pol] += spwUnflag[pol];
146 33115 : spwMap_[spw]["above_minblperant"][pol] += spwMinsnr[pol];
147 33115 : spwMap_[spw]["above_minsnr"][pol] += spwMinsnr[pol];
148 : // Acumulate total overall values
149 33115 : totalMap_["expected"][pol] += spwExp[pol];
150 33115 : totalMap_["data_unflagged"][pol] += spwUnflag[pol];
151 33115 : totalMap_["above_minblperant"][pol] += spwMinsnr[pol];
152 33115 : totalMap_["above_minsnr"][pol] += spwMinsnr[pol];
153 : }
154 :
155 19605 : }
156 :
157 165 : void CalCounts::updateRefants(Int NSpw, Int NAnt, std::map<Int, std::map<Int, Int>> refantMap) {
158 779 : for (Int spw=0; spw<NSpw; spw++) {
159 6206 : for (Int ant=0; ant<NAnt; ant++) {
160 5592 : antennaMap_[spw][ant]["used_as_refant"][0] += refantMap[spw][ant];
161 : }
162 : }
163 165 : }
164 :
165 5592 : Vector<Int> CalCounts::antMapVal(Int spw, Int ant, String gate) {
166 5592 : return antennaMap_[spw][ant][gate];
167 : }
168 :
169 2456 : Vector<Int> CalCounts::spwMapVal(Int spw, String gate) {
170 2456 : return spwMap_[spw][gate];
171 : }
172 :
173 660 : Vector<Int> CalCounts::totalMapVal(String gate) {
174 660 : return totalMap_[gate];
175 : }
176 :
177 165 : Record CalCounts::makeRecord(Int NAnt, Int NPol) {
178 :
179 165 : Vector<Int> totExp(NPol, 0), totUnflag(NPol, 0), totMinsnr(NPol, 0);
180 :
181 165 : nSpw = spwMap_.size();
182 165 : Record containerRec = Record();
183 165 : Record resultRec = Record();
184 :
185 165 : resultRec.define("expected", totalMap_["expected"]);
186 165 : resultRec.define("data_unflagged", totalMap_["data_unflagged"]);
187 165 : resultRec.define("above_minblperant", totalMap_["above_minblperant"]);
188 165 : resultRec.define("above_minsnr", totalMap_["above_minsnr"]);
189 :
190 779 : for (Int spw=0; spw<nSpw; spw++) {
191 614 : Record spwRec = Record();
192 614 : spwRec.define("expected", spwMap_[spw]["expected"]);
193 614 : spwRec.define("data_unflagged", spwMap_[spw]["data_unflagged"]);
194 614 : spwRec.define("above_minblperant", spwMap_[spw]["above_minblperant"]);
195 614 : spwRec.define("above_minsnr", spwMap_[spw]["above_minsnr"]);
196 6206 : for (Int ant=0; ant<NAnt; ant++) {
197 5592 : Record subRec = Record();
198 5592 : subRec.define("expected", antennaMap_[spw][ant]["expected"]);
199 5592 : subRec.define("data_unflagged", antennaMap_[spw][ant]["data_unflagged"]);
200 5592 : subRec.define("above_minblperant", antennaMap_[spw][ant]["above_minblperant"]);
201 5592 : subRec.define("above_minsnr", antennaMap_[spw][ant]["above_minsnr"]);
202 5592 : subRec.define("used_as_refant", antennaMap_[spw][ant]["used_as_refant"]);
203 5592 : spwRec.defineRecord(RecordFieldId("ant"+to_string(ant)), subRec);
204 5592 : }
205 614 : resultRec.defineRecord(RecordFieldId("spw"+to_string(spw)), spwRec);
206 614 : }
207 165 : containerRec.defineRecord(RecordFieldId("solvestats"), resultRec);
208 :
209 330 : return containerRec;
210 165 : }
211 :
212 0 : CalCounts::~CalCounts() {}
213 :
214 1177 : Calibrater::Calibrater():
215 1177 : ms_p(0),
216 1177 : mssel_p(0),
217 1177 : mss_p(0),
218 1177 : frequencySelections_p(nullptr),
219 1177 : msmc_p(0),
220 1177 : ve_p(0),
221 1177 : vc_p(),
222 1177 : svc_p(0),
223 1177 : histLockCounter_p(),
224 1177 : hist_p(0),
225 1177 : usingCalLibrary_(false),
226 1177 : corrDepFlags_(false), // default (==traditional behavior)
227 1177 : actRec_(),
228 1177 : resRec_(),
229 1177 : simdata_p(false),
230 3531 : ssvp_p()
231 : {
232 : // cout << "This is the NEW VI2-aware Calibrater" << endl;
233 1177 : }
234 :
235 9 : Calibrater::Calibrater(String msname):
236 9 : msname_p(msname),
237 9 : ms_p(0),
238 9 : mssel_p(0),
239 9 : mss_p(0),
240 9 : frequencySelections_p(nullptr),
241 9 : msmc_p(0),
242 9 : ve_p(0),
243 9 : vc_p(),
244 9 : svc_p(0),
245 9 : histLockCounter_p(),
246 9 : hist_p(0),
247 9 : usingCalLibrary_(false),
248 9 : corrDepFlags_(false), // default (==traditional behavior)
249 9 : actRec_(),
250 9 : resRec_(),
251 9 : simdata_p(false),
252 27 : ssvp_p()
253 : {
254 :
255 :
256 9 : if (!Table::isReadable(msname))
257 0 : throw(AipsError("MS "+msname+" does not exist."));
258 :
259 :
260 18 : logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL
261 9 : << "Arranging to calibrate MS: "+msname
262 18 : << LogIO::POST;
263 :
264 : // This is a bare Calibrater, intended to serve a VisEquation
265 :
266 : // We need very little of the usual stuff
267 :
268 : // A VisEquation
269 9 : ve_p = new VisEquation();
270 :
271 : // Reset the apply/solve VisCals
272 9 : reset();
273 :
274 9 : }
275 :
276 0 : Calibrater::Calibrater(const vi::SimpleSimVi2Parameters& ssvp):
277 0 : msname_p("<noms>"),
278 0 : ms_p(0),
279 0 : mssel_p(0),
280 0 : mss_p(0),
281 0 : frequencySelections_p(nullptr),
282 0 : msmc_p(0),
283 0 : ve_p(0),
284 0 : vc_p(),
285 0 : svc_p(0),
286 0 : histLockCounter_p(),
287 0 : hist_p(0),
288 0 : usingCalLibrary_(false),
289 0 : corrDepFlags_(false), // default (==traditional behavior)
290 0 : actRec_(),
291 0 : resRec_(),
292 0 : simdata_p(true),
293 0 : ssvp_p(ssvp)
294 : {
295 :
296 0 : logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL
297 : << "Arranging SIMULATED MS data for testing!!!!"
298 0 : << LogIO::POST;
299 :
300 : // A VisEquation
301 0 : ve_p = new VisEquation();
302 :
303 : // Initialize the meta-info server that will be shared with VisCals
304 0 : if (msmc_p) delete msmc_p;
305 0 : msmc_p = new MSMetaInfoForCal(ssvp_p);
306 :
307 : // Reset the apply/solve VisCals
308 0 : reset();
309 :
310 0 : }
311 :
312 : /*
313 : Calibrater::Calibrater(const Calibrater & other)
314 : {
315 : operator=(other);
316 : }
317 :
318 : Calibrater& Calibrater::operator=(const Calibrater & other)
319 : {
320 : ms_p=other.ms_p;
321 : mssel_p=other.mssel_p;
322 : ve_p=other.ve_p;
323 : histLockCounter_p=other.histLockCounter_p;
324 : hist_p=other.hist_p;
325 : historytab_p=other.historytab_p;
326 :
327 : return *this;
328 : }
329 : */
330 :
331 3346 : Calibrater::~Calibrater()
332 : {
333 1186 : cleanup();
334 1186 : if (msmc_p) delete msmc_p; msmc_p=0;
335 1186 : if (ms_p) delete ms_p; ms_p=0;
336 1186 : if (hist_p) delete hist_p; hist_p=0;
337 :
338 2160 : }
339 :
340 1177 : Calibrater* Calibrater::factory(Bool old) {
341 :
342 1177 : Calibrater* cal(NULL);
343 :
344 1177 : if (old)
345 203 : cal = new OldCalibrater();
346 : else
347 : //throw(AipsError("VI2-aware Calibrater not yet available..."));
348 974 : cal = new Calibrater();
349 :
350 1177 : return cal;
351 :
352 : }
353 :
354 9 : Calibrater* Calibrater::factory(String msname, Bool old) {
355 :
356 9 : Calibrater* cal(NULL);
357 :
358 9 : if (old)
359 9 : cal = new OldCalibrater(msname);
360 : else
361 0 : throw(AipsError("VI2-aware Calibrater not yet available..."));
362 : //cal = new Calibrater(msname);
363 :
364 9 : return cal;
365 :
366 : }
367 :
368 :
369 22947 : LogIO& Calibrater::logSink() {return sink_p;};
370 :
371 0 : String Calibrater::timerString() {
372 0 : ostringstream o;
373 0 : o <<" [user: " << timer_p.user () <<
374 0 : " system: " << timer_p.system () <<
375 0 : " real: " << timer_p.real () << "]";
376 0 : timer_p.mark();
377 0 : return o;
378 0 : };
379 :
380 463 : Bool Calibrater::initialize(MeasurementSet& inputMS,
381 : Bool compress,
382 : Bool addScratch, Bool addModel) {
383 :
384 463 : logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL3;
385 :
386 : try {
387 463 : timer_p.mark();
388 :
389 : // Set pointer ms_p from input MeasurementSet
390 463 : if (ms_p) {
391 0 : *ms_p=inputMS;
392 : } else {
393 463 : ms_p = new MeasurementSet(inputMS);
394 463 : AlwaysAssert(ms_p,AipsError);
395 : };
396 :
397 : // Remember the ms's name
398 463 : msname_p=ms_p->tableName();
399 :
400 : // Initialize the meta-info server that will be shared with VisCals
401 463 : if (msmc_p) delete msmc_p;
402 463 : msmc_p = new MSMetaInfoForCal(*ms_p);
403 :
404 : // Add/init scr cols, if requested (init is hard-wired)
405 463 : if (addScratch || addModel) {
406 97 : Bool alsoinit=true;
407 97 : VisSetUtil::addScrCols(*ms_p,addModel,addScratch,alsoinit,compress);
408 : }
409 :
410 : // Set the selected MeasurementSet to be the same initially
411 : // as the input MeasurementSet
412 : logSink() << LogIO::NORMAL
413 : << "Initializing nominal selection to the whole MS."
414 463 : << LogIO::POST;
415 :
416 463 : if (mssel_p) delete mssel_p;
417 463 : mssel_p=new MeasurementSet(*ms_p);
418 :
419 : // Create the associated VisEquation
420 : // TBD: move to ctor and make it non-pointer
421 463 : if (ve_p) {
422 0 : delete ve_p;
423 0 : ve_p=0;
424 : };
425 463 : ve_p=new VisEquation();
426 :
427 : // Reset the apply/solve VisCals
428 463 : reset(true,true);
429 :
430 463 : return true;
431 :
432 0 : } catch (AipsError x) {
433 0 : logSink() << LogOrigin("Calibrater","initialize",WHERE)
434 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
435 0 : << LogIO::POST;
436 0 : cleanup();
437 0 : if (msmc_p) delete msmc_p; msmc_p=NULL;
438 0 : if (ms_p) delete ms_p; ms_p=NULL;
439 0 : if (hist_p) delete hist_p; hist_p=NULL;
440 :
441 0 : throw(AipsError("Error in Calibrater::initialize()"));
442 : return false;
443 0 : }
444 : return false;
445 : }
446 :
447 :
448 : // Select data (using MSSelection syntax)
449 243 : void Calibrater::selectvis(const String& time,
450 : const String& spw,
451 : const String& scan,
452 : const String& field,
453 : const String& intent,
454 : const String& obsIDs,
455 : const String& baseline,
456 : const String& uvrange,
457 : const String& chanmode,
458 : const Int&,
459 : const Int&,
460 : const Int&,
461 : const MRadialVelocity&,
462 : const MRadialVelocity&,
463 : const String& msSelect)
464 : {
465 : // Define primary measurement set selection criteria
466 : // Inputs:
467 : // time
468 : // spw
469 : // scan
470 : // field
471 : // intent
472 : // obsIDs
473 : // baseline
474 : // uvrange
475 : // chanmode const String& Frequency/velocity selection mode
476 : // ("channel", "velocity" or
477 : // "opticalvelocity")
478 : // nchan const Int& No of channels to select
479 : // start const Int& Start channel to select
480 : // step const Int& Channel increment
481 : // mStart const MRadialVelocity& Start radial vel. to select
482 : // mStep const MRadialVelocity& Radial velocity increment
483 : // msSelect const String& MS selection string (TAQL)
484 : // Output to private data:
485 : //
486 243 : logSink() << LogOrigin("Calibrater","selectvis") << LogIO::NORMAL3;
487 :
488 : try {
489 :
490 : /*
491 : cout << "time = " << time << " " << time.length() <<endl;
492 : cout << "spw = " << spw << " " << spw.length() <<endl;
493 : cout << "scan = " << scan << " " << scan.length() <<endl;
494 : cout << "field = " << field << " " << field.length() <<endl;
495 : cout << "baseline = " << baseline << " " << baseline.length() << endl;
496 : cout << "uvrange = " << uvrange << " " << uvrange.length() << endl;
497 : */
498 :
499 243 : logSink() << "Selecting data" << LogIO::POST;
500 :
501 : // Apply selection to the original MeasurementSet
502 243 : logSink() << "Performing selection on MeasurementSet" << endl;
503 :
504 243 : if (mssel_p) {
505 243 : delete mssel_p;
506 243 : mssel_p=0;
507 : };
508 :
509 : // Report non-trivial user selections
510 243 : if (time!="")
511 4 : logSink() << " Selecting on time: '" << time << "'" << endl;
512 243 : if (spw!="")
513 42 : logSink() << " Selecting on spw: '" << spw << "'" << endl;
514 243 : if (scan!="")
515 21 : logSink() << " Selecting on scan: '" << scan << "'" << endl;
516 243 : if (field!="")
517 74 : logSink() << " Selecting on field: '" << field << "'" << endl;
518 243 : if (intent!="")
519 2 : logSink() << " Selecting on intent: '" << intent << "'" << endl;
520 243 : if(obsIDs != "")
521 2 : logSink() << " Selecting by observation IDs: '" << obsIDs << "'" << endl;
522 243 : if (baseline!="")
523 5 : logSink() << " Selecting on antenna/baseline: '" << baseline << "'" << endl;
524 243 : if (uvrange!="")
525 9 : logSink() << " Selecting on uvrange: '" << uvrange << "'" << endl;
526 243 : if (msSelect!="")
527 117 : logSink() << " Selecting with TaQL: '" << msSelect << "'" << endl;
528 243 : logSink() << LogIO::POST;
529 :
530 :
531 : // Assume no selection, for starters
532 243 : mssel_p = new MeasurementSet(*ms_p);
533 :
534 : // Apply user-supplied selection
535 243 : Bool nontrivsel=false;
536 :
537 : // Ensure use of a fresh MSSelection object
538 243 : if (mss_p) { delete mss_p; mss_p=NULL; }
539 243 : mss_p=new MSSelection();
540 486 : nontrivsel= mssSetData(*ms_p,
541 243 : *mssel_p,"",
542 : time,baseline,
543 : field,spw,
544 : uvrange,msSelect,
545 : "",scan,"",intent, obsIDs,mss_p);
546 :
547 : // Keep any MR status for the MS
548 243 : mssel_p->setMemoryResidentSubtables(ms_p->getMrsEligibility());
549 :
550 : // If non-trivial MSSelection invoked and nrow reduced:
551 243 : if(nontrivsel && mssel_p->nrow()<ms_p->nrow()) {
552 :
553 : // Escape if no rows selected
554 123 : if (mssel_p->nrow()==0)
555 0 : throw(AipsError("Specified selection selects zero rows!"));
556 :
557 : // ...otherwise report how many rows are selected
558 123 : logSink() << "By selection " << ms_p->nrow()
559 123 : << " rows are reduced to " << mssel_p->nrow()
560 123 : << LogIO::POST;
561 :
562 : // Revise the msmc_p so it contains only the _selected_ MS
563 123 : if (msmc_p) delete msmc_p;
564 123 : msmc_p = new MSMetaInfoForCal(*mssel_p, ms_p->tableName());
565 :
566 : }
567 : else {
568 : // Selection did nothing:
569 120 : logSink() << "Selection did not drop any rows" << LogIO::POST;
570 : }
571 :
572 : // Attempt to use MSSelection for channel selection
573 : // if user not using the old way
574 243 : if (chanmode=="none") {
575 243 : selectChannel(spw);
576 : }
577 : else {
578 : // Old-fashioned way now deprecated
579 : logSink() << LogIO::WARN
580 : << "You have used the old-fashioned mode parameter" << endl
581 : << "for channel selection." << endl
582 : << "Please begin using the new channel selection" << endl
583 0 : << "syntax in the spw parameter." << LogIO::POST;
584 0 : throw(AipsError("Old-fashioned chanmode selection is no longer supported!"));
585 : }
586 :
587 : }
588 0 : catch (MSSelectionError& x) {
589 : // Re-initialize with the existing MS
590 0 : logSink() << LogOrigin("Calibrater","selectvis",WHERE)
591 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
592 0 : << LogIO::POST;
593 : // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty
594 0 : initialize(*ms_p,false,false,false);
595 0 : throw(AipsError("Error in data selection specification: " + x.getMesg()));
596 0 : }
597 0 : catch (AipsError x) {
598 : // Re-initialize with the existing MS
599 0 : logSink() << LogOrigin("Calibrater","selectvis",WHERE)
600 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
601 0 : << LogIO::POST;
602 : // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty.
603 0 : initialize(*ms_p,false,false,false);
604 0 : throw(AipsError("Error in Calibrater::selectvis(): " + x.getMesg()));
605 0 : }
606 243 : };
607 :
608 :
609 177 : Bool Calibrater::setapply(const String& type,
610 : const Double& t,
611 : const String& table,
612 : const String& spw,
613 : const String& field,
614 : const String& interp,
615 : const Bool& calwt,
616 : const Vector<Int>& spwmap,
617 : const Vector<Double>& opacity)
618 : {
619 :
620 354 : logSink() << LogOrigin("Calibrater",
621 : "setapply(type, t, table, spw, field, interp, calwt, spwmap, opacity)")
622 354 : << LogIO::NORMAL;
623 :
624 :
625 : // cout << "Calibrater::setapply: field="<< field << endl;
626 :
627 : // Set record format for calibration table application information
628 177 : RecordDesc applyparDesc;
629 177 : applyparDesc.addField ("t", TpDouble);
630 177 : applyparDesc.addField ("table", TpString);
631 177 : applyparDesc.addField ("interp", TpString);
632 177 : applyparDesc.addField ("spw", TpArrayInt);
633 : // applyparDesc.addField ("field", TpArrayInt);
634 177 : applyparDesc.addField ("fieldstr", TpString);
635 177 : applyparDesc.addField ("calwt",TpBool);
636 177 : applyparDesc.addField ("spwmap",TpArrayInt);
637 177 : applyparDesc.addField ("opacity",TpArrayDouble);
638 :
639 : // Create record with the requisite field values
640 177 : Record applypar(applyparDesc);
641 177 : applypar.define ("t", t);
642 177 : applypar.define ("table", table);
643 :
644 : /*
645 : String cinterp=interp;
646 : // cinterp.erase(remove_if(cinterp.begin(), cinterp.end(), isspace), cinterp.end());
647 : cinterp.erase( remove( cinterp.begin(), cinterp.end(), ' ' ), cinterp.end() );
648 : */
649 :
650 177 : applypar.define ("interp", interp);
651 177 : applypar.define ("spw",getSpwIdx(spw));
652 : // applypar.define ("field",getFieldIdx(field));
653 177 : applypar.define ("fieldstr",field);
654 177 : applypar.define ("calwt",calwt);
655 177 : applypar.define ("spwmap",spwmap);
656 177 : applypar.define ("opacity", opacity);
657 :
658 177 : String upType=type;
659 177 : upType.upcase();
660 177 : if (upType=="")
661 : // Get type from table
662 139 : upType = calTableType(table);
663 :
664 353 : return setapply(upType,applypar);
665 :
666 179 : }
667 :
668 140 : Bool Calibrater::setapply (const String& type,
669 : const Record& applypar)
670 : {
671 140 : logSink() << LogOrigin("Calibrater", "setapply(type, applypar)");
672 :
673 : // First try to create the requested VisCal object
674 140 : VisCal *vc(NULL);
675 :
676 : try {
677 :
678 140 : if(!ok())
679 0 : throw(AipsError("Calibrater not prepared for setapply."));
680 :
681 140 : String upType=type;
682 140 : upType.upcase();
683 :
684 : logSink() << LogIO::NORMAL
685 : << "Arranging to APPLY:"
686 140 : << LogIO::POST;
687 :
688 : // Add a new VisCal to the apply list
689 140 : vc = createVisCal(upType,*msmc_p);
690 :
691 140 : vc->setApply(applypar);
692 :
693 : logSink() << LogIO::NORMAL << ". "
694 140 : << vc->applyinfo()
695 140 : << LogIO::POST;
696 :
697 140 : } catch (AipsError x) {
698 : logSink() << LogIO::SEVERE << x.getMesg()
699 : << " Check inputs and try again."
700 0 : << LogIO::POST;
701 0 : if (vc) delete vc;
702 0 : throw(AipsError("Error in Calibrater::setapply."));
703 : return false;
704 0 : }
705 :
706 : // Creation apparently successful, so add to the apply list
707 : // TBD: consolidate with above?
708 : try {
709 :
710 140 : uInt napp=vc_p.nelements();
711 140 : vc_p.resize(napp+1,false,true);
712 140 : vc_p[napp] = vc;
713 140 : vc=NULL;
714 :
715 : // Maintain sort of apply list
716 140 : ve_p->setapply(vc_p);
717 :
718 140 : return true;
719 :
720 0 : } catch (AipsError x) {
721 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
722 0 : << LogIO::POST;
723 0 : if (vc) delete vc;
724 0 : throw(AipsError("Error in Calibrater::setapply."));
725 : return false;
726 0 : }
727 : return false;
728 : }
729 :
730 :
731 : // Validate a Cal Library record
732 9 : Bool Calibrater::validatecallib(Record callib) {
733 :
734 9 : uInt ntab=callib.nfields();
735 36 : for (uInt itab=0;itab<ntab;++itab) {
736 :
737 27 : String tabname=callib.name(itab);
738 27 : Record thistabrec=callib.asRecord(itab);
739 27 : uInt ncl=thistabrec.nfields();
740 :
741 90 : for (uInt icl=0;icl<ncl;++icl) {
742 :
743 63 : if (thistabrec.dataType(icl)!=TpRecord)
744 27 : continue;
745 :
746 36 : Record thisicl=thistabrec.asRecord(icl);
747 : try {
748 36 : CalLibSlice::validateCLS(thisicl);
749 : }
750 36 : catch ( AipsError x) {
751 : logSink() << LogIO::SEVERE
752 : << "Caltable " << tabname
753 : << " is missing the following fields: "
754 : << x.getMesg()
755 36 : << LogIO::POST;
756 36 : }
757 :
758 36 : }
759 27 : }
760 9 : return true;
761 : }
762 :
763 :
764 : // Set up apply-able calibration via a Cal Library
765 14 : Bool Calibrater::setcallib2(Record callib, const MeasurementSet* ms) {
766 :
767 14 : logSink() << LogOrigin("Calibrater", "setcallib2(callib)");
768 :
769 : // cout << "Calibrater::setcallib2(callib) : " << boolalpha << callib << endl;
770 :
771 14 : uInt ntab=callib.nfields();
772 :
773 : // cout << "callib.nfields() = " << ntab << endl;
774 :
775 : // Do some preliminary per-table verification
776 30 : for (uInt itab=0;itab<ntab;++itab) {
777 :
778 16 : String tabname=callib.name(itab);
779 :
780 : // Trap parang
781 : // TBD...
782 : // if (tabname=="<parang>")
783 : // continue;
784 :
785 : // Insist that the table exists on disk
786 16 : if (!Table::isReadable(tabname))
787 0 : throw(AipsError("Caltable "+tabname+" does not exist."));
788 :
789 16 : }
790 :
791 : // Tables exist, so deploy them...
792 :
793 : // Local MS object for callib parsing (only)
794 : // MeasurementSet lms(msname_p,Table::Update);
795 : // TBD: Use selected MS instead (not yet available in OTF plotms context!)
796 : //const MeasurementSet lms(*mssel_p);
797 : //MeasurementSet lms(msname_p);
798 :
799 : // Local const MS object for callib parsing (only)
800 14 : const MeasurementSet *lmsp(0);
801 14 : if (ms) {
802 : // Use supplied MS (from outside), if specified...
803 : // TBD: should we verify same base MS as ms_p/mssel_p?
804 : //cout << "Using externally-specified MS!!" << endl;
805 0 : lmsp=ms;
806 : }
807 : else {
808 : // ...use internal one instead
809 : //cout << "Using internal MS (mssel_p)!!" << endl;
810 14 : lmsp=mssel_p;
811 : }
812 : // Reference for use below
813 14 : const MeasurementSet &lms(*lmsp);
814 :
815 :
816 30 : for (uInt itab=0;itab<ntab;++itab) {
817 :
818 16 : String tabname=callib.name(itab);
819 :
820 : // Get the type from the table
821 16 : String upType=calTableType(tabname);
822 16 : upType.upcase();
823 :
824 : // Add table name to the record
825 16 : Record thistabrec=callib.asrwRecord(itab);
826 16 : thistabrec.define("tablename",tabname);
827 :
828 : // First try to create the requested VisCal object
829 16 : VisCal *vc(NULL);
830 :
831 : try {
832 :
833 : // if(!ok())
834 : // throw(AipsError("Calibrater not prepared for setapply."));
835 :
836 : logSink() << LogIO::NORMAL
837 : << "Arranging to APPLY:"
838 16 : << LogIO::POST;
839 :
840 : // Add a new VisCal to the apply list
841 16 : vc = createVisCal(upType,*msmc_p);
842 :
843 : // ingest this table according to its callib
844 16 : vc->setCallib(thistabrec,lms);
845 :
846 0 : } catch (AipsError x) {
847 : logSink() << LogIO::SEVERE << x.getMesg()
848 : << " Check inputs and try again."
849 0 : << LogIO::POST;
850 0 : if (vc) delete vc;
851 0 : throw(AipsError("Error in Calibrater::callib2."));
852 : return false;
853 0 : }
854 :
855 : // Creation apparently successful, so add to the apply list
856 : // TBD: consolidate with above?
857 : try {
858 :
859 16 : uInt napp=vc_p.nelements();
860 16 : vc_p.resize(napp+1,false,true);
861 16 : vc_p[napp] = vc;
862 16 : vc=NULL;
863 :
864 : // Maintain sort of apply list
865 16 : ve_p->setapply(vc_p);
866 :
867 0 : } catch (AipsError x) {
868 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
869 0 : << LogIO::POST;
870 0 : if (vc) delete vc;
871 0 : throw(AipsError("Error in Calibrater::setapply."));
872 : return false;
873 0 : }
874 16 : }
875 :
876 : // Signal use of CalLibrary
877 14 : usingCalLibrary_=true;
878 :
879 : // All ok, if we get this far!
880 14 : return true;
881 :
882 : }
883 :
884 0 : Bool Calibrater::setmodel(const String& modelImage)
885 : {
886 0 : if (!svc_p)
887 0 : throw(AipsError("Calibrater::setmodel() called before Calibrater::setsolve()"));
888 0 : svc_p->setModel(modelImage);
889 0 : return true;
890 : }
891 :
892 76 : Bool Calibrater::setModel(const Vector<Double>& stokes) {
893 :
894 76 : if (ve_p) {
895 76 : Vector<Float> fstokes(stokes.shape());
896 76 : convertArray(fstokes,stokes);
897 76 : ve_p->setModel(fstokes);
898 76 : }
899 : else
900 0 : throw(AipsError("Error in Calibrater::setModel: no VisEquation."));
901 :
902 76 : return true;
903 :
904 : }
905 :
906 207 : Bool Calibrater::setsolve (const String& type,
907 : const String& solint,
908 : const String& table,
909 : const Bool append,
910 : const Double preavg,
911 : const String& apmode,
912 : const Int minblperant,
913 : const String& refant,
914 : const String& refantmode,
915 : const Bool solnorm,
916 : const String& normtype,
917 : const Float minsnr,
918 : const String& combine,
919 : const Int fillgaps,
920 : const String& cfcache,
921 : const Double painc,
922 : const Int fitorder,
923 : const Float fraction,
924 : const Int numedge,
925 : const String& radius,
926 : const Bool smooth,
927 : const Bool zerorates,
928 : const Bool globalsolve,
929 : const Int niter,
930 : const String& corrcomb,
931 : const Vector<Double>& delaywindow,
932 : const Vector<Double>& ratewindow,
933 : const Vector<Bool>& paramactive,
934 : const Bool concatspws,
935 : const String& solmode,
936 : const Vector<Double>& rmsthresh
937 : )
938 : {
939 :
940 207 : logSink() << LogOrigin("Calibrater","setsolve") << LogIO::NORMAL3;
941 :
942 : // Create a record description containing the solver parameters
943 207 : RecordDesc solveparDesc;
944 207 : solveparDesc.addField ("solint", TpString);
945 207 : solveparDesc.addField ("preavg", TpDouble);
946 207 : solveparDesc.addField ("apmode", TpString);
947 207 : solveparDesc.addField ("refant", TpArrayInt);
948 207 : solveparDesc.addField ("refantmode", TpString);
949 207 : solveparDesc.addField ("minblperant", TpInt);
950 207 : solveparDesc.addField ("table", TpString);
951 207 : solveparDesc.addField ("append", TpBool);
952 207 : solveparDesc.addField ("solnorm", TpBool);
953 207 : solveparDesc.addField ("normtype", TpString);
954 207 : solveparDesc.addField ("type", TpString);
955 207 : solveparDesc.addField ("combine", TpString);
956 207 : solveparDesc.addField ("maxgap", TpInt);
957 207 : solveparDesc.addField ("cfcache", TpString);
958 207 : solveparDesc.addField ("painc", TpDouble);
959 207 : solveparDesc.addField ("fitorder", TpInt);
960 207 : solveparDesc.addField ("solmode", TpString);
961 207 : solveparDesc.addField ("rmsthresh", TpArrayDouble);
962 :
963 : // fringe-fit specific fields
964 207 : solveparDesc.addField ("zerorates", TpBool);
965 207 : solveparDesc.addField ("minsnr", TpFloat);
966 207 : solveparDesc.addField ("globalsolve", TpBool);
967 207 : solveparDesc.addField ("delaywindow", TpArrayDouble);
968 207 : solveparDesc.addField ("ratewindow", TpArrayDouble);
969 207 : solveparDesc.addField ("niter", TpInt);
970 207 : solveparDesc.addField ("corrcomb", TpString);
971 207 : solveparDesc.addField ("paramactive", TpArrayBool);
972 207 : solveparDesc.addField ("concatspws", TpBool);
973 :
974 : // single dish specific fields
975 207 : solveparDesc.addField ("fraction", TpFloat);
976 207 : solveparDesc.addField ("numedge", TpInt);
977 207 : solveparDesc.addField ("radius", TpString);
978 207 : solveparDesc.addField ("smooth", TpBool);
979 :
980 :
981 : // Create a solver record with the requisite field values
982 207 : Record solvepar(solveparDesc);
983 207 : solvepar.define ("solint", solint);
984 207 : solvepar.define ("preavg", preavg);
985 207 : String upmode=apmode;
986 207 : upmode.upcase();
987 207 : solvepar.define ("apmode", upmode);
988 207 : solvepar.define ("refant", getRefantIdxList(refant));
989 207 : solvepar.define ("refantmode", refantmode);
990 207 : solvepar.define ("minblperant", minblperant);
991 207 : solvepar.define ("table", table);
992 207 : solvepar.define ("append", append);
993 207 : solvepar.define ("solnorm", solnorm);
994 207 : solvepar.define ("normtype", normtype);
995 : // Fringe-fit specific
996 207 : solvepar.define ("minsnr", minsnr);
997 207 : solvepar.define ("zerorates", zerorates);
998 207 : solvepar.define ("globalsolve", globalsolve);
999 207 : solvepar.define ("niter", niter);
1000 207 : solvepar.define ("corrcomb", corrcomb);
1001 207 : solvepar.define ("delaywindow", delaywindow);
1002 207 : solvepar.define ("ratewindow", ratewindow);
1003 207 : solvepar.define ("solmode", solmode);
1004 207 : solvepar.define ("rmsthresh", rmsthresh);
1005 207 : solvepar.define ("paramactive", paramactive);
1006 207 : solvepar.define ("concatspws", concatspws);
1007 :
1008 207 : String uptype=type;
1009 207 : uptype.upcase();
1010 207 : solvepar.define ("type", uptype);
1011 :
1012 207 : String upcomb=combine;
1013 207 : upcomb.upcase();
1014 207 : solvepar.define("combine",upcomb);
1015 207 : solvepar.define("maxgap",fillgaps);
1016 207 : solvepar.define ("cfcache", cfcache);
1017 207 : solvepar.define ("painc", painc);
1018 207 : solvepar.define("fitorder", fitorder);
1019 :
1020 : // single dish specific
1021 207 : solvepar.define("fraction", fraction);
1022 207 : solvepar.define("numedge", numedge);
1023 207 : solvepar.define("radius", radius);
1024 207 : solvepar.define("smooth", smooth);
1025 :
1026 413 : return setsolve(type,solvepar);
1027 211 : }
1028 :
1029 0 : Bool Calibrater::setsolvebandpoly(const String& table,
1030 : const Bool& append,
1031 : const String& solint,
1032 : const String& combine,
1033 : const Vector<Int>& degree,
1034 : const Bool& visnorm,
1035 : const Bool& solnorm,
1036 : const Int& maskcenter,
1037 : const Float& maskedge,
1038 : const String& refant) {
1039 :
1040 0 : logSink() << LogOrigin("Calibrater","setsolvebandpoly") << LogIO::NORMAL3;
1041 :
1042 : // TBD: support solution interval!
1043 :
1044 : // Create a record description containing the solver parameters
1045 0 : RecordDesc solveparDesc;
1046 0 : solveparDesc.addField ("table", TpString);
1047 0 : solveparDesc.addField ("append", TpBool);
1048 0 : solveparDesc.addField ("solint", TpString);
1049 0 : solveparDesc.addField ("combine", TpString);
1050 0 : solveparDesc.addField ("degree", TpArrayInt);
1051 0 : solveparDesc.addField ("visnorm", TpBool);
1052 0 : solveparDesc.addField ("solnorm", TpBool);
1053 0 : solveparDesc.addField ("maskcenter", TpInt);
1054 0 : solveparDesc.addField ("maskedge", TpFloat);
1055 0 : solveparDesc.addField ("refant", TpArrayInt);
1056 :
1057 : // solveparDesc.addField ("preavg", TpDouble);
1058 : // solveparDesc.addField ("phaseonly", TpBool);
1059 :
1060 : // Create a solver record with the requisite field values
1061 0 : Record solvepar(solveparDesc);
1062 0 : solvepar.define ("table", table);
1063 0 : solvepar.define ("append", append);
1064 0 : solvepar.define ("solint",solint);
1065 0 : String upcomb=combine;
1066 0 : upcomb.upcase();
1067 0 : solvepar.define ("combine",combine);
1068 0 : solvepar.define ("degree", degree);
1069 0 : solvepar.define ("visnorm", visnorm);
1070 0 : solvepar.define ("solnorm", solnorm);
1071 0 : solvepar.define ("maskcenter", maskcenter);
1072 0 : solvepar.define ("maskedge", maskedge);
1073 0 : solvepar.define ("refant", getRefantIdxList(refant));
1074 :
1075 :
1076 : // solvepar.define ("t", t);
1077 : // solvepar.define ("preavg", preavg);
1078 : // solvepar.define ("phaseonly", phaseonly);
1079 :
1080 :
1081 0 : return setsolve("BPOLY",solvepar);
1082 :
1083 0 : }
1084 :
1085 1 : Bool Calibrater::setsolvegainspline(const String& table,
1086 : const Bool& append,
1087 : const String& apmode,
1088 : const Double& splinetime,
1089 : const Double& preavg,
1090 : const Int& numpoint,
1091 : const Double& phasewrap,
1092 : const String& refant) {
1093 :
1094 1 : logSink() << LogOrigin("Calibrater","setsolvegainspline") << LogIO::NORMAL3;
1095 :
1096 : // Create a record description containing the solver parameters
1097 1 : RecordDesc solveparDesc;
1098 1 : solveparDesc.addField ("table", TpString);
1099 1 : solveparDesc.addField ("append", TpBool);
1100 1 : solveparDesc.addField ("apmode", TpString);
1101 1 : solveparDesc.addField ("splinetime", TpDouble);
1102 1 : solveparDesc.addField ("preavg", TpDouble);
1103 1 : solveparDesc.addField ("refant", TpArrayInt);
1104 1 : solveparDesc.addField ("numpoint", TpInt);
1105 1 : solveparDesc.addField ("phasewrap", TpDouble);
1106 :
1107 : // Create a solver record with the requisite field values
1108 1 : Record solvepar(solveparDesc);
1109 1 : solvepar.define ("table", table);
1110 1 : solvepar.define ("append", append);
1111 1 : String upMode=apmode;
1112 1 : upMode.upcase();
1113 1 : solvepar.define ("apmode", upMode);
1114 1 : solvepar.define ("splinetime",splinetime);
1115 1 : solvepar.define ("preavg", preavg);
1116 1 : solvepar.define ("refant", getRefantIdxList(refant));
1117 1 : solvepar.define ("numpoint",numpoint);
1118 1 : solvepar.define ("phasewrap",phasewrap);
1119 :
1120 2 : return setsolve("GSPLINE",solvepar);
1121 :
1122 1 : }
1123 :
1124 169 : Bool Calibrater::setsolve (const String& type,
1125 : const Record& solvepar) {
1126 :
1127 : // Attempt to create the solvable object
1128 169 : SolvableVisCal *svc(NULL);
1129 : try {
1130 :
1131 169 : if(!ok())
1132 0 : throw(AipsError("Calibrater not prepared for setsolve."));
1133 :
1134 169 : String upType = type;
1135 169 : upType.upcase();
1136 :
1137 : // Clean out any old solve that was lying around
1138 169 : unsetsolve();
1139 :
1140 : logSink() << LogIO::NORMAL
1141 : << "Arranging to SOLVE:"
1142 169 : << LogIO::POST;
1143 :
1144 : // Create the new SolvableVisCal
1145 169 : svc = createSolvableVisCal(upType,*msmc_p);
1146 169 : svc->setSolve(solvepar);
1147 :
1148 : logSink() << LogIO::NORMAL << ". "
1149 168 : << svc->solveinfo()
1150 168 : << LogIO::POST;
1151 :
1152 : // Creation apparently successful, keep it
1153 168 : svc_p=svc;
1154 168 : svc=NULL;
1155 :
1156 : // if calibration specific data filter is necessary
1157 : // keep configuration parameter as a record
1158 168 : setCalFilterConfiguration(upType, solvepar);
1159 :
1160 168 : return true;
1161 :
1162 170 : } catch (AipsError x) {
1163 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1164 1 : << LogIO::POST;
1165 1 : unsetsolve();
1166 1 : if (svc) delete svc;
1167 1 : throw(AipsError("Error in Calibrater::setsolve."));
1168 : return false;
1169 2 : }
1170 : return false;
1171 : }
1172 :
1173 212 : Vector<Int> Calibrater::convertSetToVector(set<Int> selset){
1174 212 : Vector<Int> vtmpint(selset.begin(), selset.size(),0);
1175 212 : return vtmpint;
1176 : }
1177 :
1178 53 : Vector<Int> Calibrater::getSelectedSpws() {
1179 53 : MSMetaData msmdtmp(mssel_p, 50.0);
1180 53 : set<uInt> selspwset = msmdtmp.getSpwIDs();
1181 53 : Vector<Int> res(selspwset.begin(), selspwset.size(),0);
1182 106 : return res;
1183 53 : }
1184 :
1185 53 : Vector<String> Calibrater::getSelectedIntents() {
1186 53 : MSMetaData msmdtmp(mssel_p, 50.0);
1187 53 : set<String> selintentset = msmdtmp.getIntents();
1188 53 : Vector<String> res(selintentset.begin(), selintentset.size(),0);
1189 106 : return res;
1190 53 : }
1191 :
1192 53 : Vector<String> Calibrater::getApplyTables() {
1193 53 : set<String> applytableset;
1194 53 : Int numtables = vc_p.nelements();
1195 53 : string space_delimiter = " ";
1196 53 : vector<string> words{};
1197 53 : size_t pos = 0;
1198 53 : string applyinf;
1199 :
1200 : // parse through the apply info
1201 : // Grab all the tables and put them in a vector
1202 53 : if (numtables > 0){
1203 22 : for (Int i=0;i<numtables;i++){
1204 12 : applyinf = vc_p[i]->applyinfo();
1205 94 : while ((pos=applyinf.find(space_delimiter))!=string::npos) {
1206 82 : words.push_back(applyinf.substr(0, pos));
1207 82 : applyinf.erase(0, pos+space_delimiter.length());
1208 : }
1209 106 : for (const auto &str : words){
1210 94 : if (str.rfind("table=",0) == 0){
1211 14 : applytableset.insert(str.substr(6));
1212 : }
1213 : }
1214 : }
1215 : }
1216 53 : Vector<String> res(applytableset.begin(),applytableset.size(),0);
1217 106 : return res;
1218 53 : }
1219 :
1220 53 : Vector<String> Calibrater::getSolveTable() {
1221 53 : string solveinf;
1222 53 : set<String> solvetableset;
1223 53 : string space_delimiter = " ";
1224 53 : vector<string> words{};
1225 53 : size_t pos = 0;
1226 :
1227 : // Parse through the solve info
1228 : // and extract the applied solve table into a vector
1229 53 : if (svc_p){
1230 53 : solveinf = svc_p->solveinfo();
1231 529 : while ((pos=solveinf.find(space_delimiter)) !=string::npos) {
1232 476 : words.push_back(solveinf.substr(0, pos));
1233 476 : solveinf.erase(0, pos+space_delimiter.length());
1234 : }
1235 529 : for (const auto &str : words) {
1236 476 : if (str.rfind("table=",0) == 0){
1237 53 : solvetableset.insert(str.substr(6));
1238 : }
1239 : }
1240 : }
1241 53 : Vector<String> res(solvetableset.begin(), solvetableset.size(),0);
1242 106 : return res;
1243 53 : }
1244 :
1245 53 : Bool Calibrater::getIteratorSelection(Vector<Int>* observationlist, Vector<Int>* scanlist, Vector<Int>* fieldlist, Vector<Int>* antennalist) {
1246 : // get the observation, scan, field, and antenna from the iterator
1247 53 : set<Int> selobsset;
1248 53 : set<Int> selscanset;
1249 53 : set<Int> selfieldset;
1250 53 : set<Int> selantset;
1251 :
1252 106 : vi::VisibilityIterator2 vi(*mssel_p);
1253 53 : vi.originChunks();
1254 53 : vi.origin();
1255 53 : vi::VisBuffer2 *vb = vi.getVisBuffer();
1256 :
1257 261 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()){
1258 107150 : for (vi.origin (); vi.more(); vi.next()){
1259 : // get obs ids
1260 106942 : selobsset.insert(vb->observationId()(0));
1261 : // get scan ids
1262 106942 : selscanset.insert(vb->scan()(0));
1263 : // get field ids
1264 106942 : selfieldset.insert(vb->fieldId()(0));
1265 : }
1266 : }
1267 4495 : for (auto & ant : vb->antenna1()){
1268 4442 : selantset.insert(ant);
1269 53 : }
1270 4495 : for (auto & ant : vb->antenna2()){
1271 4442 : selantset.insert(ant);
1272 53 : }
1273 :
1274 53 : *observationlist = convertSetToVector(selobsset);
1275 53 : *scanlist = convertSetToVector(selscanset);
1276 53 : *fieldlist = convertSetToVector(selfieldset);
1277 53 : *antennalist = convertSetToVector(selantset);
1278 :
1279 53 : return true;
1280 53 : }
1281 :
1282 53 : Record Calibrater::returndict()
1283 : {
1284 : // Create record and subrecrds for selection data
1285 53 : Record rec;
1286 53 : Record selectVisRec;
1287 :
1288 53 : Vector<Int> selscanlist;
1289 53 : Vector<Int> selfieldlist;
1290 53 : Vector<Int> selantlist;
1291 53 : Vector<Int> selobslist;
1292 :
1293 53 : getIteratorSelection(&selobslist, &selscanlist, &selfieldlist, &selantlist);
1294 :
1295 : // Define sub-record for selection parameters
1296 53 : selectVisRec.define("antennas", selantlist);
1297 53 : selectVisRec.define("field", selfieldlist);
1298 53 : selectVisRec.define("spw", getSelectedSpws());
1299 53 : selectVisRec.define("scan", selscanlist);
1300 53 : selectVisRec.define("observation", selobslist);
1301 53 : selectVisRec.define("intents", getSelectedIntents());
1302 :
1303 : // Create a record with current calibrater state information
1304 : //rec.define("antennas", selantlist);
1305 : //rec.define("field", selfieldlist);
1306 : //rec.define("spw", getSelectedSpws());
1307 : //rec.define("scan", selscanlist);
1308 : //rec.define("observation", selobslist);
1309 : //rec.define("intents", getSelectedIntents());
1310 53 : rec.defineRecord("selectvis", selectVisRec);
1311 53 : rec.define("apply_tables", getApplyTables());
1312 53 : rec.define("solve_tables", getSolveTable());
1313 :
1314 53 : rec.merge(resRec_);
1315 :
1316 106 : return rec;
1317 53 : }
1318 :
1319 0 : Bool Calibrater::state() {
1320 :
1321 0 : logSink() << LogOrigin("Calibrater","state") << LogIO::NORMAL3;
1322 :
1323 0 : applystate();
1324 0 : solvestate();
1325 :
1326 0 : return true;
1327 :
1328 : }
1329 :
1330 302 : Bool Calibrater::applystate() {
1331 :
1332 :
1333 : // logSink() << LogOrigin("Calibrater","applystate") << LogIO::NORMAL;
1334 :
1335 : logSink() << LogIO::NORMAL
1336 : << "The following calibration terms are arranged for apply:"
1337 302 : << LogIO::POST;
1338 :
1339 302 : Int napp(vc_p.nelements());
1340 302 : if (napp>0)
1341 384 : for (Int iapp=0;iapp<napp;++iapp)
1342 : logSink() << LogIO::NORMAL << ". "
1343 446 : << vc_p[iapp]->applyinfo()
1344 446 : << LogIO::POST;
1345 : else
1346 : logSink() << LogIO::NORMAL << ". "
1347 : << "(None)"
1348 141 : << LogIO::POST;
1349 :
1350 302 : return true;
1351 :
1352 : }
1353 :
1354 :
1355 207 : Bool Calibrater::solvestate() {
1356 :
1357 : // logSink() << LogOrigin("Calibrater","solvestate") << LogIO::NORMAL;
1358 :
1359 : logSink() << LogIO::NORMAL
1360 : << "The following calibration term is arranged for solve:"
1361 207 : << LogIO::POST;
1362 :
1363 207 : if (svc_p)
1364 : logSink() << LogIO::NORMAL << ". "
1365 207 : << svc_p->solveinfo()
1366 207 : << LogIO::POST;
1367 : else
1368 : logSink() << LogIO::NORMAL << ". "
1369 : << "(None)"
1370 0 : << LogIO::POST;
1371 :
1372 207 : return true;
1373 : }
1374 :
1375 2227 : Bool Calibrater::reset(const Bool& apply, const Bool& solve) {
1376 :
1377 : // logSink() << LogOrigin("Calibrater","reset") << LogIO::NORMAL;
1378 :
1379 : // Delete the VisCal apply list
1380 2227 : if (apply)
1381 2227 : unsetapply();
1382 :
1383 : // Delete the VisCal solve object
1384 2227 : if (solve)
1385 2227 : unsetsolve();
1386 :
1387 2227 : return true;
1388 : }
1389 :
1390 : // Delete all (default) or one VisCal in apply list
1391 2251 : Bool Calibrater::unsetapply(const Int& which) {
1392 :
1393 : // logSink() << LogOrigin("Calibrater","unsetapply") << LogIO::NORMAL;
1394 :
1395 : try {
1396 2251 : if (which<0) {
1397 2470 : for (uInt i=0;i<vc_p.nelements();i++)
1398 219 : if (vc_p[i]) delete vc_p[i];
1399 2251 : vc_p.resize(0,true);
1400 : } else {
1401 0 : if (vc_p[which]) delete vc_p[which];
1402 0 : vc_p.remove(which);
1403 : }
1404 :
1405 : // Maintain size/sort of apply list
1406 2251 : if(ve_p) ve_p->setapply(vc_p);
1407 :
1408 2251 : return true;
1409 0 : } catch (AipsError x) {
1410 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1411 0 : << LogIO::POST;
1412 0 : throw(AipsError("Error in Calibrater::unsetapply."));
1413 :
1414 : return false;
1415 0 : }
1416 : return false;
1417 : }
1418 :
1419 : // Delete solve VisCal
1420 2436 : Bool Calibrater::unsetsolve() {
1421 :
1422 : // logSink() << LogOrigin("Calibrater","unsetsolve") << LogIO::NORMAL;
1423 :
1424 : try {
1425 2436 : if (svc_p) delete svc_p;
1426 2436 : svc_p=NULL;
1427 :
1428 2436 : if(ve_p) ve_p->setsolve(*svc_p);
1429 :
1430 2436 : return true;
1431 :
1432 0 : } catch (AipsError x) {
1433 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1434 0 : << LogIO::POST;
1435 0 : throw(AipsError("Error in Calibrater::unsetsolve."));
1436 : return false;
1437 0 : }
1438 : return false;
1439 : }
1440 :
1441 : Bool
1442 3 : Calibrater::setCorrDepFlags(const Bool& corrDepFlags)
1443 : {
1444 :
1445 3 : logSink() << LogOrigin("Calibrater","setCorrDepFlags") << LogIO::NORMAL;
1446 :
1447 : // Set it
1448 3 : corrDepFlags_=corrDepFlags;
1449 :
1450 3 : logSink() << "Setting correlation dependent flags = " << (corrDepFlags_ ? "True" : "False") << LogIO::POST;
1451 :
1452 3 : return true;
1453 :
1454 : }
1455 :
1456 : Bool
1457 0 : Calibrater::setCorrcomb(const String& corrcomb)
1458 : {
1459 :
1460 0 : logSink() << LogOrigin("Calibrater", "setCorrcomb") << LogIO::NORMAL;
1461 :
1462 0 : corrcomb_= corrcomb;
1463 :
1464 0 : logSink() << "Setting correlation combination = " << corrcomb << LogIO::POST;
1465 :
1466 0 : return true;
1467 :
1468 : }
1469 :
1470 :
1471 : Bool
1472 82 : Calibrater::correct2(String mode)
1473 : {
1474 82 : logSink() << LogOrigin("Calibrater","correct2 (VI2/VB2)") << LogIO::NORMAL;
1475 :
1476 : //cout << "Artificial STOP!" << endl;
1477 : //return false;
1478 :
1479 :
1480 82 : Bool retval = true;
1481 :
1482 : try {
1483 :
1484 : // Ensure apply list non-zero and properly sorted
1485 82 : ve_p->setapply(vc_p);
1486 :
1487 82 : bool forceOldVIByEnv(false);
1488 82 : forceOldVIByEnv = (getenv("VI1CAL")!=NULL);
1489 82 : if (forceOldVIByEnv && anyEQ(ve_p->listTypes(),VisCal::A)) {
1490 0 : logSink() << LogIO::WARN << "Using VI2 calibration apply. AMueller (uvcontsub) no longer requires VI1 for apply." << LogIO::POST;
1491 : }
1492 :
1493 : /* CAS-12434 (2019Jun07, gmoellen): AMueller works with VB2 in _apply_ (only) context now
1494 : // Trap uvcontsub case, since it does not yet handlg VB2
1495 : if (anyEQ(ve_p->listTypes(),VisCal::A)) {
1496 :
1497 : // Only uvcontsub, nothing else
1498 : if (ve_p->nTerms()==1) {
1499 : // Use old method (which doesn't need WEIGHT_SPECTRUM support in this context)
1500 : return this->correct(mode);
1501 : }
1502 : else
1503 : throw(AipsError("Cannot handle AMueller (uvcontsub) and other types simultaneously."));
1504 : }
1505 : */
1506 :
1507 : // Report the types that will be applied
1508 82 : applystate();
1509 :
1510 : // make mode all-caps
1511 82 : String upmode=mode;
1512 82 : upmode.upcase();
1513 :
1514 : // If trialmode=T, only the flags will be set
1515 : // (and only written if not TRIAL)
1516 163 : Bool trialmode=(upmode.contains("TRIAL") ||
1517 81 : upmode.contains("FLAGONLY"));
1518 :
1519 :
1520 : // Arrange for iteration over data
1521 82 : Block<Int> columns;
1522 : // include scan iteration
1523 82 : columns.resize(5);
1524 82 : columns[0]=MS::ARRAY_ID;
1525 82 : columns[1]=MS::SCAN_NUMBER;
1526 82 : columns[2]=MS::FIELD_ID;
1527 82 : columns[3]=MS::DATA_DESC_ID;
1528 82 : columns[4]=MS::TIME;
1529 :
1530 82 : vi::SortColumns sc(columns);
1531 82 : vi::VisibilityIterator2 vi(*mssel_p,sc,true);
1532 :
1533 : // Apply channel selection (see selectChannel(spw))
1534 82 : if (frequencySelections_p)
1535 82 : vi.setFrequencySelection(*frequencySelections_p);
1536 :
1537 82 : vi::VisBuffer2 *vb = vi.getVisBuffer();
1538 :
1539 : // Detect if we will be setting WEIGHT_SPECTRUM, and arrange for this
1540 82 : vi.originChunks(); // required for wSExists() in next line to work
1541 82 : vi.origin();
1542 82 : Bool doWtSp=vi.weightSpectrumExists(); // Exists non-trivially
1543 :
1544 82 : if (doWtSp && calWt())
1545 15 : logSink() << "Found valid WEIGHT_SPECTRUM, correcting it." << LogIO::POST;
1546 :
1547 : // Pass each timestamp (VisBuffer) to VisEquation for correction
1548 :
1549 82 : Vector<Bool> uncalspw(vi.nSpectralWindows()); // Used to accumulate error messages
1550 82 : uncalspw.set(false); // instead of bombing the user
1551 :
1552 82 : uInt nvb(0);
1553 :
1554 2476 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
1555 :
1556 202621 : for (vi.origin(); vi.more(); vi.next()) {
1557 :
1558 200261 : uInt spw = vb->spectralWindows()(0);
1559 : //if (ve_p->spwOK(spw)){
1560 : //if ( (usingCalLibrary_ && ve_p->VBOKforCalApply(*vb)) // CalLibrary case
1561 : // || (!usingCalLibrary_ && ve_p->spwOK(spw)) // old-fashioned case
1562 : // ) {
1563 200261 : if ( ve_p->VBOKforCalApply(*vb) ) { // Handles old and new (CL) contexts
1564 :
1565 : // Re-initialize weight info from sigma info
1566 : // This is smart wrt spectral weights, etc.
1567 : // (this makes W and WS, if present, "dirty" in the vb)
1568 : // TBD: only do this if !trial (else: avoid the I/O)
1569 200227 : vb->resetWeightsUsingSigma();
1570 :
1571 : // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
1572 : // (this makes CD "dirty" in the vb)
1573 : // TBD: only do this if !trial (else: avoid the I/O)
1574 200227 : vb->setVisCubeCorrected(vb->visCube());
1575 :
1576 : // Make flagcube dirty in the vb
1577 : // NB: we must _always_ do this I/O (even trial mode)
1578 200227 : vb->setFlagCube(vb->flagCube());
1579 :
1580 : // Make all vb "not dirty"; we'll carefully arrange the writeback below
1581 200227 : vb->dirtyComponentsClear();
1582 :
1583 : // throws exception if nothing to apply
1584 200227 : ve_p->correct2(*vb,trialmode,doWtSp);
1585 :
1586 : // Only if not a trial run, manage writes to disk
1587 200227 : if (upmode!="TRIAL") {
1588 :
1589 192919 : if (upmode.contains("CAL")) {
1590 178303 : vb->setVisCubeCorrected(vb->visCubeCorrected());
1591 :
1592 178303 : if (calWt()) {
1593 : // Set weights dirty only if calwt=T
1594 170754 : if (doWtSp) {
1595 240 : vb->setWeightSpectrum(vb->weightSpectrum());
1596 : // If WS was calibrated, set W to its channel-axis median
1597 240 : vb->setWeight(partialMedians(vb->weightSpectrum(),IPosition(1,1)));
1598 : }
1599 : else
1600 170514 : vb->setWeight(vb->weight());
1601 : }
1602 : }
1603 :
1604 192919 : if (upmode.contains("FLAG"))
1605 182471 : vb->setFlagCube(vb->flagCube());
1606 :
1607 : // Push the calibrated data etc. back to the MS
1608 192919 : vb->writeChangesBack();
1609 192919 : nvb+=1; // increment vb counter
1610 : }
1611 :
1612 : }
1613 : else{
1614 34 : uncalspw[spw] = true;
1615 :
1616 : // set the flags, if we are being strict
1617 : // (don't touch the data/weights, which are initialized)
1618 34 : if (upmode.contains("STRICT")) {
1619 :
1620 : // reference (to avoid copy) and set the flags
1621 0 : Cube<Bool> fC(vb->flagCube()); // reference
1622 0 : fC.set(true);
1623 :
1624 : // make dirty for writeChangesBack (does this do an actual copy?)
1625 0 : vb->setFlagCube(vb->flagCube());
1626 :
1627 : // write back to
1628 0 : vb->writeChangesBack();
1629 :
1630 0 : }
1631 : else {
1632 :
1633 : // Break out of inner VI2 loop, if possible
1634 34 : if (! vi.isAsynchronous()){
1635 :
1636 : // Asynchronous I/O doesn't have a way to skip
1637 : // VisBuffers, so only break out when not using
1638 : // async i/o.
1639 34 : break;
1640 :
1641 : }
1642 :
1643 : }
1644 : }
1645 : }
1646 : }
1647 :
1648 : // Now that we're out of the loop, summarize any errors.
1649 :
1650 82 : retval = summarize_uncalspws(uncalspw, "correct",
1651 82 : upmode.contains("STRICT"));
1652 :
1653 82 : actRec_=Record();
1654 82 : actRec_.define("origin","Calibrater::correct");
1655 82 : actRec_.defineRecord("VisEquation",ve_p->actionRec());
1656 :
1657 :
1658 : //cout << "Number of VisBuffers corrected: " << nvb << endl;
1659 :
1660 82 : }
1661 0 : catch (AipsError x) {
1662 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1663 0 : << LogIO::POST;
1664 :
1665 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
1666 0 : unsetapply();
1667 :
1668 0 : throw(AipsError("Error in Calibrater::correct."));
1669 : retval = false; // Not that it ever gets here...
1670 0 : }
1671 82 : return retval;
1672 : }
1673 :
1674 0 : Bool Calibrater::corrupt2()
1675 : {
1676 0 : logSink() << LogOrigin("Calibrater","corrupt2 (VI2/VB2)") << LogIO::NORMAL;
1677 0 : Bool retval = true;
1678 :
1679 : try {
1680 :
1681 0 : if (!ok())
1682 0 : throw(AipsError("Calibrater not prepared for corrupt2!"));
1683 :
1684 : // MODEL_DATA column must be physically present!
1685 0 : if (!ms_p->tableDesc().isColumn("MODEL_DATA"))
1686 0 : throw(AipsError("MODEL_DATA column unexpectedly absent. Cannot corrupt."));
1687 :
1688 : // Ensure apply list non-zero and properly sorted
1689 0 : ve_p->setapply(vc_p);
1690 :
1691 : /*
1692 : // Trap uvcontsub case, since it does not yet handlg VB2
1693 : if (anyEQ(ve_p->listTypes(),VisCal::A)) {
1694 :
1695 : // Only uvcontsub, nothing else
1696 : if (ve_p->nTerms()==1) {
1697 : // Use old method (which doesn't need WEIGHT_SPECTRUM support in this context)
1698 : return this->correct(mode);
1699 : }
1700 : else
1701 : throw(AipsError("Cannot handle AMueller (uvcontsub) and other types simultaneously."));
1702 : }
1703 : */
1704 :
1705 : // Report the types that will be applied
1706 0 : applystate();
1707 :
1708 : // Arrange for iteration over data
1709 0 : Block<Int> columns;
1710 : // include scan iteration
1711 0 : columns.resize(5);
1712 0 : columns[0]=MS::ARRAY_ID;
1713 0 : columns[1]=MS::SCAN_NUMBER;
1714 0 : columns[2]=MS::FIELD_ID;
1715 0 : columns[3]=MS::DATA_DESC_ID;
1716 0 : columns[4]=MS::TIME;
1717 :
1718 0 : vi::SortColumns sc(columns);
1719 0 : vi::VisibilityIterator2 vi(*mssel_p,sc,true);
1720 :
1721 : // Apply channel selection (see selectChannel(spw))
1722 0 : if (frequencySelections_p)
1723 0 : vi.setFrequencySelection(*frequencySelections_p);
1724 :
1725 0 : vi::VisBuffer2 *vb = vi.getVisBuffer();
1726 :
1727 : // Detect if we will be setting WEIGHT_SPECTRUM, and arrange for this
1728 0 : vi.originChunks(); // required for wSExists() in next line to work
1729 0 : vi.origin();
1730 :
1731 0 : Vector<Bool> uncalspw(vi.nSpectralWindows()); // Used to accumulate error messages
1732 0 : uncalspw.set(false); // instead of bombing the user
1733 :
1734 : // Pass each timestamp (VisBuffer) to VisEquation for correction
1735 0 : uInt nvb(0);
1736 0 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
1737 0 : for (vi.origin(); vi.more(); vi.next()) {
1738 0 : uInt spw = vb->spectralWindows()(0);
1739 : //if (ve_p->spwOK(spw)){
1740 0 : if (usingCalLibrary_ || ve_p->spwOK(spw)){
1741 :
1742 : // Make all vb "not dirty", for safety
1743 0 : vb->dirtyComponentsClear();
1744 :
1745 : // throws exception if nothing to apply
1746 0 : ve_p->corrupt2(*vb);
1747 :
1748 : // make visCubeModel _ONLY_ dirty for writeChangesBack
1749 0 : vb->setVisCubeModel(vb->visCubeModel());
1750 :
1751 : // Push the corrupted model back to the MS
1752 0 : vb->writeChangesBack();
1753 0 : nvb+=1; // increment vb counter
1754 : }
1755 : else{
1756 0 : uncalspw[spw] = true;
1757 : }
1758 : }
1759 : }
1760 :
1761 : // Now that we're out of the loop, summarize any errors.
1762 0 : retval = summarize_uncalspws(uncalspw, "corrupt2",false); // (didn't flag them)
1763 :
1764 0 : actRec_=Record();
1765 0 : actRec_.define("origin","Calibrater::corrupt2");
1766 0 : actRec_.defineRecord("VisEquation",ve_p->actionRec());
1767 :
1768 : //cout << "Number of VisBuffers corrupted: " << nvb << endl;
1769 :
1770 0 : }
1771 0 : catch (AipsError x) {
1772 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
1773 0 : << LogIO::POST;
1774 :
1775 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
1776 0 : unsetapply();
1777 :
1778 0 : throw(AipsError("Error in Calibrater::corrupt2."));
1779 : retval = false; // Not that it ever gets here...
1780 0 : }
1781 0 : return retval;
1782 : }
1783 :
1784 24 : Bool Calibrater::initWeightsWithTsys(String wtmode, Bool dowtsp,
1785 : String tsystable, String gainfield, String interp, Vector<Int> spwmap) {
1786 :
1787 48 : logSink() << LogOrigin("Calibrater", "initWeightsWithTsys")
1788 48 : << LogIO::NORMAL;
1789 24 : Bool retval = true;
1790 :
1791 : try {
1792 :
1793 24 : if (!ok())
1794 0 : throw(AipsError("Calibrater not prepared for initWeights!"));
1795 :
1796 24 : String uptype = calTableType(tsystable);
1797 24 : if (!uptype.contains("TSYS")) {
1798 0 : throw(AipsError(
1799 0 : "Invalid calibration table type for Tsys weighting."));
1800 : }
1801 : // Set record format for calibration table application information
1802 24 : RecordDesc applyparDesc;
1803 24 : applyparDesc.addField("t", TpDouble);
1804 24 : applyparDesc.addField("table", TpString);
1805 24 : applyparDesc.addField("interp", TpString);
1806 24 : applyparDesc.addField("spw", TpArrayInt);
1807 24 : applyparDesc.addField("fieldstr", TpString);
1808 24 : applyparDesc.addField("calwt", TpBool);
1809 24 : applyparDesc.addField("spwmap", TpArrayInt);
1810 24 : applyparDesc.addField("opacity", TpArrayDouble);
1811 :
1812 : // Create record with the requisite field values
1813 24 : Record applypar(applyparDesc);
1814 24 : applypar.define("t", 0.0);
1815 24 : applypar.define("table", tsystable);
1816 24 : applypar.define("interp", interp);
1817 24 : applypar.define("spw", getSpwIdx(""));
1818 24 : applypar.define("fieldstr", gainfield);
1819 24 : applypar.define("calwt", true);
1820 24 : applypar.define("spwmap", spwmap);
1821 24 : applypar.define("opacity", Vector<Double>(1, 0.0));
1822 :
1823 24 : if (vc_p.nelements() > 0) {
1824 0 : logSink() << LogIO::WARN << "Resetting all calibration application settings." << LogIO::POST;
1825 0 : unsetapply();
1826 : }
1827 24 : logSink() << LogIO::NORMAL << "Weight initialization does not support selection. Resetting MS selection." << LogIO::POST;
1828 24 : selectvis();
1829 24 : StandardTsys vc = StandardTsys(*msmc_p);
1830 24 : vc.setApply(applypar);
1831 :
1832 24 : logSink() << LogIO::NORMAL << ". " << vc.applyinfo() << LogIO::POST;
1833 24 : PtrBlock<VisCal*> vcb(1, &vc);
1834 : // Maintain sort of apply list
1835 24 : ve_p->setapply(vcb);
1836 :
1837 : // Detect WEIGHT_SPECTRUM and SIGMA_SPECTRUM
1838 24 : TableDesc mstd = ms_p->actualTableDesc();
1839 24 : String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
1840 24 : Bool wtspexists = mstd.isColumn(colWtSp);
1841 24 : String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
1842 24 : Bool sigspexists = mstd.isColumn(colSigSp);
1843 24 : Bool addsigsp = (dowtsp && !sigspexists);
1844 :
1845 : // Some log info
1846 24 : bool use_exposure = false;
1847 24 : if (wtmode == "tsys") {
1848 : logSink()
1849 : << "Initializing SIGMA and WEIGHT according to channel bandwidth and Tsys. NOTE this is an expert mode."
1850 12 : << LogIO::WARN << LogIO::POST;
1851 12 : } else if (wtmode == "tinttsys") {
1852 : logSink()
1853 : << "Initializing SIGMA and WEIGHT according to channel bandwidth, integration time, and Tsys. NOTE this is an expert mode."
1854 12 : << LogIO::WARN << LogIO::POST;
1855 12 : use_exposure = true;
1856 : } else {
1857 0 : throw(AipsError("Unrecognized wtmode specified: " + wtmode));
1858 : }
1859 :
1860 : // Force dowtsp if the column already exists
1861 24 : if (wtspexists && !dowtsp) {
1862 : logSink() << "Found WEIGHT_SPECTRUM; will force its initialization."
1863 0 : << LogIO::POST;
1864 0 : dowtsp = true;
1865 : }
1866 :
1867 : // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
1868 24 : if (dowtsp) {
1869 :
1870 : // Ensure WEIGHT_SPECTRUM really exists at all
1871 : // (often it exists but is empty)
1872 12 : if (!wtspexists) {
1873 12 : logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
1874 :
1875 : // Nominal defaulttileshape
1876 12 : IPosition dts(3, 4, 32, 1024);
1877 :
1878 : // Discern DATA's default tile shape and use it
1879 12 : const Record dminfo = ms_p->dataManagerInfo();
1880 300 : for (uInt i = 0; i < dminfo.nfields(); ++i) {
1881 288 : Record col = dminfo.asRecord(i);
1882 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
1883 288 : if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
1884 0 : dts = IPosition(
1885 0 : col.asRecord("SPEC").asArrayInt(
1886 0 : "DEFAULTTILESHAPE"));
1887 : //cout << "Found DATA's default tile: " << dts << endl;
1888 0 : break;
1889 : }
1890 288 : }
1891 :
1892 : // Add the column
1893 12 : String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
1894 12 : TableDesc tdWtSp;
1895 12 : tdWtSp.addColumn(
1896 24 : ArrayColumnDesc<Float>(colWtSp, "weight spectrum", 2));
1897 12 : TiledShapeStMan wtSpStMan("TiledWgtSpectrum", dts);
1898 12 : ms_p->addColumn(tdWtSp, wtSpStMan);
1899 12 : } else
1900 0 : logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
1901 : // Ensure WEIGHT_SPECTRUM really exists at all
1902 : // (often it exists but is empty)
1903 12 : if (!sigspexists) {
1904 12 : logSink() << "Creating SIGMA_SPECTRUM." << LogIO::POST;
1905 :
1906 : // Nominal defaulttileshape
1907 12 : IPosition dts(3, 4, 32, 1024);
1908 :
1909 : // Discern DATA's default tile shape and use it
1910 12 : const Record dminfo = ms_p->dataManagerInfo();
1911 312 : for (uInt i = 0; i < dminfo.nfields(); ++i) {
1912 300 : Record col = dminfo.asRecord(i);
1913 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
1914 300 : if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
1915 0 : dts = IPosition(
1916 0 : col.asRecord("SPEC").asArrayInt(
1917 0 : "DEFAULTTILESHAPE"));
1918 : //cout << "Found DATA's default tile: " << dts << endl;
1919 0 : break;
1920 : }
1921 300 : }
1922 :
1923 : // Add the column
1924 12 : String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
1925 12 : TableDesc tdSigSp;
1926 12 : tdSigSp.addColumn(
1927 24 : ArrayColumnDesc<Float>(colSigSp, "sigma spectrum", 2));
1928 12 : TiledShapeStMan sigSpStMan("TiledSigtSpectrum", dts);
1929 12 : ms_p->addColumn(tdSigSp, sigSpStMan);
1930 : {
1931 12 : TableDesc loctd = ms_p->actualTableDesc();
1932 12 : String loccolSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
1933 12 : AlwaysAssert(loctd.isColumn(loccolSigSp),AipsError);
1934 12 : }
1935 12 : }
1936 : }
1937 : else {
1938 12 : if (sigspexists) {
1939 0 : logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
1940 : if (true || ms_p->canRemoveColumn(colSigSp)) {
1941 0 : ms_p->removeColumn(colSigSp);
1942 : }
1943 : else
1944 : logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
1945 : }
1946 : }
1947 :
1948 : // Arrange for iteration over data
1949 : // TBD: Be sure this sort is optimal for creating WS?
1950 24 : Block<Int> columns;
1951 : // include scan iteration
1952 24 : columns.resize(5);
1953 24 : columns[0] = MS::ARRAY_ID;
1954 24 : columns[1] = MS::SCAN_NUMBER;
1955 24 : columns[2] = MS::FIELD_ID;
1956 24 : columns[3] = MS::DATA_DESC_ID;
1957 24 : columns[4] = MS::TIME;
1958 :
1959 24 : vi::SortColumns sc(columns);
1960 24 : vi::VisibilityIterator2 vi2(*ms_p, sc, true);
1961 24 : vi::VisBuffer2 *vb = vi2.getVisBuffer();
1962 :
1963 24 : MSColumns mscol(*ms_p);
1964 24 : const MSSpWindowColumns& msspw(mscol.spectralWindow());
1965 24 : uInt nSpw = msspw.nrow();
1966 24 : Vector<Double> effChBw(nSpw, 0.0);
1967 432 : for (uInt ispw = 0; ispw < nSpw; ++ispw) {
1968 408 : effChBw[ispw] = mean(msspw.effectiveBW()(ispw));
1969 : }
1970 :
1971 24 : Int ivb(0);
1972 648 : for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
1973 :
1974 1248 : for (vi2.origin(); vi2.more(); vi2.next(), ++ivb) {
1975 :
1976 624 : Int spw = vb->spectralWindows()(0);
1977 :
1978 624 : auto nrow = vb->nRows();
1979 624 : Int nchan = vb->nChannels();
1980 624 : Int ncor = vb->nCorrelations();
1981 :
1982 : // Prepare for WEIGHT_SPECTRUM and SIGMA_SPECTRUM, if nec.
1983 624 : Cube<Float> newwtsp(0, 0, 0), newsigsp(0, 0, 0);
1984 624 : if (dowtsp) {
1985 312 : newwtsp.resize(ncor, nchan, nrow);
1986 312 : newwtsp.set(1.0);
1987 312 : newsigsp.resize(ncor, nchan, nrow);
1988 312 : newsigsp.set(1.0);
1989 : }
1990 :
1991 624 : if (ve_p->spwOK(spw)) {
1992 :
1993 : // Re-initialize weight info from sigma info
1994 : // This is smart wrt spectral weights, etc.
1995 : // (this makes W and WS, if present, "dirty" in the vb)
1996 : // TBD: only do this if !trial (else: avoid the I/O)
1997 : // vb->resetWeightsUsingSigma();
1998 : // Handle non-trivial modes
1999 : // Init WEIGHT, SIGMA from bandwidth & time
2000 192 : Matrix<Float> newwt(ncor, nrow), newsig(ncor, nrow);
2001 192 : newwt.set(1.0);
2002 192 : newsig.set(1.0);
2003 :
2004 : // Detect ACs
2005 192 : const Vector<Int> a1(vb->antenna1());
2006 192 : const Vector<Int> a2(vb->antenna2());
2007 192 : Vector<Bool> ac(a1 == a2);
2008 :
2009 : // XCs need an extra factor of 2
2010 192 : Vector<Float> xcfactor(nrow, 2.0);
2011 192 : xcfactor(ac) = 1.0; // (but not ACs)
2012 :
2013 : // The row-wise integration time
2014 192 : Vector<Float> expo(nrow);
2015 192 : convertArray(expo, vb->exposure());
2016 :
2017 : // Set weights to channel bandwidth first.
2018 192 : newwt.set(Float(effChBw(spw)));
2019 :
2020 : // For each correlation, apply exposure and xcfactor
2021 576 : for (Int icor = 0; icor < ncor; ++icor) {
2022 :
2023 384 : Vector<Float> wt(newwt.row(icor));
2024 384 : if (use_exposure) {
2025 192 : wt *= expo;
2026 : }
2027 384 : wt *= xcfactor;
2028 384 : if (dowtsp) {
2029 404160 : for (Int ich = 0; ich < nchan; ++ich) {
2030 : Vector<Float> wtspi(
2031 403968 : newwtsp(Slice(icor, 1, 1),
2032 1211904 : Slice(ich, 1, 1), Slice()).nonDegenerate(
2033 1211904 : IPosition(1, 2)));
2034 403968 : wtspi = wt;
2035 403968 : }
2036 : }
2037 384 : }
2038 : // Handle SIGMA_SPECTRUM
2039 192 : if (dowtsp) {
2040 96 : newsigsp = 1.0f / sqrt(newwtsp);
2041 : }
2042 : // sig from wt is inverse sqrt
2043 192 : newsig = 1.0f / sqrt(newwt);
2044 :
2045 : // Arrange write-back of both SIGMA and WEIGHT
2046 192 : vb->setSigma(newsig);
2047 192 : vb->setWeight(newwt);
2048 192 : if (dowtsp) {
2049 96 : vb->initWeightSpectrum(newwtsp);
2050 96 : vb->initSigmaSpectrum(newsigsp);
2051 : }
2052 : // Force writeback to disk (need to initialize weight/sigma before applying cal table)
2053 192 : vb->writeChangesBack();
2054 :
2055 : // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
2056 : // (this makes CD "dirty" in the vb)
2057 : // TBD: only do this if !trial (else: avoid the I/O)
2058 192 : vb->setVisCubeCorrected(vb->visCube());
2059 :
2060 : // Make flagcube dirty in the vb
2061 : // NB: we must _always_ do this I/O (even trial mode)
2062 192 : vb->setFlagCube(vb->flagCube());
2063 :
2064 : // Make all vb "not dirty"; we'll carefully arrange the writeback below
2065 192 : vb->dirtyComponentsClear();
2066 :
2067 : // throws exception if nothing to apply
2068 192 : ve_p->correct2(*vb, false, dowtsp);
2069 :
2070 192 : if (dowtsp) {
2071 96 : vb->setWeightSpectrum(vb->weightSpectrum());
2072 : // If WS was calibrated, set W to its channel-axis median
2073 96 : vb->setWeight( partialMedians(vb->weightSpectrum(), IPosition(1, 1)) );
2074 96 : newsigsp = 1.0f / sqrt(vb->weightSpectrum());
2075 96 : vb->initSigmaSpectrum(newsigsp);
2076 96 : vb->setSigma( partialMedians(newsigsp, IPosition(1, 1)) );
2077 : } else {
2078 96 : vb->setWeight(vb->weight());
2079 96 : newsig = 1.0f / sqrt(vb->weight());
2080 96 : vb->setSigma(newsig);
2081 : }
2082 : // Force writeback to disk
2083 192 : vb->writeChangesBack();
2084 :
2085 192 : } else {//Not calibrating the spw
2086 432 : if (dowtsp && !wtspexists) {
2087 : // newly created WS Need to initialize
2088 216 : vb->initWeightSpectrum(newwtsp);
2089 : }
2090 432 : if (addsigsp) {
2091 : // newly created SS Need to initialize
2092 216 : vb->initSigmaSpectrum(newsigsp);
2093 216 : vb->writeChangesBack();
2094 : }
2095 : }
2096 624 : }
2097 : }
2098 : // clear-up Tsys caltable from list of apply
2099 24 : unsetapply();
2100 :
2101 24 : } catch (AipsError x) {
2102 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2103 0 : << LogIO::POST;
2104 :
2105 : logSink() << "Resetting all calibration application settings."
2106 0 : << LogIO::POST;
2107 0 : unsetapply();
2108 :
2109 0 : throw(AipsError("Error in Calibrater::initWeights."));
2110 : retval = false; // Not that it ever gets here...
2111 0 : }
2112 24 : return retval;
2113 : }
2114 :
2115 :
2116 35 : Bool Calibrater::initWeights(String wtmode, Bool dowtsp) {
2117 :
2118 35 : logSink() << LogOrigin("Calibrater","initWeights") << LogIO::NORMAL;
2119 35 : Bool retval = true;
2120 :
2121 : try {
2122 :
2123 35 : if (!ok())
2124 0 : throw(AipsError("Calibrater not prepared for initWeights!"));
2125 :
2126 : // An enum for the requested wtmode
2127 : enum wtInitModeEnum {
2128 : NONE, // ambiguous, will complain
2129 : ONES, // SIGMA=1.0, propagate to WEIGHT, WEIGHT_SEPCTRUM
2130 : NYQ, // SIGMA=f(df,dt), propagate to WEIGHT, WEIGHT_SEPCTRUM
2131 : SIGMA, // SIGMA as is, propagate to WEIGHT, WEIGHT_SEPCTRUM
2132 : WEIGHT, // SIGMA, WEIGHT as are, propagate to WEIGHT_SEPCTRUM (if requested)
2133 : DELWTSP, // just delete WEIGHT_SPECTRUM if it exists
2134 : DELSIGSP, // just delete SIGMA_SPECTRUM if it exists
2135 : };
2136 :
2137 : // Translate mode String to enum value
2138 35 : wtInitModeEnum initmode(NONE);
2139 35 : if (wtmode=="ones") initmode=ONES;
2140 25 : else if (wtmode=="nyq") initmode=NYQ;
2141 8 : else if (wtmode=="sigma") initmode=SIGMA;
2142 6 : else if (wtmode=="weight") initmode=WEIGHT;
2143 4 : else if (wtmode=="delwtsp") initmode=DELWTSP;
2144 2 : else if (wtmode=="delsigsp") initmode=DELSIGSP;
2145 :
2146 : // Detect WEIGHT_SPECTRUM
2147 35 : TableDesc mstd = ms_p->actualTableDesc();
2148 35 : String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
2149 35 : Bool wtspexists=mstd.isColumn(colWtSp);
2150 35 : String colSigSp=MS::columnName(MS::SIGMA_SPECTRUM);
2151 35 : Bool sigspexists=mstd.isColumn(colSigSp);
2152 :
2153 : // Some log info
2154 35 : switch (initmode) {
2155 2 : case DELWTSP: {
2156 2 : if (wtspexists) {
2157 : if (true || ms_p->canRemoveColumn(colWtSp)) {
2158 2 : logSink() << "Removing WEIGHT_SPECTRUM." << LogIO::POST;
2159 2 : ms_p->removeColumn(colWtSp);
2160 : }
2161 : else
2162 : logSink() << "Sorry, WEIGHT_SPECTRUM is not removable." << LogIO::POST;
2163 : }
2164 : else
2165 0 : logSink() << "WEIGHT_SPECTRUM already absent." << LogIO::POST;
2166 :
2167 : // Nothing more to do here
2168 2 : return true;
2169 : break;
2170 : }
2171 2 : case DELSIGSP: {
2172 2 : if (sigspexists) {
2173 : if (true || ms_p->canRemoveColumn(colSigSp)) {
2174 2 : logSink() << "Removing SIGMA_SPECTRUM." << LogIO::POST;
2175 2 : ms_p->removeColumn(colSigSp);
2176 : }
2177 : else
2178 : logSink() << "Sorry, SIGMA_SPECTRUM is not removable." << LogIO::POST;
2179 : }
2180 : else
2181 0 : logSink() << "SIGMA_SPECTRUM already absent." << LogIO::POST;
2182 :
2183 : // Nothing more to do here
2184 2 : return true;
2185 : break;
2186 : }
2187 0 : case NONE: {
2188 0 : throw(AipsError("Unrecognized wtmode specified: "+wtmode));
2189 : break;
2190 : }
2191 10 : case ONES: {
2192 10 : logSink() << "Initializing SIGMA and WEIGHT with 1.0" << LogIO::POST;
2193 10 : break;
2194 : }
2195 17 : case NYQ: {
2196 : logSink() << "Initializing SIGMA and WEIGHT according to channel bandwidth and integration time."
2197 17 : << LogIO::POST;
2198 17 : break;
2199 : }
2200 2 : case SIGMA: {
2201 2 : logSink() << "Initializing WEIGHT according to existing SIGMA." << LogIO::POST;
2202 2 : break;
2203 : }
2204 2 : case WEIGHT: {
2205 : // Complain if dowtsp==F, because otherwise we have nothing to do
2206 2 : if (!dowtsp)
2207 0 : throw(AipsError("Specified wtmode requires dowtsp=T"));
2208 2 : break;
2209 : }
2210 : }
2211 :
2212 : // Force dowtsp if the column already exists
2213 31 : if (wtspexists && !dowtsp) {
2214 2 : logSink() << "Found WEIGHT_SPECTRUM; will force its initialization." << LogIO::POST;
2215 2 : dowtsp=true;
2216 : }
2217 : // remove SIGMA_SPECTRUM column for non-channelized weight
2218 31 : if (sigspexists) {
2219 9 : logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
2220 : if (true || ms_p->canRemoveColumn(colSigSp)) {
2221 9 : ms_p->removeColumn(colSigSp);
2222 : }
2223 : else
2224 : logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
2225 : }
2226 :
2227 : // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
2228 31 : if (dowtsp) {
2229 :
2230 : // Ensure WEIGHT_SPECTRUM really exists at all
2231 : // (often it exists but is empty)
2232 21 : if (!wtspexists) {
2233 5 : logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
2234 :
2235 : // Nominal defaulttileshape
2236 5 : IPosition dts(3,4,32,1024);
2237 :
2238 : // Discern DATA's default tile shape and use it
2239 5 : const Record dminfo=ms_p->dataManagerInfo();
2240 117 : for (uInt i=0;i<dminfo.nfields();++i) {
2241 113 : Record col=dminfo.asRecord(i);
2242 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
2243 113 : if (anyEQ(col.asArrayString("COLUMNS"),String("DATA"))) {
2244 1 : dts=IPosition(col.asRecord("SPEC").asArrayInt("DEFAULTTILESHAPE"));
2245 : //cout << "Found DATA's default tile: " << dts << endl;
2246 1 : break;
2247 : }
2248 113 : }
2249 :
2250 : // Add the column
2251 5 : String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
2252 5 : TableDesc tdWtSp;
2253 5 : tdWtSp.addColumn(ArrayColumnDesc<Float>(colWtSp,"weight spectrum", 2));
2254 5 : TiledShapeStMan wtSpStMan("TiledWgtSpectrum",dts);
2255 5 : ms_p->addColumn(tdWtSp,wtSpStMan);
2256 5 : }
2257 : else
2258 16 : logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
2259 :
2260 :
2261 21 : logSink() << "Initializing WEIGHT_SPECTRUM uniformly in channel (==WEIGHT)." << LogIO::POST;
2262 :
2263 : }
2264 :
2265 : // Arrange for iteration over data
2266 : // TBD: Be sure this sort is optimal for creating WS?
2267 62 : Block<Int> columns;
2268 : // include scan iteration
2269 31 : columns.resize(5);
2270 31 : columns[0]=MS::ARRAY_ID;
2271 31 : columns[1]=MS::SCAN_NUMBER;
2272 31 : columns[2]=MS::FIELD_ID;
2273 31 : columns[3]=MS::DATA_DESC_ID;
2274 31 : columns[4]=MS::TIME;
2275 :
2276 62 : vi::SortColumns sc(columns);
2277 62 : vi::VisibilityIterator2 vi2(*ms_p,sc,true);
2278 31 : vi::VisBuffer2 *vb = vi2.getVisBuffer();
2279 :
2280 62 : MSColumns mscol(*ms_p);
2281 31 : const MSSpWindowColumns& msspw(mscol.spectralWindow());
2282 31 : uInt nSpw=msspw.nrow();
2283 62 : Vector<Double> effChBw(nSpw,0.0);
2284 563 : for (uInt ispw=0;ispw<nSpw;++ispw) {
2285 532 : effChBw[ispw]=mean(msspw.effectiveBW()(ispw));
2286 : }
2287 :
2288 31 : Int ivb(0);
2289 3515 : for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
2290 :
2291 7753 : for (vi2.origin(); vi2.more(); vi2.next(),++ivb) {
2292 :
2293 4269 : Int spw = vb->spectralWindows()(0);
2294 :
2295 4269 : auto nrow=vb->nRows();
2296 4269 : Int nchan=vb->nChannels();
2297 4269 : Int ncor=vb->nCorrelations();
2298 :
2299 : // Vars for new sigma/weight info
2300 :
2301 : // Prepare for WEIGHT_SPECTRUM, if nec.
2302 4269 : Cube<Float> newwtsp(0,0,0);
2303 4269 : if (dowtsp) {
2304 274 : newwtsp.resize(ncor,nchan,nrow);
2305 274 : newwtsp.set(1.0);
2306 : }
2307 :
2308 : // Handle non-trivial modes
2309 4269 : switch (initmode) {
2310 : // Init WEIGHT, SIGMA with ones
2311 14 : case ONES: {
2312 :
2313 14 : Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
2314 14 : newwt.set(1.0);
2315 14 : newsig.set(1.0);
2316 :
2317 : // Arrange write-back of both SIGMA and WEIGHT
2318 14 : vb->setSigma(newsig);
2319 14 : vb->setWeight(newwt);
2320 :
2321 : // NB: newwtsp already ready
2322 :
2323 14 : break;
2324 14 : }
2325 :
2326 : // Init WEIGHT, SIGMA from bandwidth & time
2327 4224 : case NYQ: {
2328 :
2329 4224 : Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
2330 4224 : newwt.set(1.0);
2331 4224 : newsig.set(1.0);
2332 :
2333 : // Detect ACs
2334 4224 : const Vector<Int> a1(vb->antenna1());
2335 4224 : const Vector<Int> a2(vb->antenna2());
2336 4224 : Vector<Bool> ac(a1==a2);
2337 :
2338 : // XCs need an extra factor of 2
2339 4224 : Vector<Float> xcfactor(nrow,2.0);
2340 4224 : xcfactor(ac)=1.0; // (but not ACs)
2341 :
2342 : // The row-wise integration time
2343 4224 : Vector<Float> expo(nrow);
2344 4224 : convertArray(expo,vb->exposure());
2345 :
2346 : // Set weights to channel bandwidth first.
2347 4224 : newwt.set(Float(effChBw(spw)));
2348 :
2349 : // For each correlation, apply exposure and xcfactor
2350 12482 : for (Int icor=0;icor<ncor;++icor) {
2351 :
2352 8258 : Vector<Float> wt(newwt.row(icor));
2353 8258 : wt*=expo;
2354 8258 : wt*=xcfactor;
2355 8258 : if (dowtsp) {
2356 1791366 : for (Int ich=0;ich<nchan;++ich) {
2357 3581792 : Vector<Float> wtspi(newwtsp(Slice(icor,1,1),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(1,2)));
2358 1790896 : wtspi=wt;
2359 1790896 : }
2360 : }
2361 8258 : }
2362 :
2363 : // sig from wt is inverse sqrt
2364 4224 : newsig=1.0f/sqrt(newwt);
2365 :
2366 : // Arrange write-back of both SIGMA and WEIGHT
2367 4224 : vb->setSigma(newsig);
2368 4224 : vb->setWeight(newwt);
2369 :
2370 4224 : break;
2371 4224 : }
2372 : // Init WEIGHT from SIGMA
2373 6 : case SIGMA: {
2374 :
2375 6 : Matrix<Float> newwt(ncor,nrow);
2376 6 : newwt.set(FLT_EPSILON); // effectively zero, but strictly not zero
2377 :
2378 6 : Matrix<Float> sig;
2379 6 : sig.assign(vb->sigma()); // access existing SIGMA
2380 :
2381 6 : LogicalArray mask(sig==0.0f); // mask out unphysical SIGMA
2382 6 : sig(mask)=1.0f;
2383 :
2384 6 : newwt=1.0f/square(sig);
2385 6 : newwt(mask)=FLT_EPSILON; // effectively zero
2386 :
2387 : // Writeback WEIGHT
2388 6 : vb->setWeight(newwt);
2389 :
2390 6 : if (dowtsp) {
2391 8291 : for (Int ich=0;ich<nchan;++ich) {
2392 16576 : Matrix<Float> wtspi(newwtsp(Slice(),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(2,0,2)));
2393 8288 : wtspi=newwt;
2394 8288 : }
2395 : }
2396 :
2397 6 : break;
2398 6 : }
2399 : // Init WEIGHT_SPECTRUM from WEIGHT
2400 25 : case WEIGHT: {
2401 25 : const Matrix<Float> wt(vb->weight()); // access existing WEIGHT
2402 8753 : for (Int ich=0;ich<nchan;++ich) {
2403 17456 : Matrix<Float> wtspi(newwtsp(Slice(),Slice(ich,1,1),Slice()).nonDegenerate(IPosition(2,0,2)));
2404 8728 : wtspi=wt;
2405 8728 : }
2406 25 : break;
2407 25 : }
2408 0 : default: {
2409 0 : throw(AipsError("Problem in weight initialization loop."));
2410 : }
2411 : }
2412 :
2413 : // Force writeback to disk
2414 4269 : vb->writeChangesBack();
2415 :
2416 : // Handle WEIGHT_SPECTRUM
2417 4269 : if (dowtsp)
2418 274 : vb->initWeightSpectrum(newwtsp);
2419 :
2420 4269 : }
2421 : }
2422 :
2423 43 : }
2424 0 : catch (AipsError x) {
2425 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2426 0 : << LogIO::POST;
2427 :
2428 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
2429 0 : unsetapply();
2430 :
2431 0 : throw(AipsError("Error in Calibrater::initWeights."));
2432 : retval = false; // Not that it ever gets here...
2433 0 : }
2434 31 : return retval;
2435 : }
2436 :
2437 :
2438 0 : Bool Calibrater::initWeights(Bool doBT, Bool dowtsp) {
2439 :
2440 0 : logSink() << LogOrigin("Calibrater","initWeights") << LogIO::NORMAL;
2441 0 : Bool retval = true;
2442 :
2443 : try {
2444 :
2445 0 : if (!ok())
2446 0 : throw(AipsError("Calibrater not prepared for initWeights!"));
2447 :
2448 : // Log that we are beginning...
2449 0 : if (doBT)
2450 0 : logSink() << "Initializing SIGMA and WEIGHT according to channel bandwidth and integration time." << LogIO::POST;
2451 : else
2452 0 : logSink() << "Initializing SIGMA and WEIGHT to unity." << LogIO::POST;
2453 :
2454 0 : if (dowtsp) {
2455 0 : logSink() << "Also initializing WEIGHT_SPECTRUM uniformly in channel (==WEIGHT)." << LogIO::POST;
2456 :
2457 : // Ensure WEIGHT_SPECTRUM really exists at all
2458 : // (often it exists but is empty)
2459 0 : TableDesc mstd = ms_p->actualTableDesc();
2460 0 : if (!mstd.isColumn("WEIGHT_SPECTRUM")) {
2461 0 : cout << "Creating WEIGHT_SPECTRUM!" << endl;
2462 :
2463 : // Nominal defaulttileshape
2464 0 : IPosition dts(3,4,32,1024);
2465 :
2466 : // Discern DATA's default tile shape and use it
2467 0 : const Record dminfo=ms_p->dataManagerInfo();
2468 0 : for (uInt i=0;i<dminfo.nfields();++i) {
2469 0 : Record col=dminfo.asRecord(i);
2470 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
2471 0 : if (anyEQ(col.asArrayString("COLUMNS"),String("DATA"))) {
2472 0 : dts=IPosition(col.asRecord("SPEC").asArrayInt("DEFAULTTILESHAPE"));
2473 0 : cout << "Found DATA's default tile: " << dts << endl;
2474 0 : break;
2475 : }
2476 0 : }
2477 :
2478 : // Add the column
2479 0 : String colWtSp=MS::columnName(MS::WEIGHT_SPECTRUM);
2480 0 : TableDesc tdWtSp;
2481 0 : tdWtSp.addColumn(ArrayColumnDesc<Float>(colWtSp,"weight spectrum", 2));
2482 0 : TiledShapeStMan wtSpStMan("TiledWgtSpectrum",dts);
2483 0 : ms_p->addColumn(tdWtSp,wtSpStMan);
2484 0 : }
2485 0 : }
2486 :
2487 : // Arrange for iteration over data
2488 0 : Block<Int> columns;
2489 : // include scan iteration
2490 0 : columns.resize(5);
2491 0 : columns[0]=MS::ARRAY_ID;
2492 0 : columns[1]=MS::SCAN_NUMBER;
2493 0 : columns[2]=MS::FIELD_ID;
2494 0 : columns[3]=MS::DATA_DESC_ID;
2495 0 : columns[4]=MS::TIME;
2496 :
2497 0 : vi::SortColumns sc(columns);
2498 0 : vi::VisibilityIterator2 vi2(*ms_p,sc,true);
2499 0 : vi::VisBuffer2 *vb = vi2.getVisBuffer();
2500 :
2501 0 : MSColumns mscol(*ms_p);
2502 0 : const MSSpWindowColumns& msspw(mscol.spectralWindow());
2503 0 : uInt nSpw=msspw.nrow();
2504 0 : Vector<Double> effChBw(nSpw,0.0);
2505 0 : for (uInt ispw=0;ispw<nSpw;++ispw) {
2506 0 : effChBw[ispw]=mean(msspw.effectiveBW()(ispw));
2507 : }
2508 :
2509 0 : Int ivb(0);
2510 0 : for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
2511 :
2512 0 : for (vi2.origin(); vi2.more(); vi2.next()) {
2513 :
2514 0 : Int spw = vb->spectralWindows()(0);
2515 :
2516 0 : auto nrow=vb->nRows();
2517 0 : Int nchan=vb->nChannels();
2518 0 : Int ncor=vb->nCorrelations();
2519 :
2520 0 : Matrix<Float> newwt(ncor,nrow),newsig(ncor,nrow);
2521 0 : newwt.set(1.0);
2522 0 : newsig.set(1.0);
2523 :
2524 0 : Cube<Float> newwtsp(0,0,0);
2525 0 : if (dowtsp) {
2526 0 : newwtsp.resize(ncor,nchan,nrow);
2527 0 : newwtsp.set(1.0);
2528 : }
2529 :
2530 : // If requested, set weights according to bandwidth and integration time
2531 0 : if (doBT) {
2532 :
2533 : // Detect ACs
2534 0 : const Vector<Int> a1(vb->antenna1());
2535 0 : const Vector<Int> a2(vb->antenna2());
2536 0 : Vector<Bool> ac(a1==a2);
2537 :
2538 : // XCs need an extra factor of 2
2539 0 : Vector<Float> xcfactor(nrow,2.0);
2540 0 : xcfactor(ac)=1.0; // (but not ACs)
2541 :
2542 : // The row-wise integration time
2543 0 : Vector<Float> expo(nrow);
2544 0 : convertArray(expo,vb->exposure());
2545 :
2546 : // Set weights to channel bandwidth first.
2547 0 : newwt.set(Float(effChBw(spw)));
2548 :
2549 : // For each correlation, apply exposure and xcfactor
2550 0 : for (Int icor=0;icor<ncor;++icor) {
2551 :
2552 0 : Vector<Float> wt(newwt.row(icor));
2553 0 : wt*=expo;
2554 0 : wt*=xcfactor;
2555 0 : if (dowtsp) {
2556 0 : for (Int ich=0;ich<nchan;++ich) {
2557 0 : Vector<Float> wtsp(newwtsp(Slice(icor,1,1),Slice(ich,1,1),Slice()));
2558 0 : wtsp=wt;
2559 0 : }
2560 : }
2561 :
2562 0 : }
2563 :
2564 : // sig from wt is inverse sqrt
2565 0 : newsig=newsig/sqrt(newwt);
2566 :
2567 0 : }
2568 :
2569 : /*
2570 : cout << ivb << " "
2571 : << ncor << " " << nchan << " " << nrow << " "
2572 : << expo(0) << " "
2573 : << newwt(0,0) << " "
2574 : << newsig(0,0) << " "
2575 : << endl;
2576 : */
2577 0 : ++ivb;
2578 :
2579 : // Set in vb, and writeback
2580 0 : vb->setWeight(newwt);
2581 0 : vb->setSigma(newsig);
2582 0 : vb->writeChangesBack();
2583 :
2584 0 : if (dowtsp)
2585 0 : vb->initWeightSpectrum(newwtsp);
2586 :
2587 0 : }
2588 : }
2589 :
2590 0 : }
2591 0 : catch (AipsError x) {
2592 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
2593 0 : << LogIO::POST;
2594 :
2595 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
2596 0 : unsetapply();
2597 :
2598 0 : throw(AipsError("Error in Calibrater::initWeightsOLD."));
2599 : retval = false; // Not that it ever gets here...
2600 0 : }
2601 0 : return retval;
2602 : }
2603 :
2604 :
2605 168 : Bool Calibrater::solve() {
2606 :
2607 168 : logSink() << LogOrigin("Calibrater","solve") << LogIO::NORMAL3;
2608 :
2609 : try {
2610 :
2611 168 : if (!ok())
2612 0 : throw(AipsError("Calibrater not prepared for solve."));
2613 :
2614 : // Handle nothing-to-solve-for case
2615 168 : if (!svc_p)
2616 0 : throw(AipsError("Please run setsolve before attempting to solve."));
2617 :
2618 : // Handle specified caltable
2619 168 : if (svc_p) {
2620 :
2621 : // If table exists (readable) and not deletable
2622 : // we have to abort (append=T requires deletable)
2623 186 : if ( Table::isReadable(svc_p->calTableName()) &&
2624 18 : !TableUtil::canDeleteTable(svc_p->calTableName()) ) {
2625 0 : throw(AipsError("Specified caltable ("+svc_p->calTableName()+") exists and\n cannot be replaced (or appended to) because it appears to be open somewhere (Quit plotcal?)."));
2626 : }
2627 : }
2628 :
2629 : // Arrange VisEquation for solve
2630 168 : ve_p->setsolve(*svc_p);
2631 :
2632 : // Ensure apply list properly sorted w.r.t. solvable term
2633 168 : ve_p->setapply(vc_p);
2634 :
2635 : // Report what is being applied and solved-for
2636 168 : applystate();
2637 168 : solvestate();
2638 :
2639 : // Report correct/corrupt apply order
2640 : // ve_p->state();
2641 :
2642 : // Generally use standard solver
2643 168 : if (svc_p->useGenericGatherForSolve())
2644 168 : genericGatherAndSolve(); // VI2-driven, SDBs
2645 : else {
2646 : //cout << "Fully self-directed data gather and solve" << endl;
2647 : // Fully self-directed data gather and solve
2648 0 : throw(AipsError("Can't do selfGatherAndSolve for "+svc_p->typeName()));
2649 : //svc_p->selfGatherAndSolve(*vs_p,*ve_p);
2650 : }
2651 :
2652 3 : } catch (AipsError x) {
2653 3 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
2654 :
2655 3 : logSink() << "Reseting entire solve/apply state." << LogIO::POST;
2656 3 : reset();
2657 :
2658 3 : throw(AipsError("Error in Calibrater::solve."));
2659 : return false;
2660 6 : }
2661 :
2662 165 : return true;
2663 :
2664 : }
2665 :
2666 :
2667 253 : Bool Calibrater::summarize_uncalspws(const Vector<Bool>& uncalspw,
2668 : const String& origin,
2669 : Bool strictflag)
2670 : {
2671 253 : Bool hadprob = false;
2672 253 : uInt totNspw = uncalspw.nelements();
2673 :
2674 1231 : for(uInt i = 0; i < totNspw; ++i){
2675 998 : if(uncalspw[i]){
2676 20 : hadprob = true;
2677 20 : break;
2678 : }
2679 : }
2680 253 : if(hadprob){
2681 : logSink() << LogIO::WARN
2682 20 : << "Spectral window(s) ";
2683 348 : for(uInt i = 0; i < totNspw; ++i){
2684 328 : if(uncalspw[i]){
2685 38 : logSink() << i << ", ";
2686 : }
2687 : }
2688 : logSink() << "\n could not be " << origin << "ed due to missing (pre-)calibration\n"
2689 20 : << " in one or more of the specified tables.\n";
2690 20 : if (strictflag)
2691 0 : logSink() << " These spws have been flagged!";
2692 : else
2693 20 : logSink() << " Please check your results carefully!";
2694 :
2695 20 : logSink() << LogIO::POST;
2696 : }
2697 253 : return !hadprob;
2698 : }
2699 :
2700 29 : void Calibrater::fluxscale(const String& infile,
2701 : const String& outfile,
2702 : const String& refFields,
2703 : const Vector<Int>& refSpwMap,
2704 : const String& tranFields,
2705 : const Bool& append,
2706 : const Float& inGainThres,
2707 : const String& antSel,
2708 : const String& timerangeSel,
2709 : const String& scanSel,
2710 : SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
2711 : Vector<Int>& tranidx,
2712 : const String& oListFile,
2713 : const Bool& incremental,
2714 : const Int& fitorder,
2715 : const Bool& display) {
2716 :
2717 : // TBD: Permit more flexible matching on specified field names
2718 : // (Currently, exact matches are required.)
2719 :
2720 29 : logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
2721 :
2722 : //outfile check
2723 29 : if (outfile=="")
2724 0 : throw(AipsError("output fluxscaled caltable name must be specified!"));
2725 : else {
2726 29 : if (File(outfile).exists() && !append)
2727 0 : throw(AipsError("output caltable name, "+outfile+" exists. Please specify a different caltable name"));
2728 : }
2729 :
2730 : // Convert refFields/transFields to index lists
2731 29 : Vector<Int> refidx(0);
2732 :
2733 29 : if (refFields.length()>0)
2734 29 : refidx=getFieldIdx(refFields);
2735 : else
2736 0 : throw(AipsError("A reference field must be specified!"));
2737 :
2738 29 : if (tranFields.length()>0)
2739 12 : tranidx=getFieldIdx(tranFields);
2740 :
2741 : // Call Vector<Int> version:
2742 29 : fluxscale(infile,outfile,refidx,refSpwMap,tranidx,append,inGainThres,antSel,timerangeSel,
2743 : scanSel,oFluxScaleFactor,oListFile,incremental,fitorder,display);
2744 :
2745 29 : }
2746 :
2747 29 : void Calibrater::fluxscale(const String& infile,
2748 : const String& outfile,
2749 : const Vector<Int>& refField,
2750 : const Vector<Int>& refSpwMap,
2751 : const Vector<Int>& tranField,
2752 : const Bool& append,
2753 : const Float& inGainThres,
2754 : const String& antSel,
2755 : const String& timerangeSel,
2756 : const String& scanSel,
2757 : SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
2758 : const String& oListFile,
2759 : const Bool& incremental,
2760 : const Int& fitorder,
2761 : const Bool& display) {
2762 :
2763 : // throw(AipsError("Method 'fluxscale' is temporarily disabled."));
2764 :
2765 : // TBD: write inputs to MSHistory
2766 29 : logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
2767 :
2768 29 : SolvableVisCal *fsvj_(NULL);
2769 : try {
2770 : // If infile is Calibration table
2771 58 : if (Table::isReadable(infile) &&
2772 58 : TableUtil::tableInfo(infile).type()=="Calibration") {
2773 :
2774 : // get calibration type
2775 29 : String caltype;
2776 29 : caltype = TableUtil::tableInfo(infile).subType();
2777 : logSink() << "Table " << infile
2778 : << " is of type: "<< caltype
2779 29 : << LogIO::POST;
2780 58 : String message="Table "+infile+" is of type: "+caltype;
2781 29 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
2782 :
2783 : // form selection
2784 29 : String select="";
2785 : // Selection is empty for case of no tran specification
2786 29 : if (tranField.nelements()>0) {
2787 :
2788 : // All selected fields
2789 12 : Vector<Int> allflds = concatenateArray(refField,tranField);
2790 :
2791 : // Assemble TaQL
2792 12 : ostringstream selectstr;
2793 12 : selectstr << "FIELD_ID IN [";
2794 42 : for (Int iFld=0; iFld<allflds.shape(); iFld++) {
2795 30 : if (iFld>0) selectstr << ", ";
2796 30 : selectstr << allflds(iFld);
2797 : }
2798 12 : selectstr << "]";
2799 12 : select=selectstr.str();
2800 12 : }
2801 :
2802 : // Construct proper SVC object
2803 29 : if (caltype == "G Jones") {
2804 29 : fsvj_ = createSolvableVisCal("G",*msmc_p);
2805 0 : } else if (caltype == "T Jones") {
2806 0 : fsvj_ = createSolvableVisCal("T",*msmc_p);
2807 : } else {
2808 : // Can't process other than G and T (add B?)
2809 0 : ostringstream typeErr;
2810 0 : typeErr << "Type " << caltype
2811 0 : << " not supported in fluxscale.";
2812 :
2813 0 : throw(AipsError(typeErr.str()));
2814 0 : }
2815 :
2816 : // fill table with selection
2817 29 : RecordDesc applyparDesc;
2818 29 : applyparDesc.addField ("table", TpString);
2819 29 : applyparDesc.addField ("select", TpString);
2820 29 : Record applypar(applyparDesc);
2821 29 : applypar.define ("table", infile);
2822 29 : applypar.define ("select", select);
2823 29 : fsvj_->setApply(applypar);
2824 :
2825 : //Bool incremental=false;
2826 : // Make fluxscale calculation
2827 29 : Vector<String> fldnames(MSFieldColumns(ms_p->field()).name().getColumn());
2828 : //fsvj_->fluxscale(refField,tranField,refSpwMap,fldnames,oFluxScaleFactor,
2829 29 : fsvj_->fluxscale(outfile,refField,tranField,refSpwMap,fldnames,inGainThres,antSel,
2830 : timerangeSel,scanSel,oFluxScaleFactor, oListFile,incremental,fitorder,display);
2831 : // oListFile);
2832 :
2833 : // If no outfile specified, use infile (overwrite!)
2834 29 : String out(outfile);
2835 29 : if (out.length()==0)
2836 0 : out = infile;
2837 :
2838 : // Store result
2839 29 : if (append) {
2840 1 : logSink() << "Appending result to " << out << LogIO::POST;
2841 1 : String message="Appending result to "+out;
2842 1 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
2843 1 : } else {
2844 28 : logSink() << "Storing result in " << out << LogIO::POST;
2845 28 : String message="Storing result in "+out;
2846 28 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
2847 28 : }
2848 29 : fsvj_->storeNCT(out,append);
2849 :
2850 : // Clean up
2851 29 : delete fsvj_;
2852 :
2853 29 : } else {
2854 : // Table not found/unreadable, or not Calibration
2855 0 : ostringstream tabErr;
2856 0 : tabErr << "File " << infile
2857 0 : << " does not exist or is not a Calibration Table.";
2858 :
2859 0 : throw(AipsError(tabErr.str()));
2860 :
2861 0 : }
2862 0 : } catch (AipsError x) {
2863 :
2864 : logSink() << LogIO::SEVERE
2865 : << "Caught Exception: "
2866 : << x.getMesg()
2867 0 : << LogIO::POST;
2868 :
2869 : // Clean up
2870 0 : if (fsvj_) delete fsvj_;
2871 :
2872 : // Write to MS History table
2873 : // String message="Caught Exception: "+x.getMesg();
2874 : // MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
2875 :
2876 0 : throw(AipsError("Error in Calibrater::fluxscale."));
2877 :
2878 : return;
2879 :
2880 0 : }
2881 29 : return;
2882 :
2883 :
2884 : }
2885 :
2886 209 : void Calibrater::specifycal(const String& type,
2887 : const String& caltable,
2888 : const String& time,
2889 : const String& spw,
2890 : const String& antenna,
2891 : const String& pol,
2892 : const Vector<Double>& parameter,
2893 : const String& infile,
2894 : const Bool& uniform) {
2895 :
2896 209 : logSink() << LogOrigin("Calibrater","specifycal") << LogIO::NORMAL;
2897 :
2898 : // SVJ objects:
2899 209 : SolvableVisCal *cal_(NULL);
2900 :
2901 : try {
2902 :
2903 : // Set record format for calibration table application information
2904 209 : RecordDesc specifyDesc;
2905 209 : specifyDesc.addField ("caltable", TpString);
2906 209 : specifyDesc.addField ("time", TpString);
2907 209 : specifyDesc.addField ("spw", TpArrayInt);
2908 209 : specifyDesc.addField ("antenna", TpArrayInt);
2909 209 : specifyDesc.addField ("pol", TpString);
2910 209 : specifyDesc.addField ("parameter", TpArrayDouble);
2911 209 : specifyDesc.addField ("caltype",TpString);
2912 209 : specifyDesc.addField ("infile",TpString);
2913 209 : specifyDesc.addField ("uniform",TpBool);
2914 :
2915 : // Create record with the requisite field values
2916 209 : Record specify(specifyDesc);
2917 209 : specify.define ("caltable", caltable);
2918 209 : specify.define ("time", time);
2919 209 : if (spw=="*")
2920 0 : specify.define ("spw",Vector<Int>(1,-1));
2921 : else
2922 209 : specify.define ("spw",getSpwIdx(spw));
2923 209 : if (antenna=="*")
2924 0 : specify.define ("antenna",Vector<Int>(1,-1) );
2925 : else
2926 209 : specify.define ("antenna",getAntIdx(antenna));
2927 209 : specify.define ("pol",pol);
2928 209 : specify.define ("parameter",parameter);
2929 209 : specify.define ("caltype",type);
2930 209 : specify.define ("infile",infile);
2931 209 : specify.define ("uniform",uniform);
2932 :
2933 : // Now do it
2934 209 : String utype=upcase(type);
2935 209 : if (utype=="G" || utype.contains("AMP") || utype.contains("PH"))
2936 194 : cal_ = createSolvableVisCal("G",*msmc_p);
2937 15 : else if (utype=='K' || utype.contains("SBD") || utype.contains("DELAY"))
2938 2 : cal_ = createSolvableVisCal("K",*msmc_p);
2939 13 : else if (utype.contains("MBD"))
2940 0 : cal_ = createSolvableVisCal("K",*msmc_p); // As of 5.3, MBD is ordinary K
2941 13 : else if (utype.contains("ANTPOS"))
2942 6 : cal_ = createSolvableVisCal("KANTPOS",*msmc_p);
2943 7 : else if (utype.contains("TSYS"))
2944 2 : cal_ = createSolvableVisCal("TSYS",*msmc_p);
2945 10 : else if (utype.contains("EVLAGAIN") ||
2946 9 : utype.contains("SWP") ||
2947 14 : utype.contains("RQ") ||
2948 4 : utype.contains("WTS"))
2949 1 : cal_ = createSolvableVisCal("EVLASWP",*msmc_p);
2950 4 : else if (utype.contains("OPAC"))
2951 0 : cal_ = createSolvableVisCal("TOPAC",*msmc_p);
2952 4 : else if (utype.contains("GC") && ms_p && ms_p->keywordSet().isDefined("GAIN_CURVE"))
2953 1 : cal_ = createSolvableVisCal("POWERCURVE",*msmc_p);
2954 3 : else if (utype.contains("GC") || utype.contains("EFF"))
2955 2 : cal_ = createSolvableVisCal("GAINCURVE",*msmc_p);
2956 1 : else if (utype.contains("TEC"))
2957 1 : cal_ = createSolvableVisCal("TEC",*msmc_p);
2958 0 : else if (utype.contains("SDSKY_PS"))
2959 0 : cal_ = createSolvableVisCal("SDSKY_PS",*msmc_p);
2960 0 : else if (utype.contains("SDSKY_RASTER"))
2961 0 : cal_ = createSolvableVisCal("SDSKY_RASTER",*msmc_p);
2962 0 : else if (utype.contains("SDSKY_OTF"))
2963 0 : cal_ = createSolvableVisCal("SDSKY_OTF",*msmc_p);
2964 : else
2965 0 : throw(AipsError("Unrecognized caltype."));
2966 :
2967 : // set up for specification (set up the CalSet)
2968 209 : cal_->setSpecify(specify);
2969 :
2970 : // fill with specified values
2971 208 : cal_->specify(specify);
2972 :
2973 : // Store result
2974 208 : cal_->storeNCT();
2975 :
2976 208 : delete cal_;
2977 :
2978 212 : } catch (AipsError x) {
2979 : logSink() << LogIO::SEVERE
2980 : << "Caught Exception: "
2981 : << x.getMesg()
2982 1 : << LogIO::POST;
2983 :
2984 1 : if (cal_) delete cal_;
2985 :
2986 1 : throw(AipsError("Error in Calibrater::specifycal."));
2987 : return;
2988 2 : }
2989 208 : return;
2990 :
2991 : }
2992 :
2993 :
2994 10 : Bool Calibrater::smooth(const String& infile,
2995 : String& outfile, // const Bool& append,
2996 : const String& smoothtype,
2997 : const Double& smoothtime,
2998 : const String& fields)
2999 : {
3000 :
3001 : // TBD: support append?
3002 : // TBD: spw selection?
3003 :
3004 10 : logSink() << LogOrigin("Calibrater","smooth") << LogIO::NORMAL;
3005 :
3006 10 : logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
3007 :
3008 :
3009 : // A pointer to an SVC
3010 10 : SolvableVisCal *svc(NULL);
3011 :
3012 : try {
3013 :
3014 : // Handle no in file
3015 10 : if (infile=="")
3016 0 : throw(AipsError("Please specify an input calibration table."));
3017 :
3018 : // Handle bad smoothtype
3019 10 : if (smoothtype!="mean" && smoothtype!="median")
3020 0 : throw(AipsError("Unrecognized smooth type!"));
3021 :
3022 : // Handle bad smoothtime
3023 10 : if (smoothtime<=0)
3024 1 : throw(AipsError("Please specify a strictly positive smoothtime."));
3025 :
3026 : // Handle no outfile
3027 9 : if (outfile=="") {
3028 0 : outfile=infile;
3029 : logSink() << "Will overwrite input file with smoothing result."
3030 0 : << LogIO::POST;
3031 : }
3032 :
3033 :
3034 9 : svc = createSolvableVisCal(calTableType(infile),*msmc_p);
3035 :
3036 9 : if (svc->smoothable()) {
3037 :
3038 : // Fill calibration table using setApply
3039 9 : RecordDesc applyparDesc;
3040 9 : applyparDesc.addField ("table", TpString);
3041 9 : Record applypar(applyparDesc);
3042 9 : applypar.define ("table", infile);
3043 9 : svc->setApply(applypar);
3044 :
3045 : // Convert refFields/transFields to index lists
3046 9 : Vector<Int> fldidx(0);
3047 9 : if (fields.length()>0)
3048 2 : fldidx=getFieldIdx(fields);
3049 :
3050 : // Delegate to SVC
3051 8 : svc->smooth(fldidx,smoothtype,smoothtime);
3052 :
3053 : // Store the result on disk
3054 : // if (append) logSink() << "Appending result to " << outfile << LogIO::POST;
3055 : //else
3056 8 : logSink() << "Storing result in " << outfile << LogIO::POST;
3057 :
3058 :
3059 8 : if (outfile != "")
3060 8 : svc->calTableName()=outfile;
3061 8 : svc->storeNCT();
3062 :
3063 : // Clean up
3064 8 : if (svc) delete svc; svc=NULL;
3065 :
3066 : // Apparently, it worked
3067 8 : return true;
3068 :
3069 11 : }
3070 : else
3071 0 : throw(AipsError("This type ("+svc->typeName()+") does not support smoothing."));
3072 :
3073 2 : } catch (AipsError x) {
3074 :
3075 : logSink() << LogIO::SEVERE
3076 : << "Caught Exception: "
3077 : << x.getMesg()
3078 2 : << LogIO::POST;
3079 : // Clean up
3080 2 : if (svc) delete svc; svc=NULL;
3081 :
3082 2 : throw(AipsError("Error in Calibrater::smooth."));
3083 :
3084 : return false;
3085 4 : }
3086 : return false;
3087 : }
3088 :
3089 : // Apply new reference antenna to calibration
3090 7 : Bool Calibrater::reRefant(const casacore::String& infile,
3091 : casacore::String& outfile,
3092 : const casacore::String& refantmode,
3093 : const casacore::String& refant)
3094 : {
3095 :
3096 7 : logSink() << LogOrigin("Calibrater","reRefant") << LogIO::NORMAL;
3097 :
3098 : // logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
3099 :
3100 :
3101 : // A pointer to an SVC
3102 7 : SolvableVisJones *svj(NULL);
3103 :
3104 : try {
3105 :
3106 : // Handle no in file
3107 7 : if (infile=="")
3108 0 : throw(AipsError("Please specify an input calibration table."));
3109 :
3110 : // Handle bad refantmode
3111 11 : if (refantmode!="strict" &&
3112 4 : refantmode!="flex")
3113 0 : throw(AipsError("Unrecognized refantmode!"));
3114 :
3115 : // Handle no outfile
3116 7 : if (outfile=="") {
3117 0 : outfile=infile;
3118 : logSink() << "Will overwrite input file with rerefant result."
3119 0 : << LogIO::POST;
3120 : }
3121 :
3122 :
3123 7 : svj = (SolvableVisJones*) createSolvableVisCal(calTableType(infile),*msmc_p);
3124 :
3125 : // Fill calibration table using setApply
3126 7 : RecordDesc applyparDesc;
3127 7 : applyparDesc.addField ("table", TpString);
3128 7 : Record applypar(applyparDesc);
3129 7 : applypar.define ("table", infile);
3130 7 : svj->setApply(applypar);
3131 :
3132 : // Do the work
3133 7 : svj->refantmode() = refantmode;
3134 7 : svj->refantlist().reference(getRefantIdxList(refant)); // replaces the default list
3135 7 : svj->applyRefAnt();
3136 :
3137 : // Store the result on disk
3138 7 : logSink() << "Storing result in " << outfile << LogIO::POST;
3139 :
3140 7 : if (outfile != "")
3141 7 : svj->calTableName()=outfile;
3142 7 : svj->storeNCT();
3143 :
3144 : // Clean up
3145 7 : if (svj) delete svj; svj=NULL;
3146 :
3147 : // Apparently, it worked
3148 7 : return true;
3149 :
3150 7 : } catch (AipsError x) {
3151 :
3152 : logSink() << LogIO::SEVERE
3153 : << "Caught Exception: "
3154 : << x.getMesg()
3155 0 : << LogIO::POST;
3156 : // Clean up
3157 0 : if (svj) delete svj; svj=NULL;
3158 :
3159 0 : throw(AipsError("Error in Calibrater::reRefant."));
3160 :
3161 : return false;
3162 0 : }
3163 : return false;
3164 : }
3165 :
3166 :
3167 : // List a calibration table
3168 10 : Bool Calibrater::listCal(const String& infile,
3169 : const String& field,
3170 : const String& antenna,
3171 : const String& spw,
3172 : const String& listfile,
3173 : const Int& pagerows) {
3174 :
3175 10 : SolvableVisCal *svc(NULL);
3176 10 : logSink() << LogOrigin("Calibrater","listCal");
3177 :
3178 : try {
3179 :
3180 : // Trap (currently) unsupported types
3181 30 : if (upcase(calTableType(infile))=="GSPLINE" ||
3182 20 : upcase(calTableType(infile))=="BPOLY")
3183 0 : throw(AipsError("GSPLINE and BPOLY tables cannot currently be listed."));
3184 :
3185 : // Get user's selected fields, ants
3186 10 : Vector<Int> ufldids=getFieldIdx(field);
3187 10 : Vector<Int> uantids=getAntIdx(antenna);
3188 :
3189 9 : String newSpw = spw;
3190 9 : Bool defaultSelect = false;
3191 9 : if (spw.empty()) { // list all channels (default)
3192 8 : defaultSelect = true;
3193 8 : newSpw = "*";
3194 : logSink() << LogIO::NORMAL1 << "Spws selected: ALL" << endl
3195 8 : << "Channels selected: ALL" << LogIO::POST;
3196 : }
3197 : // Get user's selected spw and channels
3198 9 : Vector<Int> uspwids=getSpwIdx(newSpw);
3199 9 : Matrix<Int> uchanids=getChanIdx(newSpw);
3200 9 : if (!defaultSelect) {
3201 : logSink() << LogIO::NORMAL1 << "Spw and Channel selection matrix: "
3202 : << endl << "Each rows shows: [ Spw , Start Chan , Stop Chan , Chan Step ]"
3203 1 : << endl << uchanids << LogIO::POST;
3204 : }
3205 : logSink() << LogIO::DEBUG2
3206 : << "uspwids = " << uspwids << endl
3207 9 : << "uchanids = " << uchanids << LogIO::POST;
3208 :
3209 : // By default, do first spw, first chan
3210 9 : if (uspwids.nelements()==0) {
3211 0 : uchanids.resize(1,4);
3212 0 : uchanids=0;
3213 : }
3214 :
3215 : // Set record format for calibration table application information
3216 9 : RecordDesc applyparDesc;
3217 9 : applyparDesc.addField ("table", TpString);
3218 :
3219 : // Create record with the requisite field values
3220 9 : Record applypar(applyparDesc);
3221 9 : applypar.define ("table", infile);
3222 :
3223 : // Generate the VisCal to be listed
3224 9 : svc = createSolvableVisCal(calTableType(infile),*msmc_p);
3225 9 : svc->setApply(applypar);
3226 :
3227 : // list it
3228 9 : svc->listCal(ufldids,uantids,uchanids, //uchanids(0,0),uchanids(0,1),
3229 : listfile,pagerows);
3230 :
3231 9 : if (svc) delete svc; svc=NULL;
3232 :
3233 9 : return true;
3234 :
3235 11 : } catch (AipsError x) {
3236 :
3237 : logSink() << LogIO::SEVERE
3238 : << "Caught Exception: "
3239 : << x.getMesg()
3240 1 : << LogIO::POST;
3241 : // Clean up
3242 1 : if (svc) delete svc; svc=NULL;
3243 :
3244 1 : throw(AipsError("Error in Calibrater::listCal."));
3245 :
3246 : return false;
3247 2 : }
3248 : return false;
3249 :
3250 : }
3251 :
3252 :
3253 :
3254 3 : Bool Calibrater::updateCalTable(const String& caltable) {
3255 :
3256 : // Call the SVC method that knows how
3257 3 : return NewCalTable::CTBackCompat(caltable);
3258 :
3259 : }
3260 :
3261 243 : void Calibrater::selectChannel(const String& spw) {
3262 :
3263 243 : if (mss_p && mssel_p) {
3264 :
3265 : // Refresh the frequencySelections object to feed to VI2, if relevant
3266 243 : frequencySelections_p.reset(new vi::FrequencySelections());
3267 :
3268 243 : vi::FrequencySelectionUsingChannels usingChannels;
3269 243 : usingChannels.add(*mss_p,mssel_p);
3270 243 : frequencySelections_p->add(usingChannels);
3271 :
3272 : // cout << usingChannels.toString() << endl;
3273 : // cout << "FS.size() = " << frequencySelections_p->size() << endl;
3274 :
3275 243 : }
3276 :
3277 : // TBD: Does frequencySelections_p support string info for reporting to logger?
3278 :
3279 243 : Matrix<Int> chansel = getChanIdx(spw);
3280 243 : uInt nselspw=chansel.nrow();
3281 :
3282 243 : if (nselspw==0)
3283 : logSink() << "Frequency selection: Selecting all channels in all spws."
3284 201 : << LogIO::POST;
3285 : else {
3286 :
3287 42 : logSink() << "Frequency selection: " << LogIO::POST;
3288 :
3289 : // Trap non-unit step (for now)
3290 42 : if (ntrue(chansel.column(3)==1)!=nselspw) {
3291 : logSink() << LogIO::WARN
3292 : << "Calibration does not support non-unit channel stepping; "
3293 : << "using step=1."
3294 0 : << LogIO::POST;
3295 0 : chansel.column(3)=1;
3296 : }
3297 :
3298 42 : Vector<Int> uspw(chansel.column(0));
3299 42 : Vector<Int> ustart(chansel.column(1));
3300 42 : Vector<Int> uend(chansel.column(2));
3301 42 : Vector<Int> ustep(chansel.column(3));
3302 :
3303 42 : logSink() << LogIO::NORMAL;
3304 118 : for (uInt i=0;i<nselspw;++i) {
3305 :
3306 152 : logSink() << ". Spw " << uspw(i) << ":"
3307 304 : << ustart(i) << "~" << uend(i)
3308 76 : << " (" << uend(i)-ustart(i)+1 << " channels,"
3309 152 : << " step by " << ustep(i) << ")"
3310 152 : << endl;
3311 :
3312 : } // i
3313 42 : logSink() << LogIO::POST;
3314 :
3315 42 : } // non-triv spw selection
3316 :
3317 243 : }
3318 :
3319 :
3320 1186 : Bool Calibrater::cleanup() {
3321 :
3322 : // logSink() << LogOrigin("Calibrater","cleanup") << LogIO::NORMAL;
3323 :
3324 : // Delete the VisCals
3325 1186 : reset();
3326 :
3327 : // Delete derived dataset stuff
3328 1186 : if(mssel_p) delete mssel_p; mssel_p=0;
3329 1186 : if(mss_p) delete mss_p; mss_p=0;
3330 1186 : frequencySelections_p.reset();
3331 :
3332 : // Delete the current VisEquation
3333 1186 : if(ve_p) delete ve_p; ve_p=0;
3334 :
3335 1186 : return true;
3336 :
3337 : }
3338 :
3339 : // Parse refant specification
3340 215 : Vector<Int> Calibrater::getRefantIdxList(const String& refant) {
3341 :
3342 215 : Vector<Int> irefant;
3343 215 : if (refant.length()==0) {
3344 : // Nothing specified, return -1 in single-element vector
3345 137 : irefant.resize(1);
3346 137 : irefant(0)=-1;
3347 : }
3348 : else {
3349 : // parse the specification
3350 78 : MSSelection msselect;
3351 78 : msselect.setAntennaExpr(refant);
3352 78 : Vector<Int> iref=msselect.getAntenna1List(mssel_p);
3353 78 : if (anyLT(iref,0))
3354 0 : cout << "Negated selection (via '!') not yet implemented for refant," << endl << " and will be ignored." << endl;
3355 78 : irefant=iref(iref>-1).getCompressedArray();
3356 78 : if (irefant.nelements()==0) {
3357 0 : irefant.resize(1);
3358 0 : irefant(0)=-1;
3359 : }
3360 78 : }
3361 :
3362 215 : return irefant;
3363 0 : }
3364 :
3365 :
3366 : // Interpret refant *index*
3367 235 : Vector<Int> Calibrater::getAntIdx(const String& antenna) {
3368 :
3369 235 : MSSelection msselect;
3370 235 : msselect.setAntennaExpr(antenna);
3371 469 : return msselect.getAntenna1List(mssel_p);
3372 :
3373 235 : }
3374 :
3375 : // Interpret field indices (MSSelection)
3376 53 : Vector<Int> Calibrater::getFieldIdx(const String& fields) {
3377 :
3378 53 : MSSelection mssel;
3379 53 : mssel.setFieldExpr(fields);
3380 105 : return mssel.getFieldList(mssel_p);
3381 :
3382 53 : }
3383 :
3384 : // Interpret spw indices (MSSelection)
3385 435 : Vector<Int> Calibrater::getSpwIdx(const String& spws) {
3386 :
3387 435 : MSSelection mssel;
3388 435 : mssel.setSpwExpr(spws);
3389 :
3390 : /*
3391 : cout << "mssel.getSpwList(mssel_p) = " << mssel.getSpwList(mssel_p) << endl;
3392 : cout << "mssel.getChanList(mssel_p) = " << mssel.getChanList(mssel_p) << endl; cout << "Vector<Int>() = " << Vector<Int>() << endl;
3393 : */
3394 :
3395 : // Use getChanList (column 0 for spw) because it is
3396 : // more reliable about the number and order of specified spws.
3397 : // return mssel.getSpwList(mssel_p);
3398 435 : Matrix<Int> chanmat=mssel.getChanList(mssel_p);
3399 435 : if (chanmat.nelements()>0)
3400 205 : return chanmat.column(0);
3401 : else
3402 230 : return Vector<Int>();
3403 :
3404 435 : }
3405 :
3406 417 : Matrix<Int> Calibrater::getChanIdx(const String& spw) {
3407 :
3408 417 : MSSelection mssel;
3409 417 : mssel.setSpwExpr(spw);
3410 :
3411 834 : return mssel.getChanList(mssel_p);
3412 :
3413 417 : }
3414 :
3415 :
3416 : // Query apply types if we are calibrating the weights
3417 178325 : Bool Calibrater::calWt() {
3418 :
3419 178325 : Int napp(vc_p.nelements());
3420 : // Return true as soon as we find a type which is cal'ing wts
3421 185881 : for (Int iapp=0;iapp<napp;++iapp)
3422 178325 : if (vc_p[iapp] && vc_p[iapp]->calWt())
3423 170769 : return true;
3424 :
3425 : // None cal'd weights, so return false
3426 7556 : return false;
3427 :
3428 : }
3429 :
3430 536 : Bool Calibrater::ok() {
3431 :
3432 536 : if ((simdata_p ||
3433 536 : (ms_p && mssel_p))
3434 536 : && ve_p) {
3435 536 : return true;
3436 : }
3437 : else {
3438 0 : logSink() << "Calibrater is not yet initialized" << LogIO::POST;
3439 0 : return false;
3440 : }
3441 : }
3442 : // The standard solving mechanism
3443 168 : casacore::Bool Calibrater::genericGatherAndSolve()
3444 : {
3445 :
3446 : #ifdef _OPENMP
3447 168 : Double Tsetup(0.0),Tgather(0.0),Tsolve(0.0),Tadd(0.0);
3448 168 : Double time0=omp_get_wtime();
3449 : #endif
3450 :
3451 : // Create record to store results
3452 168 : resRec_ = Record();
3453 168 : Record attemptRec;
3454 168 : attemptRec = Record();
3455 :
3456 : // Condition solint values
3457 168 : svc_p->reParseSolintForVI2();
3458 :
3459 : // Organize VI2 layers for solving:
3460 168 : CalSolVi2Organizer vi2org;
3461 :
3462 : //-------------------------------------------------
3463 : // NB: Populating the vi2org should probably be delegated to the svc_p
3464 : // since that is where most of the required (non-data) info is,
3465 : // and then some calibration types may introduce layers that are
3466 : // very specific to them (e.g., SD data selection, etc.)
3467 : // e.g., replace the following with something like:
3468 : //
3469 : // svc_p->formVi2LayerFactories(vi2org,mssel_p,ve_p);
3470 : // ssvp_p // a simdata version
3471 : //
3472 :
3473 : // Add the (bottom) data access layer
3474 168 : if (simdata_p)
3475 : // Simulated data (used for testing)
3476 0 : vi2org.addSimIO(ssvp_p);
3477 : else
3478 : {
3479 : // Real (selected) data in an MS (channel selection handled by addDiskIO method)
3480 : // The iteration time-interval is the solution interval
3481 168 : vi2org.addDiskIO(mssel_p,svc_p->solTimeInterval(),
3482 168 : svc_p->combobs(),svc_p->combscan(),
3483 168 : svc_p->combfld(),svc_p->combspw(),
3484 : true, // use MSIter2
3485 168 : frequencySelections_p); // Tell VI2 factory about the freq selection!
3486 : }
3487 :
3488 : // Add ad hoc SD section layer (e.g., OTF select of raster boundaries, etc.)
3489 : // only double circle gain calibration is implemented
3490 168 : bool SD = svc_p->longTypeName().startsWith("SDGAIN_OTFD");
3491 168 : if (SD) {
3492 9 : vi2org.addCalFilter(calFilterConfig_p);
3493 : }
3494 :
3495 : // Add pre-cal layer, using the VisEquation
3496 : // (include control for corr-dep flags)
3497 168 : vi2org.addCalForSolving(*ve_p,corrDepFlags_);
3498 :
3499 :
3500 : // Add the freq-averaging layer, if needed
3501 : //cout << "svc_p->fintervalChV() = " << svc_p->fintervalChV() << endl;
3502 : //cout << "svc_p->fsolint() = " << svc_p->fsolint() << endl;
3503 : // TBD: improve the following logic with new method in SVC...
3504 246 : if (!svc_p->freqDepMat() || // entirely unchannelized cal OR
3505 125 : (svc_p->freqDepPar() && // channelized par and
3506 47 : svc_p->fsolint()!="none" && // some partial channel averaging
3507 171 : anyGT(svc_p->fintervalChV(),1.0)) // explicity specified (non-trivially)
3508 : ) {
3509 92 : Vector<Int> chanbin(svc_p->fintervalChV().nelements());
3510 92 : convertArray(chanbin,svc_p->fintervalChV());
3511 92 : vi2org.addChanAve(chanbin);
3512 92 : }
3513 :
3514 : // Add the time-averaging layer, if needed
3515 : // NB: There is some evidence that doing time-averaging _after_
3516 : // channel averaging may be more expensive then doing it _before_,
3517 : // but this ensures that the meta-info (e.g. time, timeCentroid, etc.)
3518 : // appear correctly in the VB2 accessed at this scope.
3519 : // The problem is that AveragingTvi2 has not explicitly
3520 : // implemented all of the relevant data accessors; it just
3521 : // assumes---incorrectly---that you are going to use its VB2.
3522 : // Making AveragingTvi2 the top layer ensures you do use it.
3523 : // (Hard-wired use of AveragingTvi2 in MSTransform set it up
3524 : // as the top [last] layer, and has been well-tested...)
3525 :
3526 : //cout << "svc_p->solint() = " << svc_p->solint() << endl;
3527 : //cout << "svc_p->solTimeInterval() = " << svc_p->solTimeInterval() << endl;
3528 : //cout << "svc_p->preavg() = " << svc_p->preavg() << endl;
3529 324 : if (!svc_p->solint().contains("int") && // i.e., not "int")
3530 156 : svc_p->preavg() != -DBL_MAX) {
3531 130 : Float avetime(svc_p->solTimeInterval()); // avetime is solint, nominally
3532 : // Use preavg instead, if...
3533 260 : if (svc_p->preavg()>FLT_EPSILON && // ...set meaningfully
3534 130 : svc_p->preavg()<svc_p->solTimeInterval()) // ...and less than solint
3535 35 : avetime=svc_p->preavg();
3536 130 : vi2org.addTimeAve(avetime); // use min of solint and preavg here!
3537 : }
3538 : // small@jive.eu (2021-12-17): Currently we only handle the corrcomb
3539 : // cases of "all" and "none"; there will be a need to extend this, but the
3540 : // PolAverageTVILayerFactory that underlies this feature will also need to be extended
3541 : // to make that possible
3542 168 : if (svc_p->corrcomb().contains("all")) {
3543 : //cerr << "Calibrater::genericGatherAndSolve(): Combining correlations!" << endl;
3544 1 : vi2org.addCorrCombine();
3545 : }
3546 : //else {
3547 : // cerr << "Calibrater::genericGatherAndSolve(): Not combining correlations!" << endl;
3548 : //}
3549 :
3550 : // vi2org should be fully configured at this point
3551 : //-------------------------------------------------
3552 :
3553 :
3554 : // Form the VI2 to drive data iteration below
3555 168 : vi::VisibilityIterator2& vi(vi2org.makeFullVI());
3556 : // cout << "VI Layers: " << vi.ViiType() << endl;
3557 :
3558 : // Establish output freq meta data prior to solving (CAS-12735 and related)
3559 :
3560 : // Discern (even implicitly-)selected spw subset
3561 168 : set<uInt> selspwset;
3562 168 : if (!simdata_p) {
3563 :
3564 : // We can't proceed rationally if we have more than one freqSelection (multiple MSs)
3565 : // (this is a sort-of out-of-the-blue test here....)
3566 168 : AlwaysAssert(frequencySelections_p->size()<2,AipsError);
3567 :
3568 : // TBD can we use the msmc_p? (or maybe it is for the whole MS, not just the selected one?)
3569 168 : MSMetaData msmdtmp(mssel_p,50.0);
3570 168 : selspwset=msmdtmp.getSpwIDs();
3571 168 : }
3572 :
3573 : // Extract selected spw list as a Vector<uInt>
3574 168 : Vector<uInt> selspwlist;
3575 168 : if (!simdata_p && selspwset.size()>0) {
3576 168 : Vector<uInt> vtmp(selspwset.begin(),selspwset.size(),0);
3577 168 : selspwlist.reference(vtmp);
3578 168 : } else {
3579 : // All spws in the MS (this is a last resort!)
3580 : // NB: This is used in simdata_p=True context!
3581 0 : selspwlist.resize(msmc_p->nSpw());
3582 0 : indgen(selspwlist);
3583 : }
3584 : // cout << "selspwlist = " << selspwlist << endl;
3585 :
3586 : // Delegate freq meta calculation to the SVC (wherein this info is stored)
3587 168 : svc_p->discernAndSetSolnFrequencies(vi,selspwlist);
3588 :
3589 :
3590 : // Access to the net VB2 for forming SolveDataBuffers in the SDBList below
3591 : // NB: this assumes that the internal address of the VI2's VB2 will never change!
3592 165 : vi::VisBuffer2 *vb = vi.getImpl()->getVisBuffer();
3593 :
3594 : // VI2 should now be ready....
3595 :
3596 : // Discern number of Solutions and how many VI2 chunks per each
3597 165 : Int nSol(0);
3598 165 : Vector<Int> nChPSol(1000,0); // nominal size; will enlarge as needed, and trim at end
3599 :
3600 : {
3601 : //cout << "Counting chunks and solutions..." << endl;
3602 165 : uInt isol(0);
3603 : // uInt ichk(0);
3604 19882 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
3605 : // NB: this loop NEVER touches the the subChunks, since
3606 : // this would cause data I/O, cal, averaging, etc.
3607 :
3608 : // int frame=vi.getImpl()->getReportingFrameOfReference();
3609 : // cout << "ichk=" << ichk << " freqs= " << vi.getImpl()->getFrequencies(-1.0e0,frame,selspwlist(ispw),0);
3610 :
3611 :
3612 : // Enlarge nChPSol Vector, if necessary
3613 19717 : if (isol>nChPSol.nelements()-1) {
3614 : //cout << " ...At isol=" << isol << ", resizing nchPSol: " << nChPSol.nelements() << "-->";
3615 6 : nChPSol.resize(isol*2,True); // double length, copy existing elements
3616 6 : nChPSol(Slice(isol,isol,1)).set(0); // init new elements
3617 : //cout << nChPSol.nelements() << endl;
3618 : //cout << "sol counting: " << isol << " " << nChPSol << " (" << ntrue(nChPSol>0) << "/" << nChPSol.nelements() << ")" << endl;
3619 : }
3620 :
3621 : // incr chunk counter for current solution
3622 19717 : ++nChPSol(isol);
3623 : //cout << "sol counting: " << isol << " " << nChPSol(Slice(0,min(isol+2,nChPSol.nelements()),1))
3624 : // << " (" << ntrue(nChPSol>0) << "/" << nChPSol.nelements() << ")"
3625 : // << " keyCh=" << vi.keyChange()
3626 : // << endl;
3627 :
3628 : // next chunk is nominally next solution
3629 19717 : ++isol;
3630 :
3631 : // If combining spw or field, and the next chunk changes by
3632 : // DATA_DESC_ID or FIELD_ID (and _not_ TIME, which is
3633 : // changing slower than these when combine is on),
3634 : // then the next chunk should be counted in the same soln
3635 59051 : if ( (svc_p->combspw() && vi.keyChange()=="DATA_DESC_ID") ||
3636 39334 : (svc_p->combfld() && vi.keyChange()=="FIELD_ID") )
3637 112 : --isol; // next one is the same solution interval
3638 :
3639 : }
3640 : // Trim list to realized length, which is the number of solutions we'll
3641 : // attempt below
3642 165 : nSol=ntrue(nChPSol>0);
3643 165 : nChPSol.resize(nSol,true);
3644 : //cout << "nSol =" << nSol << endl;
3645 : //cout << "nChPSol=" << nChPSol << endl;
3646 :
3647 : /* from SVC...
3648 : if (svc_p->combobs())
3649 : logSink() << "Combining observation Ids." << LogIO::POST;
3650 : if (svc_p->combscan())
3651 : logSink() << "Combining scans." << LogIO::POST;
3652 : if (svc_p->combspw())
3653 : logSink() << "Combining spws: " << spwlist << " -> " << spwlab << LogIO::POST;
3654 : if (svc_p->combfld())
3655 : logSink() << "Combining fields." << LogIO::POST;
3656 : */
3657 :
3658 165 : logSink() << "For solint = " << svc_p->solint() << ", found "
3659 : << nSol << " solution intervals."
3660 165 : << LogIO::POST;
3661 : }
3662 :
3663 : // throw(AipsError("EARLY ESCAPE!!"));
3664 :
3665 : // Create the output caltable
3666 : // (this version doesn't revise frequencies)
3667 165 : svc_p->createMemCalTable2();
3668 :
3669 165 : Vector<Float> spwwts(msmc_p->nSpw(),-1.0);
3670 165 : Vector<Int64> nexp(msmc_p->nSpw(),0), natt(msmc_p->nSpw(),0),nsuc(msmc_p->nSpw(),0), nbelowsnr(msmc_p->nSpw(),0), nbelowbl(msmc_p->nSpw(),0);
3671 :
3672 : // Start Collecting counts
3673 165 : CalCounts* calCounts = new CalCounts();
3674 165 : calCounts->initCounts(msmc_p->nSpw(),msmc_p->nAnt(), svc_p->nPar());
3675 : // Set up results record
3676 165 : std::map<Int, std::map<String, Vector<Int>>> resultMap;
3677 :
3678 :
3679 : #ifdef _OPENMP
3680 165 : Tsetup+=(omp_get_wtime()-time0);
3681 : #endif
3682 :
3683 165 : Int nGood(0);
3684 165 : vi.originChunks();
3685 165 : Int nGlobalChunks=0; // counts VI chunks globally
3686 19770 : for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
3687 :
3688 : #ifdef _OPENMP
3689 19605 : time0=omp_get_wtime();
3690 : #endif
3691 :
3692 : // Data will accumulate here
3693 19605 : SDBList sdbs;
3694 :
3695 : // Gather the chunks/VBs for this solution
3696 : // Solution boundaries will ALWAYS occur on chunk boundaries,
3697 : // though some chunk boundaries will be ignored in the
3698 : // combine='spw' or 'field' context
3699 :
3700 19605 : for (Int ichunk=0; // count chunks in this solution
3701 39322 : ichunk<nChPSol(isol)&&vi.moreChunks(); // while more chunks needed _and_ available
3702 19717 : ++ichunk,vi.nextChunk()) { // advance to next chunk
3703 :
3704 : // Global chunk counter
3705 19717 : ++nGlobalChunks;
3706 :
3707 : // Loop over VB2s in this chunk
3708 : // (we get more then one when preavg<solint)
3709 19717 : Int ivb(0);
3710 19717 : for (vi.origin();
3711 66913 : vi.more();
3712 47196 : ++ivb,vi.next()) {
3713 :
3714 : // Add this VB to the SDBList
3715 : #ifdef _OPENMP
3716 47196 : Double Tadd0=omp_get_wtime();
3717 : #endif
3718 :
3719 47196 : sdbs.add(*vb);
3720 :
3721 : #ifdef _OPENMP
3722 47196 : Tadd+=(omp_get_wtime()-Tadd0);
3723 : #endif
3724 :
3725 : // Keep track of spws seen but not included in solving
3726 47196 : Int ispw=vb->spectralWindows()(0);
3727 47196 : if (spwwts(ispw)<0) spwwts(ispw)=0.0f;
3728 47196 : spwwts(ispw)+=sum(vb->weightSpectrum());
3729 :
3730 : /*
3731 : Double modv(86400.0);
3732 : cout.precision(7);
3733 : cout << "isol=" << isol
3734 : << " ichk="<<ichunk
3735 : << " ivb="<<ivb
3736 : << " sc="<<vb->scan()(0)
3737 : << " fld="<<vb->fieldId()(0)
3738 : << " spw="<<vb->spectralWindows()(0)
3739 : << " nr="<<vb->nRows()
3740 : << " nch="<<vb->nChannels() << flush;
3741 : cout << " f="<<mean(vb->getFrequencies(0))/1e9
3742 : << "->"<< mean(sdbs.freqs())/1e9
3743 : << " t="<<fmod(mean(vb->time()),modv)
3744 : << "->"<< fmod(sdbs.aggregateTime(),modv)
3745 : << " tC="<<fmod(mean(vb->timeCentroid()),modv)
3746 : << "->"<< fmod(sdbs.aggregateTimeCentroid(),modv)
3747 : << " wt="<<sum(vb->weightSpectrum())
3748 : << " nSDB=" << sdbs.nSDB()
3749 : << " nGlChks=" << nGlobalChunks
3750 : << " (keych=" << vi.keyChange() << ")"
3751 : << endl;
3752 : //*/
3753 :
3754 : } // VI2 subchunks (VB2s)
3755 : } // VI2 chunks
3756 :
3757 : // Which spw is this?
3758 19605 : Int thisSpw(sdbs.aggregateSpw());
3759 :
3760 : // Expecting a solution
3761 19605 : nexp(thisSpw)+=1;
3762 : // Initialize the antennaMap_ in svc
3763 19605 : svc_p->clearMap();
3764 : // Get expected and data unflagged accumulation
3765 19605 : svc_p->expectedUnflagged(sdbs);
3766 :
3767 :
3768 : #ifdef _OPENMP
3769 19605 : Tgather+=(omp_get_wtime()-time0);
3770 19605 : time0=omp_get_wtime();
3771 : #endif
3772 :
3773 :
3774 19605 : if (sdbs.Ok()) {
3775 :
3776 : // Some unflagged data, so Attempting a solution
3777 19570 : natt(thisSpw)+=1;
3778 :
3779 : // make phase- or amp-only, if necessary
3780 19570 : sdbs.enforceAPonData(svc_p->apmode());
3781 :
3782 : // zero cross-hand weights, if necessary
3783 19570 : sdbs.enforceSolveWeights(svc_p->phandonly());
3784 :
3785 : // Synchronize meta-info in SVC
3786 19570 : svc_p->syncSolveMeta(sdbs);
3787 :
3788 : // Set or verify freqs in the caltable
3789 : //svc_p->setOrVerifyCTFrequencies(thisSpw);
3790 19570 : svc_p->setCTFrequencies(thisSpw);
3791 :
3792 : // Size the solvePar arrays inside SVC
3793 : // (smart: if freqDepPar()=F, uses 1)
3794 : // returns the number of channel solutions to iterate over
3795 : //Int nChanSol=svc_p->sizeSolveParCurrSpw(sdbs.nChannels());
3796 19570 : Int nChanSol=svc_p->sizeSolveParCurrSpw((svc_p->freqDepPar() ? sdbs.nChannels() : 1));
3797 :
3798 19570 : if (svc_p->useGenericSolveOne()) {
3799 :
3800 : // We'll use the generic solver
3801 15936 : VisCalSolver2 vcs(svc_p->solmode(),svc_p->rmsthresh());
3802 :
3803 : // Guess from the data
3804 15936 : svc_p->guessPar(sdbs,corrDepFlags_);
3805 :
3806 15936 : Bool totalGoodSol(False); // Will be set True if any channel is good
3807 : //for (Int ich=0;ich<nChanSol;++ich) {
3808 33120 : for (Int ich=nChanSol-1;ich>-1;--ich) {
3809 17184 : svc_p->markTimer();
3810 17184 : svc_p->focusChan()=ich;
3811 :
3812 : // Execute the solve
3813 17184 : Bool goodsol=vcs.solve(*ve_p,*svc_p,sdbs);
3814 :
3815 17184 : if (goodsol) {
3816 9414 : totalGoodSol=True;
3817 :
3818 9414 : svc_p->formSolveSNR();
3819 9414 : svc_p->applySNRThreshold();
3820 : }
3821 : else
3822 7770 : svc_p->currMetaNote();
3823 :
3824 : // Record solution in its channel, good or bad
3825 17184 : if (svc_p->freqDepPar())
3826 1278 : svc_p->keep1(ich);
3827 :
3828 : } // ich
3829 :
3830 15936 : if (totalGoodSol) {
3831 : // Keep this good solution, and count it
3832 8538 : svc_p->keepNCT();
3833 8538 : ++nGood;
3834 8538 : nsuc(thisSpw)+=1;
3835 : }
3836 :
3837 15936 : } // useGenericSolveOne
3838 : else {
3839 : // Use self-directed individual solve
3840 : // TBD: return T/F for goodness?
3841 : //cout << "Calling selfSolveOne()!!!!!!" << endl;
3842 3634 : svc_p->selfSolveOne(sdbs);
3843 :
3844 : // Keep this good solution, and count it
3845 3634 : svc_p->keepNCT();
3846 3634 : ++nGood;
3847 3634 : nsuc(thisSpw)+=1;
3848 : }
3849 :
3850 : } // sdbs.Ok()
3851 : else {
3852 : // Synchronize meta-info in SVC
3853 35 : svc_p->syncSolveMeta(sdbs);
3854 35 : cout << "Found no unflagged data at:";
3855 35 : svc_p->currMetaNote();
3856 : }
3857 : //cout << endl;
3858 : // Get all the antenna value counts
3859 19605 : resultMap = svc_p->getAntennaMap();
3860 19605 : calCounts->addAntennaCounts(thisSpw,msmc_p->nAnt(), svc_p->nPar(), resultMap);
3861 :
3862 : #ifdef _OPENMP
3863 19605 : Tsolve+=(omp_get_wtime()-time0);
3864 : #endif
3865 :
3866 : // throw(AipsError("EARLY ESCAPE!!"));
3867 :
3868 19605 : } // isol
3869 :
3870 : // Report nGood to logger
3871 : logSink() << " Found good "
3872 165 : << svc_p->typeName() << " solutions in "
3873 : << nGood << " solution intervals."
3874 165 : << LogIO::POST;
3875 :
3876 : #ifdef _OPENMP
3877 : #ifdef REPORT_CAL_TIMING
3878 : cout << "Calibrater::genericGatherAndSolve Timing: " << endl;
3879 : cout << " setup=" << Tsetup
3880 : << " gather=" << Tgather
3881 : << " (SDBadd=" << Tadd << ")"
3882 : << " solve=" << Tsolve
3883 : << " total=" << Tsetup+Tgather+Tsolve
3884 : // << " tick=" << omp_get_wtick()
3885 : << endl;
3886 : #endif
3887 : #endif
3888 :
3889 : // Report spws that were seen but not solved
3890 165 : Vector<Bool> unsolspw=(spwwts==0.0f);
3891 165 : summarize_uncalspws(unsolspw, "solv");
3892 :
3893 : // throw(AipsError("EARLY ESCAPE!!"));
3894 :
3895 165 : if (nGood>0) {
3896 160 : if (svc_p->typeName()!="BPOLY") { // needed?
3897 : // apply refant, etc.
3898 160 : svc_p->clearRefantMap();
3899 160 : svc_p->globalPostSolveTinker();
3900 :
3901 : // write to disk
3902 160 : svc_p->storeNCT();
3903 : }
3904 : }
3905 : else {
3906 : logSink() << "No output calibration table written."
3907 5 : << LogIO::POST;
3908 : }
3909 :
3910 : // Collect and update the refants
3911 165 : std::map<Int, std::map<Int, Int>> refantMap;
3912 165 : refantMap = svc_p->getRefantMap();
3913 165 : calCounts->updateRefants(msmc_p->nSpw(), msmc_p->nAnt(), refantMap);
3914 : // Compile all accumulated counts into a record
3915 165 : resRec_ = calCounts->makeRecord(msmc_p->nAnt(), vi.nPolarizationIds());
3916 :
3917 : // print a matrix to the logger
3918 165 : logSink() << "----- PER ANTENNA INFO -----" << LogIO::POST;
3919 : // print the antenna list
3920 165 : logSink() << " ";
3921 1866 : for (Int ant=0; ant<msmc_p->nAnt(); ant++) {
3922 1701 : logSink() << " ANT: " << ant << " ";
3923 : }
3924 165 : logSink() << LogIO::POST;
3925 :
3926 779 : for (Int spw=0; spw < msmc_p->nSpw(); spw++) {
3927 :
3928 614 : logSink() << LogIO::NORMAL << "SPW: " << spw;
3929 :
3930 6206 : for (Int ant=0; ant < msmc_p->nAnt(); ant++) {
3931 5592 : logSink() << " " << calCounts->antMapVal(spw, ant, "above_minsnr") << " ";
3932 : }
3933 614 : logSink() << LogIO::POST;
3934 : }
3935 :
3936 165 : logSink() << "----- PER SPW INFO -----" << LogIO::POST;
3937 : // print the result fields
3938 165 : logSink() << " ";
3939 165 : logSink() << " expected data_unflagged above_minblperant above_minsnr";
3940 165 : logSink() << LogIO::POST;
3941 779 : for (Int spw = 0; spw < msmc_p->nSpw(); spw++) {
3942 614 : logSink() << LogIO::NORMAL << "SPW: " << spw << " ";
3943 614 : logSink() << calCounts->spwMapVal(spw, "expected") << " ";
3944 614 : logSink() << calCounts->spwMapVal(spw, "data_unflagged") << " ";
3945 614 : logSink() << calCounts->spwMapVal(spw, "above_minblperant") << " ";
3946 614 : logSink() << calCounts->spwMapVal(spw, "above_minsnr");
3947 614 : logSink() << LogIO::POST;
3948 : }
3949 :
3950 165 : logSink() << "----- GLOBAL INFO -----" << LogIO::POST;
3951 165 : logSink() << "expected data_unflagged above_minblperant above_minsnr";
3952 165 : logSink() << LogIO::POST;
3953 165 : logSink() << calCounts->totalMapVal("expected") << " ";
3954 165 : logSink() << calCounts->totalMapVal("data_unflagged") << " ";
3955 165 : logSink() << calCounts->totalMapVal("above_minblperant") << " ";
3956 165 : logSink() << calCounts->totalMapVal("above_minsnr");
3957 165 : logSink() << LogIO::POST;
3958 :
3959 : // Fill activity record
3960 :
3961 165 : actRec_ = Record();
3962 165 : actRec_.define("origin","Calibrater::genericGatherAndSolve");
3963 165 : actRec_.define("nExpected",nexp);
3964 165 : actRec_.define("nAttempt",natt);
3965 165 : actRec_.define("nSucceed",nsuc);
3966 :
3967 : //cout << nexp << ", " << natt << ", " << nsuc << endl;
3968 :
3969 : {
3970 165 : Record solveRec=svc_p->solveActionRec();
3971 165 : if (solveRec.nfields()>0)
3972 6 : actRec_.merge(solveRec);
3973 165 : }
3974 :
3975 : // Reach here, all is good
3976 165 : return True;
3977 :
3978 177 : }
3979 :
3980 :
3981 0 : void Calibrater::writeHistory(LogIO& /*os*/, Bool /*cliCommand*/)
3982 : {
3983 : // Disabled 2016/04/19: avoid direct MS.HISTORY updates from
3984 : // below the python level, FOR NOW
3985 :
3986 0 : return;
3987 : /*
3988 : if (!historytab_p.isNull()) {
3989 : if (histLockCounter_p == 0) {
3990 : historytab_p.lock(false);
3991 : }
3992 : ++histLockCounter_p;
3993 :
3994 : os.postLocally();
3995 : if (cliCommand) {
3996 : hist_p->cliCommand(os);
3997 : } else {
3998 : hist_p->addMessage(os);
3999 : }
4000 :
4001 : if (histLockCounter_p == 1) {
4002 : historytab_p.unlock();
4003 : }
4004 : if (histLockCounter_p > 0) {
4005 : --histLockCounter_p;
4006 : }
4007 : } else {
4008 : os << LogIO::SEVERE << "calibrater is not yet initialized" << LogIO::POST;
4009 : }
4010 : */
4011 : }
4012 :
4013 168 : void Calibrater::setCalFilterConfiguration(String const &type,
4014 : Record const &config) {
4015 : // currently only SDDoubleCircleGainCal requires data filtering
4016 168 : if (type.startsWith("SDGAIN_OTFD")) {
4017 9 : calFilterConfig_p.define("mode", "SDGAIN_OTFD");
4018 9 : if (config.isDefined("smooth")) {
4019 9 : calFilterConfig_p.define("smooth", config.asBool("smooth"));
4020 : }
4021 9 : if (config.isDefined("radius")) {
4022 9 : calFilterConfig_p.define("radius", config.asString("radius"));
4023 : }
4024 : }
4025 168 : }
4026 :
4027 : // *********************************************
4028 : // OldCalibrater implementations that use vs_p
4029 :
4030 203 : OldCalibrater::OldCalibrater():
4031 : Calibrater(),
4032 203 : vs_p(0),
4033 203 : rawvs_p(0)
4034 : {
4035 : // cout << "This is the OLD VI2-aware Calibrater" << endl;
4036 203 : }
4037 :
4038 9 : OldCalibrater::OldCalibrater(String msname):
4039 : Calibrater(msname),
4040 9 : vs_p(0),
4041 9 : rawvs_p(0)
4042 : {
4043 9 : }
4044 :
4045 : /*
4046 : OldCalibrater::OldCalibrater(const OldCalibrater & other) :
4047 : Calibrater(other)
4048 : {
4049 : operator=(other);
4050 : }
4051 :
4052 : OldCalibrater& OldCalibrater::operator=(const OldCalibrater & other)
4053 : {
4054 : Calibrater::operator=(other); // copy parental units
4055 : vs_p=other.vs_p;
4056 : rawvs_p=other.rawvs_p;
4057 : return *this;
4058 : }
4059 : */
4060 :
4061 424 : OldCalibrater::~OldCalibrater()
4062 : {
4063 212 : OldCalibrater::cleanupVisSet();
4064 424 : }
4065 :
4066 :
4067 : // Select data (using MSSelection syntax)
4068 168 : void OldCalibrater::selectvis(const String& time,
4069 : const String& spw,
4070 : const String& scan,
4071 : const String& field,
4072 : const String& intent,
4073 : const String& obsIDs,
4074 : const String& baseline,
4075 : const String& uvrange,
4076 : const String& chanmode,
4077 : const Int& nchan,
4078 : const Int& start,
4079 : const Int& step,
4080 : const MRadialVelocity& mStart,
4081 : const MRadialVelocity& mStep,
4082 : const String& msSelect)
4083 : {
4084 : // Define primary measurement set selection criteria
4085 : // Inputs:
4086 : // time
4087 : // spw
4088 : // scan
4089 : // field
4090 : // intent
4091 : // obsIDs
4092 : // baseline
4093 : // uvrange
4094 : // chanmode const String& Frequency/velocity selection mode
4095 : // ("channel", "velocity" or
4096 : // "opticalvelocity")
4097 : // nchan const Int& No of channels to select
4098 : // start const Int& Start channel to select
4099 : // step const Int& Channel increment
4100 : // mStart const MRadialVelocity& Start radial vel. to select
4101 : // mStep const MRadialVelocity& Radial velocity increment
4102 : // msSelect const String& MS selection string (TAQL)
4103 : // Output to private data:
4104 : //
4105 168 : logSink() << LogOrigin("Calibrater","selectvis") << LogIO::NORMAL3;
4106 :
4107 : try {
4108 :
4109 : /*
4110 : cout << "time = " << time << " " << time.length() <<endl;
4111 : cout << "spw = " << spw << " " << spw.length() <<endl;
4112 : cout << "scan = " << scan << " " << scan.length() <<endl;
4113 : cout << "field = " << field << " " << field.length() <<endl;
4114 : cout << "baseline = " << baseline << " " << baseline.length() << endl;
4115 : cout << "uvrange = " << uvrange << " " << uvrange.length() << endl;
4116 : */
4117 :
4118 168 : logSink() << "Selecting data" << LogIO::POST;
4119 :
4120 : // Apply selection to the original MeasurementSet
4121 168 : logSink() << "Performing selection on MeasurementSet" << endl;
4122 :
4123 168 : if (mssel_p) {
4124 168 : delete mssel_p;
4125 168 : mssel_p=0;
4126 : };
4127 :
4128 : // Report non-trivial user selections
4129 168 : if (time!="")
4130 2 : logSink() << " Selecting on time: '" << time << "'" << endl;
4131 168 : if (spw!="")
4132 21 : logSink() << " Selecting on spw: '" << spw << "'" << endl;
4133 168 : if (scan!="")
4134 2 : logSink() << " Selecting on scan: '" << scan << "'" << endl;
4135 168 : if (field!="")
4136 20 : logSink() << " Selecting on field: '" << field << "'" << endl;
4137 168 : if (intent!="")
4138 20 : logSink() << " Selecting on intent: '" << intent << "'" << endl;
4139 168 : if(obsIDs != "")
4140 0 : logSink() << " Selecting by observation IDs: '" << obsIDs << "'" << endl;
4141 168 : if (baseline!="")
4142 3 : logSink() << " Selecting on antenna/baseline: '" << baseline << "'" << endl;
4143 168 : if (uvrange!="")
4144 2 : logSink() << " Selecting on uvrange: '" << uvrange << "'" << endl;
4145 168 : if (msSelect!="")
4146 1 : logSink() << " Selecting with TaQL: '" << msSelect << "'" << endl;
4147 168 : logSink() << LogIO::POST;
4148 :
4149 :
4150 : // Assume no selection, for starters
4151 : // gmoellen 2012/01/30 mssel_p = new MeasurementSet(sorted, ms_p);
4152 168 : mssel_p = new MeasurementSet(*ms_p);
4153 :
4154 : // Apply user-supplied selection
4155 168 : Bool nontrivsel=false;
4156 : // gmoellen 2012/01/30 nontrivsel= mssSetData(MeasurementSet(sorted, ms_p),
4157 :
4158 : // Ensure use of a fresh MSSelection object
4159 168 : if (mss_p) { delete mss_p; mss_p=NULL; }
4160 168 : mss_p=new MSSelection();
4161 345 : nontrivsel= mssSetData(*ms_p,
4162 168 : *mssel_p,"",
4163 : time,baseline,
4164 : field,spw,
4165 : uvrange,msSelect,
4166 : "",scan,"",intent, obsIDs,mss_p);
4167 :
4168 : // Keep any MR status for the MS
4169 165 : mssel_p->setMemoryResidentSubtables(ms_p->getMrsEligibility());
4170 :
4171 : // If non-trivial MSSelection invoked and nrow reduced:
4172 165 : if(nontrivsel && mssel_p->nrow()<ms_p->nrow()) {
4173 :
4174 : // Escape if no rows selected
4175 46 : if (mssel_p->nrow()==0)
4176 0 : throw(AipsError("Specified selection selects zero rows!"));
4177 :
4178 : // ...otherwise report how many rows are selected
4179 46 : logSink() << "By selection " << ms_p->nrow()
4180 46 : << " rows are reduced to " << mssel_p->nrow()
4181 46 : << LogIO::POST;
4182 : }
4183 : else {
4184 : // Selection did nothing:
4185 119 : logSink() << "Selection did not drop any rows" << LogIO::POST;
4186 : }
4187 :
4188 : // Now, re-create the associated VisSet
4189 165 : if(vs_p) delete vs_p; vs_p=0;
4190 165 : Block<int> sort(0);
4191 165 : Matrix<Int> noselection;
4192 : // gmoellen 2012/01/30 vs_p = new VisSet(*mssel_p,sort,noselection);
4193 165 : vs_p = new VisSet(*mssel_p,sort,noselection,false,0.0,false,false);
4194 165 : AlwaysAssert(vs_p, AipsError);
4195 :
4196 : // Attempt to use MSSelection for channel selection
4197 : // if user not using the old way
4198 165 : if (chanmode=="none") {
4199 165 : selectChannel(spw);
4200 : }
4201 : else {
4202 : // Reluctantly use the old-fashioned way
4203 : logSink() << LogIO::WARN
4204 : << "You have used the old-fashioned mode parameter" << endl
4205 : << "for channel selection. It still works, for now," << endl
4206 : << "but this will be eliminated in the near future." << endl
4207 : << "Please begin using the new channel selection" << endl
4208 0 : << "syntax in the spw parameter." << LogIO::POST;
4209 0 : selectChannel(chanmode,nchan,start,step,mStart,mStep);
4210 : }
4211 :
4212 165 : }
4213 3 : catch (MSSelectionError& x) {
4214 : // Re-initialize with the existing MS
4215 6 : logSink() << LogOrigin("Calibrater","selectvis",WHERE)
4216 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4217 6 : << LogIO::POST;
4218 : // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty
4219 3 : initialize(*ms_p,false,false,false);
4220 3 : throw(AipsError("Error in data selection specification: " + x.getMesg()));
4221 3 : }
4222 0 : catch (AipsError x) {
4223 : // Re-initialize with the existing MS
4224 0 : logSink() << LogOrigin("Calibrater","selectvis",WHERE)
4225 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4226 0 : << LogIO::POST;
4227 : // jagonzal (CAS-4110): I guess it is not necessary to create these columns when the selection is empty.
4228 0 : initialize(*ms_p,false,false,false);
4229 0 : throw(AipsError("Error in Calibrater::selectvis(): " + x.getMesg()));
4230 0 : }
4231 165 : };
4232 :
4233 :
4234 37 : Bool OldCalibrater::setapply (const String& type,
4235 : const Record& applypar)
4236 : {
4237 37 : logSink() << LogOrigin("Calibrater", "setapply(type, applypar)");
4238 :
4239 : // First try to create the requested VisCal object
4240 37 : VisCal *vc(NULL);
4241 :
4242 : try {
4243 :
4244 37 : if(!ok())
4245 0 : throw(AipsError("Calibrater not prepared for setapply."));
4246 :
4247 37 : String upType=type;
4248 37 : upType.upcase();
4249 :
4250 : logSink() << LogIO::NORMAL
4251 : << "Arranging to APPLY:"
4252 37 : << LogIO::POST;
4253 :
4254 : // Add a new VisCal to the apply list
4255 37 : vc = createVisCal(upType,*vs_p);
4256 :
4257 37 : vc->setApply(applypar);
4258 :
4259 : logSink() << LogIO::NORMAL << ". "
4260 36 : << vc->applyinfo()
4261 36 : << LogIO::POST;
4262 :
4263 38 : } catch (AipsError x) {
4264 : logSink() << LogIO::SEVERE << x.getMesg()
4265 : << " Check inputs and try again."
4266 1 : << LogIO::POST;
4267 1 : if (vc) delete vc;
4268 1 : throw(AipsError("Error in Calibrater::setapply."));
4269 : return false;
4270 2 : }
4271 :
4272 : // Creation apparently successful, so add to the apply list
4273 : // TBD: consolidate with above?
4274 : try {
4275 :
4276 36 : uInt napp=vc_p.nelements();
4277 36 : vc_p.resize(napp+1,false,true);
4278 36 : vc_p[napp] = vc;
4279 36 : vc=NULL;
4280 :
4281 : // Maintain sort of apply list
4282 36 : ve_p->setapply(vc_p);
4283 :
4284 36 : return true;
4285 :
4286 0 : } catch (AipsError x) {
4287 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4288 0 : << LogIO::POST;
4289 0 : if (vc) delete vc;
4290 0 : throw(AipsError("Error in Calibrater::setapply."));
4291 : return false;
4292 0 : }
4293 : return false;
4294 : }
4295 :
4296 : // Set up apply-able calibration via a Cal Library
4297 0 : Bool OldCalibrater::setcallib(Record callib) {
4298 :
4299 0 : logSink() << LogOrigin("Calibrater", "setcallib(callib)");
4300 :
4301 : // cout << "Calibrater::setcallib: callib.isFixed() = " << boolalpha << callib.isFixed() << endl;
4302 :
4303 0 : uInt ntab=callib.nfields();
4304 :
4305 : // cout << "callib.nfields() = " << ntab << endl;
4306 :
4307 : // Do some preliminary per-table verification
4308 0 : for (uInt itab=0;itab<ntab;++itab) {
4309 :
4310 0 : String tabname=callib.name(itab);
4311 :
4312 : // Insist that the table exists on disk
4313 0 : if (!Table::isReadable(tabname))
4314 0 : throw(AipsError("Caltable "+tabname+" does not exist."));
4315 :
4316 0 : }
4317 :
4318 : // Tables exist, so deploy them...
4319 :
4320 0 : for (uInt itab=0;itab<ntab;++itab) {
4321 :
4322 0 : String tabname=callib.name(itab);
4323 :
4324 : // Get the type from the table
4325 0 : String upType=calTableType(tabname);
4326 0 : upType.upcase();
4327 :
4328 : // Add table name to the record
4329 0 : Record thistabrec=callib.asrwRecord(itab);
4330 0 : thistabrec.define("tablename",tabname);
4331 :
4332 : // First try to create the requested VisCal object
4333 0 : VisCal *vc(NULL);
4334 :
4335 : try {
4336 :
4337 0 : if(!ok())
4338 0 : throw(AipsError("Calibrater not prepared for setapply."));
4339 :
4340 : logSink() << LogIO::NORMAL
4341 : << "Arranging to APPLY:"
4342 0 : << LogIO::POST;
4343 :
4344 : // Add a new VisCal to the apply list
4345 0 : vc = createVisCal(upType,*vs_p);
4346 :
4347 :
4348 : // ingest this table according to its callib
4349 0 : vc->setCallib(thistabrec,*mssel_p);
4350 :
4351 0 : } catch (AipsError x) {
4352 : logSink() << LogIO::SEVERE << x.getMesg()
4353 : << " Check inputs and try again."
4354 0 : << LogIO::POST;
4355 0 : if (vc) delete vc;
4356 0 : throw(AipsError("Error in Calibrater::setapply."));
4357 : return false;
4358 0 : }
4359 :
4360 : // Creation apparently successful, so add to the apply list
4361 : // TBD: consolidate with above?
4362 : try {
4363 :
4364 0 : uInt napp=vc_p.nelements();
4365 0 : vc_p.resize(napp+1,false,true);
4366 0 : vc_p[napp] = vc;
4367 0 : vc=NULL;
4368 :
4369 : // Maintain sort of apply list
4370 0 : ve_p->setapply(vc_p);
4371 :
4372 0 : } catch (AipsError x) {
4373 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4374 0 : << LogIO::POST;
4375 0 : if (vc) delete vc;
4376 0 : throw(AipsError("Error in Calibrater::setapply."));
4377 : return false;
4378 0 : }
4379 0 : }
4380 :
4381 : // All ok, if we get this far!
4382 0 : return true;
4383 :
4384 : }
4385 :
4386 :
4387 : // Set up apply-able calibration via a Cal Library
4388 9 : Bool OldCalibrater::setcallib2(Record callib, const casacore::MeasurementSet* ms) {
4389 :
4390 9 : logSink() << LogOrigin("OldCalibrater", "setcallib2(callib)");
4391 :
4392 : // cout << "Calibrater::setcallib2(callib) : " << boolalpha << callib << endl;
4393 :
4394 9 : uInt ntab=callib.nfields();
4395 :
4396 : // cout << "callib.nfields() = " << ntab << endl;
4397 :
4398 : // Do some preliminary per-table verification
4399 36 : for (uInt itab=0;itab<ntab;++itab) {
4400 :
4401 27 : String tabname=callib.name(itab);
4402 :
4403 : // Trap parang
4404 : // TBD...
4405 : // if (tabname=="<parang>")
4406 : // continue;
4407 :
4408 : // Insist that the table exists on disk
4409 27 : if (!Table::isReadable(tabname))
4410 0 : throw(AipsError("Caltable "+tabname+" does not exist."));
4411 :
4412 27 : }
4413 :
4414 : // Tables exist, so deploy them...
4415 :
4416 : // Local MS object for callib parsing (only)
4417 : // MeasurementSet lms(msname_p,Table::Update);
4418 : //cout << "OLD lms" << endl;
4419 :
4420 :
4421 : // Local const MS object for callib parsing (only)
4422 9 : const MeasurementSet *lmsp(0);
4423 9 : if (ms) {
4424 : // Use supplied MS (from outside), if specified...
4425 : // TBD: should we verify same base MS as ms_p/mssel_p?
4426 9 : lmsp=ms;
4427 : }
4428 : else {
4429 : // ...use internal one instead
4430 0 : lmsp=mssel_p;
4431 : }
4432 : // Reference for use below
4433 9 : const MeasurementSet &lms(*lmsp);
4434 :
4435 : // Get some global shape info:
4436 9 : Int MSnAnt = lms.antenna().nrow();
4437 9 : Int MSnSpw = lms.spectralWindow().nrow();
4438 :
4439 36 : for (uInt itab=0;itab<ntab;++itab) {
4440 :
4441 27 : String tabname=callib.name(itab);
4442 :
4443 : // Get the type from the table
4444 27 : String upType=calTableType(tabname);
4445 27 : upType.upcase();
4446 :
4447 : // Add table name to the record
4448 27 : Record thistabrec=callib.asrwRecord(itab);
4449 27 : thistabrec.define("tablename",tabname);
4450 :
4451 : // First try to create the requested VisCal object
4452 27 : VisCal *vc(NULL);
4453 :
4454 : try {
4455 :
4456 : // if(!ok())
4457 : // throw(AipsError("Calibrater not prepared for setapply."));
4458 :
4459 : logSink() << LogIO::NORMAL
4460 : << "Arranging to APPLY:"
4461 27 : << LogIO::POST;
4462 :
4463 : // Add a new VisCal to the apply list
4464 27 : vc = createVisCal(upType,msname_p,MSnAnt,MSnSpw);
4465 :
4466 : // ingest this table according to its callib
4467 27 : vc->setCallib(thistabrec,lms);
4468 :
4469 0 : } catch (AipsError x) {
4470 : logSink() << LogIO::SEVERE << x.getMesg()
4471 : << " Check inputs and try again."
4472 0 : << LogIO::POST;
4473 0 : if (vc) delete vc;
4474 0 : throw(AipsError("Error in Calibrater::callib2."));
4475 : return false;
4476 0 : }
4477 :
4478 : // Creation apparently successful, so add to the apply list
4479 : // TBD: consolidate with above?
4480 : try {
4481 :
4482 27 : uInt napp=vc_p.nelements();
4483 27 : vc_p.resize(napp+1,false,true);
4484 27 : vc_p[napp] = vc;
4485 27 : vc=NULL;
4486 :
4487 : // Maintain sort of apply list
4488 27 : ve_p->setapply(vc_p);
4489 :
4490 0 : } catch (AipsError x) {
4491 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4492 0 : << LogIO::POST;
4493 0 : if (vc) delete vc;
4494 0 : throw(AipsError("Error in Calibrater::setapply."));
4495 : return false;
4496 0 : }
4497 27 : }
4498 : // All ok, if we get this far!
4499 9 : return true;
4500 :
4501 : }
4502 :
4503 :
4504 39 : Bool OldCalibrater::setsolve (const String& type,
4505 : const Record& solvepar) {
4506 :
4507 : // Attempt to create the solvable object
4508 39 : SolvableVisCal *svc(NULL);
4509 : try {
4510 :
4511 39 : if(!ok())
4512 0 : throw(AipsError("Calibrater not prepared for setsolve."));
4513 :
4514 39 : String upType = type;
4515 39 : upType.upcase();
4516 :
4517 : // Clean out any old solve that was lying around
4518 39 : unsetsolve();
4519 :
4520 : logSink() << LogIO::NORMAL
4521 : << "Arranging to SOLVE:"
4522 39 : << LogIO::POST;
4523 :
4524 : // Create the new SolvableVisCal
4525 39 : svc = createSolvableVisCal(upType,*vs_p);
4526 39 : svc->setSolve(solvepar);
4527 :
4528 : logSink() << LogIO::NORMAL << ". "
4529 39 : << svc->solveinfo()
4530 39 : << LogIO::POST;
4531 :
4532 : // Creation apparently successful, keep it
4533 39 : svc_p=svc;
4534 39 : svc=NULL;
4535 :
4536 39 : return true;
4537 :
4538 39 : } catch (AipsError x) {
4539 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4540 0 : << LogIO::POST;
4541 0 : unsetsolve();
4542 0 : if (svc) delete svc;
4543 0 : throw(AipsError("Error in Calibrater::setsolve."));
4544 : return false;
4545 0 : }
4546 : return false;
4547 : }
4548 :
4549 0 : Bool OldCalibrater::correct(String mode)
4550 : {
4551 0 : logSink() << LogOrigin("Calibrater","correct") << LogIO::NORMAL;
4552 :
4553 0 : Bool retval = true;
4554 :
4555 : try {
4556 :
4557 : // make mode all-caps
4558 0 : String upmode=mode;
4559 0 : upmode.upcase();
4560 :
4561 : // If trialmode=T, only the flags will be set
4562 : // (and only written if not TRIAL)
4563 0 : Bool trialmode=(upmode.contains("TRIAL") ||
4564 0 : upmode.contains("FLAGONLY"));
4565 :
4566 : // Set up VisSet and its VisibilityIterator.
4567 :
4568 0 : VisibilityIterator::DataColumn whichOutCol = configureForCorrection ();
4569 :
4570 0 : VisIter& vi(vs_p->iter());
4571 0 : VisBufferAutoPtr vb (vi);
4572 0 : vi.origin();
4573 :
4574 : // Pass each timestamp (VisBuffer) to VisEquation for correction
4575 :
4576 0 : Vector<Bool> uncalspw(vi.numberSpw()); // Used to accumulate error messages
4577 0 : uncalspw.set(false); // instead of bombing the user
4578 0 : uncalspw.set(False); // instead of bombing the user
4579 : // in a loop.
4580 :
4581 0 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
4582 :
4583 0 : for (vi.origin(); vi.more(); vi++) {
4584 :
4585 0 : uInt spw = vb->spectralWindow();
4586 :
4587 : // Re-initialize weights from sigma column
4588 0 : vb->resetWeightMat();
4589 :
4590 : // If we can calibrate this vb, do it...
4591 0 : if (ve_p->spwOK(spw)){
4592 :
4593 : // throws exception if nothing to apply
4594 0 : ve_p->correct(*vb,trialmode);
4595 :
4596 : }
4597 : // ...else don't, prepare warning, and possibly set flags
4598 : else{
4599 :
4600 : // set uncalspw for warning message
4601 0 : uncalspw[spw] = true;
4602 : // set the flags, if we are being strict
4603 0 : if (upmode.contains("STRICT"))
4604 : // set the flags
4605 : // (don't touch the data/weights, which are initialized)
4606 0 : vb->flag().set(true);
4607 : }
4608 :
4609 : // Only if not a trial run, trigger write to disk
4610 0 : if (!upmode.contains("TRIAL")) {
4611 :
4612 0 : if (upmode.contains("CAL")) {
4613 0 : vi.setVis (vb->visCube(), whichOutCol);
4614 0 : vi.setWeightMat(vb->weightMat());
4615 : }
4616 :
4617 0 : if (upmode.contains("FLAG"))
4618 0 : vi.setFlag (vb->flag());
4619 :
4620 : }
4621 :
4622 : }
4623 : }
4624 :
4625 0 : vs_p->flush (); // Flush to disk
4626 :
4627 : // Now that we're out of the loop, summarize any errors.
4628 :
4629 0 : retval = summarize_uncalspws(uncalspw, "correct",
4630 0 : upmode.contains("STRICT"));
4631 :
4632 0 : actRec_=Record();
4633 0 : actRec_.define("origin","Calibrater::correct");
4634 0 : actRec_.defineRecord("VisEquation",ve_p->actionRec());
4635 :
4636 0 : }
4637 0 : catch (AipsError x) {
4638 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4639 0 : << LogIO::POST;
4640 :
4641 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
4642 0 : unsetapply();
4643 :
4644 0 : throw(AipsError("Error in Calibrater::correct."));
4645 : retval = false; // Not that it ever gets here...
4646 0 : }
4647 0 : return retval;
4648 : }
4649 :
4650 4 : Bool OldCalibrater::corrupt() {
4651 :
4652 4 : logSink() << LogOrigin("Calibrater","corrupt") << LogIO::NORMAL;
4653 4 : Bool retval = true;
4654 :
4655 : try {
4656 :
4657 4 : if (!ok())
4658 0 : throw(AipsError("Calibrater not prepared for corrupt!"));
4659 :
4660 : // Nominally, we write out to the MODEL_DATA, unless absent
4661 4 : VisibilityIterator::DataColumn whichOutCol(VisibilityIterator::Model);
4662 :
4663 4 : if (!ms_p->tableDesc().isColumn("MODEL_DATA"))
4664 0 : throw(AipsError("MODEL_DATA column unexpectedly absent. Cannot corrupt."));
4665 :
4666 : // Ensure apply list non-zero and properly sorted
4667 4 : ve_p->setapply(vc_p);
4668 :
4669 : // Report the types that will be applied
4670 4 : applystate();
4671 :
4672 : // Arrange for iteration over data
4673 4 : Block<Int> columns;
4674 : // include scan iteration
4675 4 : columns.resize(5);
4676 4 : columns[0]=MS::ARRAY_ID;
4677 4 : columns[1]=MS::SCAN_NUMBER;
4678 4 : columns[2]=MS::FIELD_ID;
4679 4 : columns[3]=MS::DATA_DESC_ID;
4680 4 : columns[4]=MS::TIME;
4681 4 : vs_p->resetVisIter(columns,0.0);
4682 4 : VisIter& vi(vs_p->iter());
4683 4 : VisBuffer vb(vi);
4684 :
4685 : // Pass each timestamp (VisBuffer) to VisEquation for corruption.
4686 4 : Vector<Bool> uncalspw(vi.numberSpw()); // Used to accumulate error messages
4687 4 : uncalspw.set(false); // instead of bombing the user
4688 : // in a loop.
4689 12 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
4690 8 : Int spw = vi.spectralWindow();
4691 :
4692 : // Only proceed if spw can be calibrated
4693 8 : if (ve_p->spwOK(spw)) {
4694 :
4695 144 : for (vi.origin(); vi.more(); vi++) {
4696 :
4697 : // Corrupt the MODEL_DATA
4698 : // (note we are not treating weights and flags)
4699 136 : ve_p->corrupt(vb); // throws exception if nothing to apply
4700 136 : vi.setVis(vb.modelVisCube(),whichOutCol);
4701 :
4702 : }
4703 : }
4704 : else
4705 0 : uncalspw[spw] = true;
4706 : }
4707 : // Flush to disk
4708 4 : vs_p->flush();
4709 :
4710 : // Now that we're out of the loop, summarize any errors.
4711 4 : retval = summarize_uncalspws(uncalspw, "corrupt");
4712 4 : }
4713 0 : catch (AipsError x) {
4714 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
4715 0 : << LogIO::POST;
4716 :
4717 0 : logSink() << "Resetting all calibration application settings." << LogIO::POST;
4718 0 : unsetapply();
4719 :
4720 0 : throw(AipsError("Error in Calibrater::corrupt."));
4721 : retval = false; // Not that it ever gets here...
4722 0 : }
4723 4 : return retval;
4724 : }
4725 :
4726 0 : Bool OldCalibrater::initWeightsWithTsys(String wtmode, Bool dowtsp,
4727 : String tsystable, String gainfield, String interp, Vector<Int> spwmap) {
4728 :
4729 0 : logSink() << LogOrigin("Calibrater", "initWeightsWithTsys")
4730 0 : << LogIO::NORMAL;
4731 0 : Bool retval = true;
4732 :
4733 : try {
4734 :
4735 0 : if (!ok())
4736 0 : throw(AipsError("Calibrater not prepared for initWeights!"));
4737 :
4738 0 : String uptype = calTableType(tsystable);
4739 0 : if (!uptype.contains("TSYS")) {
4740 0 : throw(AipsError(
4741 0 : "Invalid calibration table type for Tsys weighting."));
4742 : }
4743 : // Set record format for calibration table application information
4744 0 : RecordDesc applyparDesc;
4745 0 : applyparDesc.addField("t", TpDouble);
4746 0 : applyparDesc.addField("table", TpString);
4747 0 : applyparDesc.addField("interp", TpString);
4748 0 : applyparDesc.addField("spw", TpArrayInt);
4749 0 : applyparDesc.addField("fieldstr", TpString);
4750 0 : applyparDesc.addField("calwt", TpBool);
4751 0 : applyparDesc.addField("spwmap", TpArrayInt);
4752 0 : applyparDesc.addField("opacity", TpArrayDouble);
4753 :
4754 : // Create record with the requisite field values
4755 0 : Record applypar(applyparDesc);
4756 0 : applypar.define("t", 0.0);
4757 0 : applypar.define("table", tsystable);
4758 0 : applypar.define("interp", interp);
4759 0 : applypar.define("spw", getSpwIdx(""));
4760 0 : applypar.define("fieldstr", gainfield);
4761 0 : applypar.define("calwt", true);
4762 0 : applypar.define("spwmap", spwmap);
4763 0 : applypar.define("opacity", Vector<Double>(1, 0.0));
4764 :
4765 0 : if (vc_p.nelements() > 0) {
4766 0 : logSink() << LogIO::WARN << "Resetting all calibration application settings." << LogIO::POST;
4767 0 : unsetapply();
4768 : }
4769 0 : logSink() << LogIO::NORMAL << "Weight initialization does not support selection. Resetting MS selection." << LogIO::POST;
4770 0 : selectvis();
4771 0 : StandardTsys vc = StandardTsys(*vs_p);
4772 0 : vc.setApply(applypar);
4773 :
4774 0 : logSink() << LogIO::NORMAL << ". " << vc.applyinfo() << LogIO::POST;
4775 0 : PtrBlock<VisCal*> vcb(1, &vc);
4776 : // Maintain sort of apply list
4777 0 : ve_p->setapply(vcb);
4778 :
4779 : // Detect WEIGHT_SPECTRUM and SIGMA_SPECTRUM
4780 0 : TableDesc mstd = ms_p->actualTableDesc();
4781 0 : String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
4782 0 : Bool wtspexists = mstd.isColumn(colWtSp);
4783 0 : String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
4784 0 : Bool sigspexists = mstd.isColumn(colSigSp);
4785 0 : Bool addsigsp = (dowtsp && !sigspexists);
4786 :
4787 : // Some log info
4788 0 : bool use_exposure = false;
4789 0 : if (wtmode == "tsys") {
4790 : logSink()
4791 : << "Initializing SIGMA and WEIGHT according to channel bandwidth and Tsys. NOTE this is an expert mode."
4792 0 : << LogIO::WARN << LogIO::POST;
4793 0 : } else if (wtmode == "tinttsys") {
4794 : logSink()
4795 : << "Initializing SIGMA and WEIGHT according to channel bandwidth, integration time, and Tsys. NOTE this is an expert mode."
4796 0 : << LogIO::WARN << LogIO::POST;
4797 0 : use_exposure = true;
4798 : } else {
4799 0 : throw(AipsError("Unrecognized wtmode specified: " + wtmode));
4800 : }
4801 :
4802 : // Force dowtsp if the column already exists
4803 0 : if (wtspexists && !dowtsp) {
4804 : logSink() << "Found WEIGHT_SPECTRUM; will force its initialization."
4805 0 : << LogIO::POST;
4806 0 : dowtsp = true;
4807 : }
4808 :
4809 : // Report that we are initializing the WEIGHT_SPECTRUM, and prepare to do so.
4810 0 : if (dowtsp) {
4811 :
4812 : // Ensure WEIGHT_SPECTRUM really exists at all
4813 : // (often it exists but is empty)
4814 0 : if (!wtspexists) {
4815 0 : logSink() << "Creating WEIGHT_SPECTRUM." << LogIO::POST;
4816 :
4817 : // Nominal defaulttileshape
4818 0 : IPosition dts(3, 4, 32, 1024);
4819 :
4820 : // Discern DATA's default tile shape and use it
4821 0 : const Record dminfo = ms_p->dataManagerInfo();
4822 0 : for (uInt i = 0; i < dminfo.nfields(); ++i) {
4823 0 : Record col = dminfo.asRecord(i);
4824 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
4825 0 : if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
4826 0 : dts = IPosition(
4827 0 : col.asRecord("SPEC").asArrayInt(
4828 0 : "DEFAULTTILESHAPE"));
4829 : //cout << "Found DATA's default tile: " << dts << endl;
4830 0 : break;
4831 : }
4832 0 : }
4833 :
4834 : // Add the column
4835 0 : String colWtSp = MS::columnName(MS::WEIGHT_SPECTRUM);
4836 0 : TableDesc tdWtSp;
4837 0 : tdWtSp.addColumn(
4838 0 : ArrayColumnDesc<Float>(colWtSp, "weight spectrum", 2));
4839 0 : TiledShapeStMan wtSpStMan("TiledWgtSpectrum", dts);
4840 0 : ms_p->addColumn(tdWtSp, wtSpStMan);
4841 0 : } else
4842 0 : logSink() << "Found WEIGHT_SPECTRUM." << LogIO::POST;
4843 : // Ensure WEIGHT_SPECTRUM really exists at all
4844 : // (often it exists but is empty)
4845 0 : if (!sigspexists) {
4846 0 : logSink() << "Creating SIGMA_SPECTRUM." << LogIO::POST;
4847 :
4848 : // Nominal defaulttileshape
4849 0 : IPosition dts(3, 4, 32, 1024);
4850 :
4851 : // Discern DATA's default tile shape and use it
4852 0 : const Record dminfo = ms_p->dataManagerInfo();
4853 0 : for (uInt i = 0; i < dminfo.nfields(); ++i) {
4854 0 : Record col = dminfo.asRecord(i);
4855 : //if (upcase(col.asString("NAME"))=="TILEDDATA") {
4856 0 : if (anyEQ(col.asArrayString("COLUMNS"), String("DATA"))) {
4857 0 : dts = IPosition(
4858 0 : col.asRecord("SPEC").asArrayInt(
4859 0 : "DEFAULTTILESHAPE"));
4860 : //cout << "Found DATA's default tile: " << dts << endl;
4861 0 : break;
4862 : }
4863 0 : }
4864 :
4865 : // Add the column
4866 0 : String colSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
4867 0 : TableDesc tdSigSp;
4868 0 : tdSigSp.addColumn(
4869 0 : ArrayColumnDesc<Float>(colSigSp, "sigma spectrum", 2));
4870 0 : TiledShapeStMan sigSpStMan("TiledSigtSpectrum", dts);
4871 0 : ms_p->addColumn(tdSigSp, sigSpStMan);
4872 : {
4873 0 : TableDesc loctd = ms_p->actualTableDesc();
4874 0 : String loccolSigSp = MS::columnName(MS::SIGMA_SPECTRUM);
4875 0 : AlwaysAssert(loctd.isColumn(loccolSigSp),AipsError);
4876 0 : }
4877 0 : }
4878 : }
4879 : else {
4880 0 : if (sigspexists) {
4881 0 : logSink() << "Removing SIGMA_SPECTRUM for non-channelized weight." << LogIO::POST;
4882 : if (true || ms_p->canRemoveColumn(colSigSp)) {
4883 0 : ms_p->removeColumn(colSigSp);
4884 : }
4885 : else
4886 : logSink() << LogIO::WARN << "Failed to remove SIGMA_SPECTRUM column. Values in SIGMA and SIGMA_SPECTRUM columns may be inconsistent after the operation." << LogIO::POST;
4887 : }
4888 : }
4889 :
4890 : // Arrange for iteration over data
4891 : // TBD: Be sure this sort is optimal for creating WS?
4892 0 : Block<Int> columns;
4893 : // include scan iteration
4894 0 : columns.resize(5);
4895 0 : columns[0] = MS::ARRAY_ID;
4896 0 : columns[1] = MS::SCAN_NUMBER;
4897 0 : columns[2] = MS::FIELD_ID;
4898 0 : columns[3] = MS::DATA_DESC_ID;
4899 0 : columns[4] = MS::TIME;
4900 :
4901 0 : vi::SortColumns sc(columns);
4902 0 : vi::VisibilityIterator2 vi2(*ms_p, sc, true);
4903 0 : vi::VisBuffer2 *vb = vi2.getVisBuffer();
4904 :
4905 0 : MSColumns mscol(*ms_p);
4906 0 : const MSSpWindowColumns& msspw(mscol.spectralWindow());
4907 0 : uInt nSpw = msspw.nrow();
4908 0 : Vector<Double> effChBw(nSpw, 0.0);
4909 0 : for (uInt ispw = 0; ispw < nSpw; ++ispw) {
4910 0 : effChBw[ispw] = mean(msspw.effectiveBW()(ispw));
4911 : }
4912 :
4913 0 : Int ivb(0);
4914 0 : for (vi2.originChunks(); vi2.moreChunks(); vi2.nextChunk()) {
4915 :
4916 0 : for (vi2.origin(); vi2.more(); vi2.next(), ++ivb) {
4917 :
4918 0 : Int spw = vb->spectralWindows()(0);
4919 :
4920 0 : auto nrow = vb->nRows();
4921 0 : Int nchan = vb->nChannels();
4922 0 : Int ncor = vb->nCorrelations();
4923 :
4924 : // Prepare for WEIGHT_SPECTRUM and SIGMA_SPECTRUM, if nec.
4925 0 : Cube<Float> newwtsp(0, 0, 0), newsigsp(0, 0, 0);
4926 0 : if (dowtsp) {
4927 0 : newwtsp.resize(ncor, nchan, nrow);
4928 0 : newwtsp.set(1.0);
4929 0 : newsigsp.resize(ncor, nchan, nrow);
4930 0 : newsigsp.set(1.0);
4931 : }
4932 :
4933 0 : if (ve_p->spwOK(spw)) {
4934 :
4935 : // Re-initialize weight info from sigma info
4936 : // This is smart wrt spectral weights, etc.
4937 : // (this makes W and WS, if present, "dirty" in the vb)
4938 : // TBD: only do this if !trial (else: avoid the I/O)
4939 : // vb->resetWeightsUsingSigma();
4940 : // Handle non-trivial modes
4941 : // Init WEIGHT, SIGMA from bandwidth & time
4942 0 : Matrix<Float> newwt(ncor, nrow), newsig(ncor, nrow);
4943 0 : newwt.set(1.0);
4944 0 : newsig.set(1.0);
4945 :
4946 : // Detect ACs
4947 0 : const Vector<Int> a1(vb->antenna1());
4948 0 : const Vector<Int> a2(vb->antenna2());
4949 0 : Vector<Bool> ac(a1 == a2);
4950 :
4951 : // XCs need an extra factor of 2
4952 0 : Vector<Float> xcfactor(nrow, 2.0);
4953 0 : xcfactor(ac) = 1.0; // (but not ACs)
4954 :
4955 : // The row-wise integration time
4956 0 : Vector<Float> expo(nrow);
4957 0 : convertArray(expo, vb->exposure());
4958 :
4959 : // Set weights to channel bandwidth first.
4960 0 : newwt.set(Float(effChBw(spw)));
4961 :
4962 : // For each correlation, apply exposure and xcfactor
4963 0 : for (Int icor = 0; icor < ncor; ++icor) {
4964 :
4965 0 : Vector<Float> wt(newwt.row(icor));
4966 0 : if (use_exposure) {
4967 0 : wt *= expo;
4968 : }
4969 0 : wt *= xcfactor;
4970 0 : if (dowtsp) {
4971 0 : for (Int ich = 0; ich < nchan; ++ich) {
4972 : Vector<Float> wtspi(
4973 0 : newwtsp(Slice(icor, 1, 1),
4974 0 : Slice(ich, 1, 1), Slice()).nonDegenerate(
4975 0 : IPosition(1, 2)));
4976 0 : wtspi = wt;
4977 0 : }
4978 : }
4979 0 : }
4980 : // Handle SIGMA_SPECTRUM
4981 0 : if (dowtsp) {
4982 0 : newsigsp = 1.0f / sqrt(newwtsp);
4983 : }
4984 : // sig from wt is inverse sqrt
4985 0 : newsig = 1.0f / sqrt(newwt);
4986 :
4987 : // Arrange write-back of both SIGMA and WEIGHT
4988 0 : vb->setSigma(newsig);
4989 0 : vb->setWeight(newwt);
4990 0 : if (dowtsp) {
4991 0 : vb->initWeightSpectrum(newwtsp);
4992 0 : vb->initSigmaSpectrum(newsigsp);
4993 : }
4994 : // Force writeback to disk (need to initialize weight/sigma before applying cal table)
4995 0 : vb->writeChangesBack();
4996 :
4997 : // Arrange for _in-place_ apply on CORRECTED_DATA (init from DATA)
4998 : // (this makes CD "dirty" in the vb)
4999 : // TBD: only do this if !trial (else: avoid the I/O)
5000 0 : vb->setVisCubeCorrected(vb->visCube());
5001 :
5002 : // Make flagcube dirty in the vb
5003 : // NB: we must _always_ do this I/O (even trial mode)
5004 0 : vb->setFlagCube(vb->flagCube());
5005 :
5006 : // Make all vb "not dirty"; we'll carefully arrange the writeback below
5007 0 : vb->dirtyComponentsClear();
5008 :
5009 : // throws exception if nothing to apply
5010 0 : ve_p->correct2(*vb, false, dowtsp);
5011 :
5012 0 : if (dowtsp) {
5013 0 : vb->setWeightSpectrum(vb->weightSpectrum());
5014 : // If WS was calibrated, set W to its channel-axis median
5015 0 : vb->setWeight( partialMedians(vb->weightSpectrum(), IPosition(1, 1)) );
5016 0 : newsigsp = 1.0f / sqrt(vb->weightSpectrum());
5017 0 : vb->initSigmaSpectrum(newsigsp);
5018 0 : vb->setSigma( partialMedians(newsigsp, IPosition(1, 1)) );
5019 : } else {
5020 0 : vb->setWeight(vb->weight());
5021 0 : newsig = 1.0f / sqrt(vb->weight());
5022 0 : vb->setSigma(newsig);
5023 : }
5024 : // Force writeback to disk
5025 0 : vb->writeChangesBack();
5026 :
5027 0 : } else {//Not calibrating the spw
5028 0 : if (dowtsp && !wtspexists) {
5029 : // newly created WS Need to initialize
5030 0 : vb->initWeightSpectrum(newwtsp);
5031 : }
5032 0 : if (addsigsp) {
5033 : // newly created SS Need to initialize
5034 0 : vb->initSigmaSpectrum(newsigsp);
5035 0 : vb->writeChangesBack();
5036 : }
5037 : }
5038 0 : }
5039 : }
5040 : // clear-up Tsys caltable from list of apply
5041 0 : unsetapply();
5042 :
5043 0 : } catch (AipsError x) {
5044 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg()
5045 0 : << LogIO::POST;
5046 :
5047 : logSink() << "Resetting all calibration application settings."
5048 0 : << LogIO::POST;
5049 0 : unsetapply();
5050 :
5051 0 : throw(AipsError("Error in Calibrater::initWeights."));
5052 : retval = false; // Not that it ever gets here...
5053 0 : }
5054 0 : return retval;
5055 : }
5056 :
5057 39 : Bool OldCalibrater::solve() {
5058 :
5059 39 : logSink() << LogOrigin("Calibrater","solve") << LogIO::NORMAL3;
5060 :
5061 : try {
5062 :
5063 39 : if (!ok())
5064 0 : throw(AipsError("Calibrater not prepared for solve."));
5065 :
5066 : // Handle nothing-to-solve-for case
5067 39 : if (!svc_p)
5068 0 : throw(AipsError("Please run setsolve before attempting to solve."));
5069 :
5070 : // Handle specified caltable
5071 39 : if (true && svc_p) {
5072 :
5073 : /*
5074 : cout << "name: " << svc_p->calTableName() << endl;
5075 : cout << boolalpha;
5076 : cout << "append? " << svc_p->append() << endl;
5077 : cout << "opened? " << Table::isOpened(svc_p->calTableName()) << endl;
5078 : cout << "readable? " << Table::isReadable(svc_p->calTableName()) << endl;
5079 : // cout << "writable? " << Table::isWritable(svc_p->calTableName()) << endl;
5080 : cout << "canDelete? " << Table::canDeleteTable(svc_p->calTableName(),true) << endl;
5081 : */
5082 :
5083 : // If table exists (readable) and not deletable
5084 : // we have to abort (append=T requires deletable)
5085 40 : if ( Table::isReadable(svc_p->calTableName()) &&
5086 1 : !TableUtil::canDeleteTable(svc_p->calTableName()) ) {
5087 0 : throw(AipsError("Specified caltable ("+svc_p->calTableName()+") exists and\n cannot be replaced (or appended to) because it appears to be open somewhere (Quit plotcal?)."));
5088 : }
5089 : }
5090 :
5091 : // Arrange VisEquation for solve
5092 39 : ve_p->setsolve(*svc_p);
5093 :
5094 : // Ensure apply list properly sorted w.r.t. solvable term
5095 39 : ve_p->setapply(vc_p);
5096 :
5097 : // Report what is being applied and solved-for
5098 39 : applystate();
5099 39 : solvestate();
5100 :
5101 :
5102 : // Report correct/corrupt apply order
5103 : // ve_p->state();
5104 :
5105 : // Set the channel mask
5106 39 : svc_p->setChanMask(chanmask_);
5107 :
5108 : // Generally use standard solver
5109 39 : if (svc_p->useGenericGatherForSolve())
5110 2 : genericGatherAndSolve(); // using VisBuffGroupAcc
5111 : else {
5112 : //cout << "Fully self-directed data gather and solve" << endl;
5113 : // Fully self-directed data gather and solve
5114 37 : svc_p->selfGatherAndSolve(*vs_p,*ve_p);
5115 : }
5116 :
5117 36 : svc_p->clearChanMask();
5118 :
5119 3 : } catch (AipsError x) {
5120 3 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
5121 :
5122 3 : logSink() << "Reseting entire solve/apply state." << LogIO::POST;
5123 3 : reset();
5124 :
5125 3 : throw(AipsError("Error in Calibrater::solve."));
5126 : return false;
5127 6 : }
5128 :
5129 36 : return true;
5130 :
5131 : }
5132 :
5133 24 : Vector<Double> OldCalibrater::modelfit(const Int& niter,
5134 : const String& stype,
5135 : const Vector<Double>& par,
5136 : const Vector<Bool>& vary,
5137 : const String& file) {
5138 :
5139 : /*
5140 : cout << "Calibrater::modelfit" << endl;
5141 : cout << " niter = " << niter << endl;
5142 : cout << " stype = " << stype << endl;
5143 : cout << " par = " << par << endl;
5144 : cout << " vary = " << vary << endl;
5145 : cout << " file = " << file << endl;
5146 : */
5147 : // logSink() << LogOrigin("Calibrater","modelfit") << LogIO::NORMAL;
5148 :
5149 : try {
5150 24 : if(!ok()) throw(AipsError("Calibrater not ok()"));
5151 :
5152 : // Construct UVMod with the VisSet
5153 24 : UVMod uvmod(*vs_p);
5154 :
5155 24 : if (stype=="P")
5156 22 : uvmod.setModel(ComponentType::POINT, par, vary);
5157 2 : else if (stype=="G")
5158 1 : uvmod.setModel(ComponentType::GAUSSIAN, par, vary);
5159 1 : else if (stype=="D")
5160 1 : uvmod.setModel(ComponentType::DISK, par, vary);
5161 : else
5162 0 : throw(AipsError("Unrecognized component type in Calibrater::modelfit."));
5163 :
5164 : // Run the fit
5165 24 : uvmod.modelfit(niter,file);
5166 :
5167 : // Return the parameter vector
5168 24 : return uvmod.par();
5169 :
5170 24 : } catch (AipsError x) {
5171 0 : logSink() << LogIO::SEVERE << "Caught exception: " << x.getMesg() << LogIO::POST;
5172 0 : throw(AipsError("Error in Calibrater::modelfit."));
5173 :
5174 : return Vector<Double>();
5175 0 : }
5176 :
5177 : }
5178 :
5179 0 : void OldCalibrater::fluxscale(const String& infile,
5180 : const String& outfile,
5181 : const Vector<Int>& refField,
5182 : const Vector<Int>& refSpwMap,
5183 : const Vector<Int>& tranField,
5184 : const Bool& append,
5185 : const Float& inGainThres,
5186 : const String& antSel,
5187 : const String& timerangeSel,
5188 : const String& scanSel,
5189 : SolvableVisCal::fluxScaleStruct& oFluxScaleFactor,
5190 : const String& oListFile,
5191 : const Bool& incremental,
5192 : const Int& fitorder,
5193 : const Bool& display) {
5194 :
5195 : // throw(AipsError("Method 'fluxscale' is temporarily disabled."));
5196 :
5197 : // TBD: write inputs to MSHistory
5198 0 : logSink() << LogOrigin("Calibrater","fluxscale") << LogIO::NORMAL3;
5199 :
5200 0 : SolvableVisCal *fsvj_(NULL);
5201 : try {
5202 : // If infile is Calibration table
5203 0 : if (Table::isReadable(infile) &&
5204 0 : TableUtil::tableInfo(infile).type()=="Calibration") {
5205 :
5206 : // get calibration type
5207 0 : String caltype;
5208 0 : caltype = TableUtil::tableInfo(infile).subType();
5209 : logSink() << "Table " << infile
5210 : << " is of type: "<< caltype
5211 0 : << LogIO::POST;
5212 0 : String message="Table "+infile+" is of type: "+caltype;
5213 0 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
5214 :
5215 : // form selection
5216 0 : String select="";
5217 : // Selection is empty for case of no tran specification
5218 0 : if (tranField.nelements()>0) {
5219 :
5220 : // All selected fields
5221 0 : Vector<Int> allflds = concatenateArray(refField,tranField);
5222 :
5223 : // Assemble TaQL
5224 0 : ostringstream selectstr;
5225 0 : selectstr << "FIELD_ID IN [";
5226 0 : for (Int iFld=0; iFld<allflds.shape(); iFld++) {
5227 0 : if (iFld>0) selectstr << ", ";
5228 0 : selectstr << allflds(iFld);
5229 : }
5230 0 : selectstr << "]";
5231 0 : select=selectstr.str();
5232 0 : }
5233 :
5234 : // Construct proper SVC object
5235 0 : if (caltype == "G Jones") {
5236 0 : fsvj_ = createSolvableVisCal("G",*vs_p);
5237 0 : } else if (caltype == "T Jones") {
5238 0 : fsvj_ = createSolvableVisCal("T",*vs_p);
5239 : } else {
5240 : // Can't process other than G and T (add B?)
5241 0 : ostringstream typeErr;
5242 0 : typeErr << "Type " << caltype
5243 0 : << " not supported in fluxscale.";
5244 :
5245 0 : throw(AipsError(typeErr.str()));
5246 0 : }
5247 :
5248 : // fill table with selection
5249 0 : RecordDesc applyparDesc;
5250 0 : applyparDesc.addField ("table", TpString);
5251 0 : applyparDesc.addField ("select", TpString);
5252 0 : Record applypar(applyparDesc);
5253 0 : applypar.define ("table", infile);
5254 0 : applypar.define ("select", select);
5255 0 : fsvj_->setApply(applypar);
5256 :
5257 : //Bool incremental=false;
5258 : // Make fluxscale calculation
5259 0 : Vector<String> fldnames(MSFieldColumns(ms_p->field()).name().getColumn());
5260 : //fsvj_->fluxscale(refField,tranField,refSpwMap,fldnames,oFluxScaleFactor,
5261 0 : fsvj_->fluxscale(outfile,refField,tranField,refSpwMap,fldnames,inGainThres,antSel,
5262 : timerangeSel,scanSel,oFluxScaleFactor, oListFile,incremental,fitorder,display);
5263 : // oListFile);
5264 :
5265 : // If no outfile specified, use infile (overwrite!)
5266 0 : String out(outfile);
5267 0 : if (out.length()==0)
5268 0 : out = infile;
5269 :
5270 : // Store result
5271 0 : if (append) {
5272 0 : logSink() << "Appending result to " << out << LogIO::POST;
5273 0 : String message="Appending result to "+out;
5274 0 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
5275 0 : } else {
5276 0 : logSink() << "Storing result in " << out << LogIO::POST;
5277 0 : String message="Storing result in "+out;
5278 0 : MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
5279 0 : }
5280 0 : fsvj_->storeNCT(out,append);
5281 :
5282 : // Clean up
5283 0 : delete fsvj_;
5284 :
5285 0 : } else {
5286 : // Table not found/unreadable, or not Calibration
5287 0 : ostringstream tabErr;
5288 0 : tabErr << "File " << infile
5289 0 : << " does not exist or is not a Calibration Table.";
5290 :
5291 0 : throw(AipsError(tabErr.str()));
5292 :
5293 0 : }
5294 0 : } catch (AipsError x) {
5295 :
5296 : logSink() << LogIO::SEVERE
5297 : << "Caught Exception: "
5298 : << x.getMesg()
5299 0 : << LogIO::POST;
5300 :
5301 : // Clean up
5302 0 : if (fsvj_) delete fsvj_;
5303 :
5304 : // Write to MS History table
5305 : // String message="Caught Exception: "+x.getMesg();
5306 : // MSHistoryHandler::addMessage(*ms_p, message, "calibrater", "", "calibrater::fluxscale()");
5307 :
5308 0 : throw(AipsError("Error in Calibrater::fluxscale."));
5309 :
5310 : return;
5311 :
5312 0 : }
5313 0 : return;
5314 :
5315 :
5316 : }
5317 :
5318 0 : void OldCalibrater::accumulate(const String& intab,
5319 : const String& incrtab,
5320 : const String& outtab,
5321 : const String& fields,
5322 : const String& calFields,
5323 : const String& interp,
5324 : const Double& t,
5325 : const Vector<Int>& spwmap) {
5326 :
5327 : // logSink() << LogOrigin("Calibrater","accumulate") << LogIO::NORMAL;
5328 :
5329 0 : logSink() << "Beginning accumulate." << LogIO::POST;
5330 :
5331 : // SVJ objects:
5332 0 : SolvableVisCal *incal_(NULL), *incrcal_(NULL);
5333 :
5334 : try {
5335 :
5336 : /*
5337 : cout << "intab = " << intab << endl;
5338 : cout << "incrtab = " << incrtab << endl;
5339 : cout << "outtab = " << outtab << endl;
5340 : cout << "fields = " << fields << endl;
5341 : cout << "calFields = " << calFields << endl;
5342 : cout << "interp = " << interp << endl;
5343 : cout << "t = " << t << endl;
5344 : */
5345 :
5346 : // Incremental table's type sets the type we are dealing with
5347 0 : String caltype=calTableType(incrtab);
5348 :
5349 : // If no input cumulative timescale specified, then
5350 : // a valid input cumulative table must be specified
5351 0 : if (t < 0.0) {
5352 :
5353 0 : String intype=calTableType(intab);
5354 :
5355 0 : if (intype!=caltype) {
5356 :
5357 0 : ostringstream typeErr;
5358 0 : typeErr << "Table " << intab
5359 0 : << " is not the same type as "
5360 0 : << incrtab << " (" << caltype << ")";
5361 0 : throw(AipsError(typeErr.str()));
5362 0 : }
5363 0 : }
5364 :
5365 : // At this point all is ok; we will:
5366 : // o fill from intab and accumulate to it (t<0), OR
5367 : // o create a new cumulative table from scratch (t>0)
5368 :
5369 : // If creating a new cumulative table, it must span the whole dataset,
5370 : // so reset data selection to whole MS, and setup iterator
5371 0 : if (t>0.0) {
5372 0 : selectvis();
5373 0 : Block<Int> columns;
5374 0 : columns.resize(4);
5375 0 : columns[0]=MS::ARRAY_ID;
5376 0 : columns[1]=MS::TIME;
5377 0 : columns[2]=MS::FIELD_ID;
5378 0 : columns[3]=MS::DATA_DESC_ID;
5379 0 : vs_p->resetVisIter(columns,t);
5380 0 : }
5381 :
5382 : // logSink() << "Table " << infile
5383 : // << " is of type: "<< caltype
5384 : // << LogIO::POST;
5385 :
5386 0 : incal_ = createSolvableVisCal(caltype,*vs_p);
5387 0 : incrcal_ = createSolvableVisCal(caltype,*vs_p);
5388 :
5389 : // TBD: move to svj.setAccumulate?
5390 0 : if ( !(incal_->accumulatable()) ) {
5391 0 : ostringstream typeErr;
5392 0 : typeErr << "Type " << caltype
5393 0 : << " not yet supported in accumulate.";
5394 0 : throw(AipsError(typeErr.str()));
5395 0 : }
5396 :
5397 : // At this point, accumulation apparently supported,
5398 : // so continue...
5399 :
5400 : // initialize the cumulative solutions
5401 0 : incal_->setAccumulate(*vs_p,intab,"",t,-1);
5402 :
5403 :
5404 : /*
5405 : // form selection on incr table
5406 : String incrSel="";
5407 : if (calFields.shape()>0) {
5408 :
5409 : // Assemble TaQL
5410 : ostringstream selectstr;
5411 : selectstr << "FIELD_ID IN [";
5412 : for (Int iFld=0; iFld<calFields.shape(); iFld++) {
5413 : if (iFld>0) selectstr << ", ";
5414 : selectstr << calFields(iFld);
5415 : }
5416 : selectstr << "]";
5417 : incrSel=selectstr.str();
5418 : }
5419 : */
5420 :
5421 : // fill incr table with selection
5422 : logSink() << "Preparing to accumulate calibration from table: "
5423 : << incrtab
5424 0 : << LogIO::POST;
5425 :
5426 : // Set record format for calibration table application information
5427 0 : RecordDesc applyparDesc;
5428 0 : applyparDesc.addField ("t", TpDouble);
5429 0 : applyparDesc.addField ("table", TpString);
5430 : // applyparDesc.addField ("select", TpString);
5431 0 : applyparDesc.addField ("fieldstr", TpString);
5432 0 : applyparDesc.addField ("interp", TpString);
5433 0 : applyparDesc.addField ("spwmap",TpArrayInt);
5434 :
5435 : // Create record with the requisite field values
5436 0 : Record applypar(applyparDesc);
5437 0 : applypar.define ("t", t);
5438 0 : applypar.define ("table", incrtab);
5439 : // applypar.define ("select", incrSel);
5440 0 : applypar.define ("fieldstr", calFields);
5441 0 : applypar.define ("interp", interp);
5442 0 : applypar.define ("spwmap",spwmap);
5443 :
5444 0 : incrcal_->setApply(applypar);
5445 :
5446 0 : Vector<Int> fldidx(0);
5447 0 : if (fields.length()>0)
5448 0 : fldidx=getFieldIdx(fields);
5449 :
5450 : // All ready, now do the accumulation
5451 0 : incal_->accumulate(incrcal_,fldidx);
5452 :
5453 : // ...and store the result
5454 : logSink() << "Storing accumulated calibration in table: "
5455 : << outtab
5456 0 : << LogIO::POST;
5457 :
5458 0 : if (outtab != "")
5459 0 : incal_->calTableName()=outtab;
5460 :
5461 0 : incal_->storeNCT();
5462 :
5463 0 : delete incal_;
5464 0 : delete incrcal_;
5465 :
5466 : logSink() << "Finished accumulation."
5467 0 : << LogIO::POST;
5468 :
5469 0 : } catch (AipsError x) {
5470 : logSink() << LogIO::SEVERE
5471 : << "Caught Exception: "
5472 : << x.getMesg()
5473 0 : << LogIO::POST;
5474 :
5475 0 : if (incal_) delete incal_;
5476 0 : if (incrcal_) delete incrcal_;
5477 :
5478 0 : throw(AipsError("Error in Calibrater::accumulate."));
5479 : return;
5480 0 : }
5481 0 : return;
5482 :
5483 : }
5484 :
5485 16 : void OldCalibrater::specifycal(const String& type,
5486 : const String& caltable,
5487 : const String& time,
5488 : const String& spw,
5489 : const String& antenna,
5490 : const String& pol,
5491 : const Vector<Double>& parameter,
5492 : const String& infile,
5493 : const Bool& uniform) {
5494 :
5495 16 : logSink() << LogOrigin("Calibrater","specifycal") << LogIO::NORMAL;
5496 :
5497 : // SVJ objects:
5498 16 : SolvableVisCal *cal_(NULL);
5499 :
5500 : try {
5501 :
5502 : // Set record format for calibration table application information
5503 16 : RecordDesc specifyDesc;
5504 16 : specifyDesc.addField ("caltable", TpString);
5505 16 : specifyDesc.addField ("time", TpString);
5506 16 : specifyDesc.addField ("spw", TpArrayInt);
5507 16 : specifyDesc.addField ("antenna", TpArrayInt);
5508 16 : specifyDesc.addField ("pol", TpString);
5509 16 : specifyDesc.addField ("parameter", TpArrayDouble);
5510 16 : specifyDesc.addField ("caltype",TpString);
5511 16 : specifyDesc.addField ("infile",TpString);
5512 16 : specifyDesc.addField ("uniform",TpBool);
5513 :
5514 : // Create record with the requisite field values
5515 16 : Record specify(specifyDesc);
5516 16 : specify.define ("caltable", caltable);
5517 16 : specify.define ("time", time);
5518 16 : if (spw=="*")
5519 0 : specify.define ("spw",Vector<Int>(1,-1));
5520 : else
5521 16 : specify.define ("spw",getSpwIdx(spw));
5522 16 : if (antenna=="*")
5523 0 : specify.define ("antenna",Vector<Int>(1,-1) );
5524 : else
5525 16 : specify.define ("antenna",getAntIdx(antenna));
5526 16 : specify.define ("pol",pol);
5527 16 : specify.define ("parameter",parameter);
5528 16 : specify.define ("caltype",type);
5529 16 : specify.define ("infile",infile);
5530 16 : specify.define ("uniform",uniform);
5531 :
5532 : // Now do it
5533 16 : String utype=upcase(type);
5534 16 : if (utype=="G" || utype.contains("AMP") || utype.contains("PH"))
5535 0 : cal_ = createSolvableVisCal("G",*vs_p);
5536 16 : else if (utype=='K' || utype.contains("SBD") || utype.contains("DELAY"))
5537 0 : cal_ = createSolvableVisCal("K",*vs_p);
5538 16 : else if (utype.contains("MBD"))
5539 0 : cal_ = createSolvableVisCal("K",*vs_p); // as of 5.3, KMBD is just K
5540 16 : else if (utype.contains("ANTPOS"))
5541 0 : cal_ = createSolvableVisCal("KANTPOS",*vs_p);
5542 16 : else if (utype.contains("TSYS"))
5543 16 : cal_ = createSolvableVisCal("TSYS",*vs_p);
5544 0 : else if (utype.contains("EVLAGAIN") ||
5545 0 : utype.contains("SWP") ||
5546 0 : utype.contains("RQ"))
5547 0 : cal_ = createSolvableVisCal("EVLASWP",*vs_p);
5548 0 : else if (utype.contains("OPAC"))
5549 0 : cal_ = createSolvableVisCal("TOPAC",*vs_p);
5550 0 : else if (utype.contains("GC") || utype.contains("EFF"))
5551 0 : cal_ = createSolvableVisCal("GAINCURVE",*vs_p);
5552 0 : else if (utype.contains("TEC"))
5553 0 : cal_ = createSolvableVisCal("TEC",*vs_p);
5554 0 : else if (utype.contains("SDSKY_PS"))
5555 0 : cal_ = createSolvableVisCal("SDSKY_PS",*vs_p);
5556 0 : else if (utype.contains("SDSKY_RASTER"))
5557 0 : cal_ = createSolvableVisCal("SDSKY_RASTER",*vs_p);
5558 0 : else if (utype.contains("SDSKY_OTF"))
5559 0 : cal_ = createSolvableVisCal("SDSKY_OTF",*vs_p);
5560 : else
5561 0 : throw(AipsError("Unrecognized caltype."));
5562 :
5563 : // set up for specification (set up the CalSet)
5564 16 : cal_->setSpecify(specify);
5565 :
5566 : // fill with specified values
5567 16 : cal_->specify(specify);
5568 :
5569 : // Store result
5570 16 : cal_->storeNCT();
5571 :
5572 16 : delete cal_;
5573 :
5574 16 : } catch (AipsError x) {
5575 : logSink() << LogIO::SEVERE
5576 : << "Caught Exception: "
5577 : << x.getMesg()
5578 0 : << LogIO::POST;
5579 :
5580 0 : if (cal_) delete cal_;
5581 :
5582 0 : throw(AipsError("Error in Calibrater::specifycal."));
5583 : return;
5584 0 : }
5585 16 : return;
5586 :
5587 : }
5588 :
5589 0 : Bool OldCalibrater::smooth(const String& infile,
5590 : String& outfile, // const Bool& append,
5591 : const String& smoothtype,
5592 : const Double& smoothtime,
5593 : const String& fields)
5594 : {
5595 :
5596 : // TBD: support append?
5597 : // TBD: spw selection?
5598 :
5599 0 : logSink() << LogOrigin("Calibrater","smooth") << LogIO::NORMAL;
5600 :
5601 0 : logSink() << "Beginning smoothing/interpolating method." << LogIO::POST;
5602 :
5603 :
5604 : // A pointer to an SVC
5605 0 : SolvableVisCal *svc(NULL);
5606 :
5607 : try {
5608 :
5609 : // Handle no in file
5610 0 : if (infile=="")
5611 0 : throw(AipsError("Please specify an input calibration table."));
5612 :
5613 : // Handle bad smoothtype
5614 0 : if (smoothtype!="mean" && smoothtype!="median")
5615 0 : throw(AipsError("Unrecognized smooth type!"));
5616 :
5617 : // Handle bad smoothtime
5618 0 : if (smoothtime<=0)
5619 0 : throw(AipsError("Please specify a strictly positive smoothtime."));
5620 :
5621 : // Handle no outfile
5622 0 : if (outfile=="") {
5623 0 : outfile=infile;
5624 : logSink() << "Will overwrite input file with smoothing result."
5625 0 : << LogIO::POST;
5626 : }
5627 :
5628 :
5629 0 : svc = createSolvableVisCal(calTableType(infile),*vs_p);
5630 :
5631 0 : if (svc->smoothable()) {
5632 :
5633 : // Fill calibration table using setApply
5634 0 : RecordDesc applyparDesc;
5635 0 : applyparDesc.addField ("table", TpString);
5636 0 : Record applypar(applyparDesc);
5637 0 : applypar.define ("table", infile);
5638 0 : svc->setApply(applypar);
5639 :
5640 : // Convert refFields/transFields to index lists
5641 0 : Vector<Int> fldidx(0);
5642 0 : if (fields.length()>0)
5643 0 : fldidx=getFieldIdx(fields);
5644 :
5645 : // Delegate to SVC
5646 0 : svc->smooth(fldidx,smoothtype,smoothtime);
5647 :
5648 : // Store the result on disk
5649 : // if (append) logSink() << "Appending result to " << outfile << LogIO::POST;
5650 : //else
5651 0 : logSink() << "Storing result in " << outfile << LogIO::POST;
5652 :
5653 :
5654 0 : if (outfile != "")
5655 0 : svc->calTableName()=outfile;
5656 0 : svc->storeNCT();
5657 :
5658 : // Clean up
5659 0 : if (svc) delete svc; svc=NULL;
5660 :
5661 : // Apparently, it worked
5662 0 : return true;
5663 :
5664 0 : }
5665 : else
5666 0 : throw(AipsError("This type ("+svc->typeName()+") does not support smoothing."));
5667 :
5668 0 : } catch (AipsError x) {
5669 :
5670 : logSink() << LogIO::SEVERE
5671 : << "Caught Exception: "
5672 : << x.getMesg()
5673 0 : << LogIO::POST;
5674 : // Clean up
5675 0 : if (svc) delete svc; svc=NULL;
5676 :
5677 0 : throw(AipsError("Error in Calibrater::smooth."));
5678 :
5679 : return false;
5680 0 : }
5681 : return false;
5682 : }
5683 :
5684 : // List a calibration table
5685 0 : Bool OldCalibrater::listCal(const String& infile,
5686 : const String& field,
5687 : const String& antenna,
5688 : const String& spw,
5689 : const String& listfile,
5690 : const Int& pagerows) {
5691 :
5692 0 : SolvableVisCal *svc(NULL);
5693 0 : logSink() << LogOrigin("Calibrater","listCal");
5694 :
5695 : try {
5696 :
5697 : // Trap (currently) unsupported types
5698 0 : if (upcase(calTableType(infile))=="GSPLINE" ||
5699 0 : upcase(calTableType(infile))=="BPOLY")
5700 0 : throw(AipsError("GSPLINE and BPOLY tables cannot currently be listed."));
5701 :
5702 : // Get user's selected fields, ants
5703 0 : Vector<Int> ufldids=getFieldIdx(field);
5704 0 : Vector<Int> uantids=getAntIdx(antenna);
5705 :
5706 0 : String newSpw = spw;
5707 0 : Bool defaultSelect = false;
5708 0 : if (spw.empty()) { // list all channels (default)
5709 0 : defaultSelect = true;
5710 0 : newSpw = "*";
5711 : logSink() << LogIO::NORMAL1 << "Spws selected: ALL" << endl
5712 0 : << "Channels selected: ALL" << LogIO::POST;
5713 : }
5714 : // Get user's selected spw and channels
5715 0 : Vector<Int> uspwids=getSpwIdx(newSpw);
5716 0 : Matrix<Int> uchanids=getChanIdx(newSpw);
5717 0 : if (!defaultSelect) {
5718 : logSink() << LogIO::NORMAL1 << "Spw and Channel selection matrix: "
5719 : << endl << "Each rows shows: [ Spw , Start Chan , Stop Chan , Chan Step ]"
5720 0 : << endl << uchanids << LogIO::POST;
5721 : }
5722 : logSink() << LogIO::DEBUG2
5723 : << "uspwids = " << uspwids << endl
5724 0 : << "uchanids = " << uchanids << LogIO::POST;
5725 :
5726 : // By default, do first spw, first chan
5727 0 : if (uspwids.nelements()==0) {
5728 0 : uchanids.resize(1,4);
5729 0 : uchanids=0;
5730 : }
5731 :
5732 : // Set record format for calibration table application information
5733 0 : RecordDesc applyparDesc;
5734 0 : applyparDesc.addField ("table", TpString);
5735 :
5736 : // Create record with the requisite field values
5737 0 : Record applypar(applyparDesc);
5738 0 : applypar.define ("table", infile);
5739 :
5740 : // Generate the VisCal to be listed
5741 0 : svc = createSolvableVisCal(calTableType(infile),*vs_p);
5742 0 : svc->setApply(applypar);
5743 :
5744 : // list it
5745 0 : svc->listCal(ufldids,uantids,uchanids, //uchanids(0,0),uchanids(0,1),
5746 : listfile,pagerows);
5747 :
5748 0 : if (svc) delete svc; svc=NULL;
5749 :
5750 0 : return true;
5751 :
5752 0 : } catch (AipsError x) {
5753 :
5754 : logSink() << LogIO::SEVERE
5755 : << "Caught Exception: "
5756 : << x.getMesg()
5757 0 : << LogIO::POST;
5758 : // Clean up
5759 0 : if (svc) delete svc; svc=NULL;
5760 :
5761 0 : throw(AipsError("Error in Calibrater::listCal."));
5762 :
5763 : return false;
5764 0 : }
5765 : return false;
5766 :
5767 : }
5768 :
5769 147 : Bool OldCalibrater::initialize(MeasurementSet& inputMS,
5770 : Bool compress,
5771 : Bool addScratch, Bool addModel) {
5772 :
5773 147 : logSink() << LogOrigin("Calibrater","") << LogIO::NORMAL3;
5774 :
5775 : try {
5776 147 : timer_p.mark();
5777 :
5778 : // Set pointer ms_p from input MeasurementSet
5779 147 : if (ms_p) {
5780 3 : *ms_p=inputMS;
5781 : } else {
5782 144 : ms_p = new MeasurementSet(inputMS);
5783 144 : AlwaysAssert(ms_p,AipsError);
5784 : };
5785 :
5786 : // Disabled 2016/04/19 (gmoellen): avoid direct MS.HISTORY
5787 : // updates from below the python level, FOR NOW
5788 :
5789 : /*
5790 :
5791 : // Setup to write LogIO to HISTORY Table in MS
5792 : if(!(Table::isReadable(ms_p->historyTableName()))){
5793 : // create a new HISTORY table if its not there
5794 : TableRecord &kws = ms_p->rwKeywordSet();
5795 : SetupNewTable historySetup(ms_p->historyTableName(),
5796 : MSHistory::requiredTableDesc(),Table::New);
5797 : kws.defineTable(MS::keywordName(MS::HISTORY), Table(historySetup));
5798 : MSHistoryHandler::addMessage(*ms_p, "HISTORY Table added by Calibrater",
5799 : "Calibrater","","Calibrater::initialize()");
5800 : }
5801 : historytab_p=Table(ms_p->historyTableName(),
5802 : TableLock(TableLock::UserNoReadLocking), Table::Update);
5803 : // jagonzal (CAS-4110): When the selectvis method throws an exception the initialize method
5804 : // is called again to leave the calibrater in a proper state, and since there was a previous
5805 : // initialization the history handler was already created, and has to be destroyed before
5806 : // creating a new one to avoid leaveing the HISTORY table opened.
5807 : if (hist_p) delete hist_p;
5808 : hist_p= new MSHistoryHandler(*ms_p, "calibrater");
5809 :
5810 : // (2016/04/19) */
5811 :
5812 : // Remember the ms's name
5813 147 : msname_p=ms_p->tableName();
5814 :
5815 :
5816 : // Add/init scr cols, if requested (init is hard-wired)
5817 147 : if (addScratch || addModel) {
5818 90 : Bool alsoinit=true;
5819 90 : VisSetUtil::addScrCols(*ms_p,addModel,addScratch,alsoinit,compress);
5820 : }
5821 :
5822 : // Set the selected MeasurementSet to be the same initially
5823 : // as the input MeasurementSet
5824 147 : if (mssel_p) delete mssel_p;
5825 147 : mssel_p=new MeasurementSet(*ms_p);
5826 :
5827 : logSink() << LogIO::NORMAL
5828 : << "Initializing nominal selection to the whole MS."
5829 147 : << LogIO::POST;
5830 :
5831 :
5832 : // Create a VisSet with no selection
5833 : // (gmoellen 2012/02/06: this merely makes a VisIter now)
5834 147 : if (vs_p) {
5835 3 : delete vs_p;
5836 3 : vs_p=0;
5837 : };
5838 147 : Block<Int> nosort(0);
5839 147 : Matrix<Int> noselection;
5840 147 : Double timeInterval=0;
5841 : // gmoellen 2012/02/06 vs_p=new VisSet(*ms_p,nosort,noselection,addScratch,timeInterval,compress, addModel);
5842 147 : vs_p=new VisSet(*ms_p,nosort,noselection,false,timeInterval,false,false);
5843 :
5844 : // Size-up the chanmask PB
5845 147 : initChanMask();
5846 :
5847 : // Create the associated VisEquation
5848 : // TBD: move to ctor and make it non-pointer
5849 147 : if (ve_p) {
5850 3 : delete ve_p;
5851 3 : ve_p=0;
5852 : };
5853 147 : ve_p=new VisEquation();
5854 :
5855 : // Reset the apply/solve VisCals
5856 147 : reset(true,true);
5857 :
5858 147 : return true;
5859 :
5860 147 : } catch (AipsError x) {
5861 0 : logSink() << LogOrigin("Calibrater","initialize",WHERE)
5862 : << LogIO::SEVERE << "Caught exception: " << x.getMesg()
5863 0 : << LogIO::POST;
5864 0 : cleanup();
5865 0 : cleanupVisSet();
5866 0 : if (ms_p) delete ms_p; ms_p=NULL;
5867 0 : if (hist_p) delete hist_p; hist_p=NULL;
5868 :
5869 0 : throw(AipsError("Error in Calibrater::initialize()"));
5870 : return false;
5871 0 : }
5872 : return false;
5873 : }
5874 :
5875 11 : Bool OldCalibrater::initCalSet(const Int& calSet)
5876 : {
5877 :
5878 : // logSink() << LogOrigin("Calibrater","initCalSet") << LogIO::NORMAL3;
5879 :
5880 11 : if (vs_p) {
5881 :
5882 11 : Block<Int> columns;
5883 : // include scan iteration, for more optimal iteration
5884 11 : columns.resize(5);
5885 11 : columns[0]=MS::ARRAY_ID;
5886 11 : columns[1]=MS::SCAN_NUMBER;
5887 11 : columns[2]=MS::FIELD_ID;
5888 11 : columns[3]=MS::DATA_DESC_ID;
5889 11 : columns[4]=MS::TIME;
5890 11 : vs_p->resetVisIter(columns,0.0);
5891 :
5892 11 : vs_p->initCalSet(calSet);
5893 11 : return true;
5894 11 : }
5895 : else {
5896 0 : throw(AipsError("Calibrater cannot initCalSet"));
5897 : return false;
5898 : }
5899 : }
5900 :
5901 212 : Bool OldCalibrater::cleanupVisSet() {
5902 :
5903 : // logSink() << LogOrigin("OldCalibrater","cleanupVisSet") << LogIO::NORMAL;
5904 :
5905 212 : if(vs_p) delete vs_p; vs_p=0;
5906 :
5907 : // Delete chanmask
5908 212 : initChanMask();
5909 :
5910 212 : return true;
5911 :
5912 : }
5913 :
5914 0 : VisibilityIterator::DataColumn OldCalibrater::configureForCorrection ()
5915 : {
5916 0 : if (!ok())
5917 0 : throw(AipsError("Calibrater not prepared for correct!"));
5918 :
5919 : // Nominally, we write out to the CORRECTED_DATA, unless absent
5920 0 : VisibilityIterator::DataColumn whichOutCol(VisibilityIterator::Corrected);
5921 :
5922 0 : if (!ms_p->tableDesc().isColumn("CORRECTED_DATA"))
5923 0 : throw(AipsError("CORRECTED_DATA column unexpectedly absent. Cannot correct."));
5924 :
5925 : // Ensure apply list non-zero and properly sorted
5926 0 : ve_p->setapply(vc_p);
5927 :
5928 : // Report the types that will be applied
5929 0 : applystate();
5930 :
5931 : // Arrange for iteration over data
5932 0 : Block<Int> columns;
5933 : // include scan iteration
5934 0 : columns.resize(5);
5935 0 : columns[0]=MS::ARRAY_ID;
5936 0 : columns[1]=MS::SCAN_NUMBER;
5937 0 : columns[2]=MS::FIELD_ID;
5938 0 : columns[3]=MS::DATA_DESC_ID;
5939 0 : columns[4]=MS::TIME;
5940 :
5941 : // Reset the VisibilityIterator in the VisSet.
5942 0 : vs_p->resetVisIter (columns, 0.0);
5943 :
5944 0 : return whichOutCol;
5945 0 : }
5946 :
5947 165 : void OldCalibrater::selectChannel(const String& spw) {
5948 :
5949 : // Initialize the chanmask_
5950 165 : initChanMask();
5951 :
5952 165 : if (mss_p && mssel_p) {
5953 :
5954 : // Refresh the frequencySelections object to feed to VI2, if relevant
5955 165 : frequencySelections_p.reset(new vi::FrequencySelections());
5956 :
5957 165 : vi::FrequencySelectionUsingChannels usingChannels;
5958 165 : usingChannels.add(*mss_p,mssel_p);
5959 165 : frequencySelections_p->add(usingChannels);
5960 :
5961 : // cout << usingChannels.toString() << endl;
5962 : // cout << "FS.size() = " << frequencySelections_p->size() << endl;
5963 :
5964 165 : }
5965 :
5966 165 : Matrix<Int> chansel = getChanIdx(spw);
5967 165 : uInt nselspw=chansel.nrow();
5968 :
5969 165 : if (nselspw==0)
5970 : logSink() << "Frequency selection: Selecting all channels in all spws."
5971 147 : << LogIO::POST;
5972 : else {
5973 :
5974 18 : logSink() << "Frequency selection: " << LogIO::POST;
5975 :
5976 : // Trap non-unit step (for now)
5977 18 : if (ntrue(chansel.column(3)==1)!=nselspw) {
5978 : logSink() << LogIO::WARN
5979 : << "Calibration does not support non-unit channel stepping; "
5980 : << "using step=1."
5981 0 : << LogIO::POST;
5982 0 : chansel.column(3)=1;
5983 : }
5984 :
5985 18 : Int nspw=vs_p->numberSpw();
5986 18 : Vector<Int> nChan0;
5987 18 : nChan0 = vs_p->numberChan();
5988 :
5989 18 : Vector<Int> uspw(chansel.column(0));
5990 18 : Vector<Int> ustart(chansel.column(1));
5991 18 : Vector<Int> uend(chansel.column(2));
5992 :
5993 18 : Vector<Int> start(nspw,INT_MAX);
5994 18 : Vector<Int> end(nspw,-INT_MAX);
5995 18 : logSink() << LogIO::NORMAL;
5996 97 : for (uInt i=0;i<nselspw;++i) {
5997 :
5998 79 : Int& spw=uspw(i);
5999 :
6000 : // Initialize this spw mask, if necessary (def = masked)
6001 79 : if (!chanmask_[spw])
6002 72 : chanmask_[spw]=new Vector<Bool>(nChan0(spw),true);
6003 :
6004 : // revise net start/end/nchan
6005 79 : start(spw)=min(start(spw),ustart(i));
6006 79 : end(spw)=max(end(spw),uend(i));
6007 79 : Int nchan=end(spw)-start(spw)+1; // net inclusive nchan
6008 :
6009 : // User's
6010 79 : Int step=chansel(i,3);
6011 79 : Int unchan=uend(i)-ustart(i)+1;
6012 :
6013 : // Update the mask (false = valid)
6014 79 : (*chanmask_[spw])(Slice(ustart(i),unchan))=false;
6015 :
6016 :
6017 : logSink() << ". Spw " << spw << ":"
6018 316 : << ustart(i) << "~" << uend(i)
6019 79 : << " (" << uend(i)-ustart(i)+1 << " channels,"
6020 : << " step by " << step << ")"
6021 158 : << endl;
6022 :
6023 : /*
6024 : cout << i << " " << spw << " {"
6025 : << start(spw) << " [" << ustart(i) << " "
6026 : << uend(i) << "] " << end(spw) << "}" << endl;
6027 : cout << "chanmask = ";
6028 : for (Int j=0;j<nChan0(spw);++j) cout << (*chanmask_[spw])(j);
6029 : cout << endl << endl;
6030 : */
6031 :
6032 : // Call via VisSet (avoid call to VisIter::origin)
6033 79 : vs_p->selectChannel(1,start(spw),nchan,step,spw,false);
6034 :
6035 : } // i
6036 18 : logSink() << LogIO::POST;
6037 :
6038 18 : } // non-triv spw selection
6039 :
6040 : // For testing:
6041 : if (false) {
6042 :
6043 : VisIter& vi(vs_p->iter());
6044 : VisBuffer vb(vi);
6045 :
6046 : // Pass each timestamp (VisBuffer) to VisEquation for correction
6047 : for (vi.originChunks(); vi.moreChunks(); vi.nextChunk()) {
6048 : vi.origin();
6049 : // for (vi.origin(); vi.more(); vi++)
6050 : cout << vb.spectralWindow() << " "
6051 : << vb.nChannel() << " "
6052 : << vb.channel() << " "
6053 : << vb.visCube().shape()
6054 : << endl;
6055 : }
6056 : }
6057 :
6058 165 : }
6059 :
6060 524 : void OldCalibrater::initChanMask() {
6061 :
6062 4012 : for (uInt i=0;i<chanmask_.nelements();++i)
6063 3488 : if (chanmask_[i])
6064 72 : delete chanmask_[i];
6065 524 : if (vs_p) {
6066 312 : chanmask_.resize(vs_p->numberSpw(),true);
6067 312 : chanmask_=NULL;
6068 : }
6069 : else {
6070 : // throw(AipsError("Trouble sizing chanmask!"));
6071 : // just don't support channel masking:
6072 212 : chanmask_.resize(0,true);
6073 : }
6074 :
6075 524 : }
6076 :
6077 : // Select on channel in the VisSet
6078 0 : void OldCalibrater::selectChannel(const String& mode,
6079 : const Int& nchan,
6080 : const Int& start, const Int& step,
6081 : const MRadialVelocity& mStart,
6082 : const MRadialVelocity& mStep) {
6083 :
6084 : // Set data selection variables
6085 0 : dataMode_p=mode;
6086 0 : dataNchan_p=nchan;
6087 0 : if (dataNchan_p<0) dataNchan_p=0;
6088 0 : dataStart_p=start;
6089 0 : if (dataStart_p<0) dataNchan_p=0;
6090 0 : dataStep_p=step;
6091 0 : if (dataStep_p<1) dataNchan_p=1;
6092 :
6093 0 : mDataStart_p=mStart;
6094 0 : mDataStep_p=mStep;
6095 :
6096 : // Select on frequency channel
6097 0 : if(dataMode_p=="channel") {
6098 : // *** this bit here is temporary till we unifomize data selection
6099 : //Getting the selected SPWs
6100 0 : MSMainColumns msc(*mssel_p);
6101 0 : Vector<Int> dataDescID = msc.dataDescId().getColumn();
6102 : Bool dum;
6103 0 : Sort sort( dataDescID.getStorage(dum),sizeof(Int) );
6104 0 : sort.sortKey((uInt)0,TpInt);
6105 0 : Vector<uInt> index,uniq;
6106 0 : sort.sort(index,dataDescID.nelements());
6107 0 : uInt nSpw = sort.unique(uniq,index);
6108 :
6109 0 : Vector<Int> selectedSpw(nSpw);
6110 0 : Vector<Int> nChan(nSpw);
6111 0 : for (uInt k=0; k < nSpw; ++k) {
6112 0 : selectedSpw[k]=dataDescID[index[uniq[k]]];
6113 0 : nChan[k]=vs_p->numberChan()(selectedSpw[k]);
6114 :
6115 : }
6116 0 : if(dataNchan_p==0) dataNchan_p=vs_p->numberChan()(selectedSpw[0]);
6117 0 : if(dataStart_p<0) {
6118 : logSink() << LogIO::SEVERE << "Illegal start pixel = "
6119 0 : << dataStart_p << LogIO::POST;
6120 : }
6121 0 : Int end = Int(dataStart_p) + Int(dataNchan_p) * Int(dataStep_p);
6122 0 : for (uInt k=0; k < selectedSpw.nelements() ; ++k){
6123 0 : if(end < 1 || end > nChan[k]) {
6124 : logSink() << LogIO::SEVERE << "Illegal step pixel = " << dataStep_p
6125 0 : << " in Spw " << selectedSpw[k]
6126 0 : << LogIO::POST;
6127 : }
6128 : logSink() << "Selecting "<< dataNchan_p
6129 : << " channels, starting at visibility channel "
6130 : << dataStart_p << " stepped by "
6131 0 : << dataStep_p << " in Spw " << selectedSpw[k] << LogIO::POST;
6132 :
6133 : // Set frequency channel selection for all spectral window id's
6134 : Int nch;
6135 : //Vector<Int> nChan=vs_p->numberChan();
6136 : //Int nSpw=vs_p->numberSpw();
6137 0 : if (dataNchan_p==0) {
6138 0 : nch=nChan(k);
6139 : }else {
6140 0 : nch=dataNchan_p;
6141 : };
6142 0 : vs_p->selectChannel(1,dataStart_p,nch,dataStep_p,selectedSpw[k]);
6143 :
6144 : }
6145 0 : }
6146 : // Select on velocity
6147 0 : else if (dataMode_p=="velocity") {
6148 0 : MVRadialVelocity mvStart(mDataStart_p.get("m/s"));
6149 0 : MVRadialVelocity mvStep(mDataStep_p.get("m/s"));
6150 : MRadialVelocity::Types
6151 0 : vType((MRadialVelocity::Types)mDataStart_p.getRefPtr()->getType());
6152 : logSink() << "Selecting "<< dataNchan_p
6153 : << " channels, starting at radio velocity " << mvStart
6154 : << " stepped by " << mvStep << ", reference frame is "
6155 0 : << MRadialVelocity::showType(vType) << LogIO::POST;
6156 0 : vs_p->iter().selectVelocity(Int(dataNchan_p), mvStart, mvStep,
6157 : vType, MDoppler::RADIO);
6158 0 : }
6159 :
6160 : // Select on optical velocity
6161 0 : else if (dataMode_p=="opticalvelocity") {
6162 0 : MVRadialVelocity mvStart(mDataStart_p.get("m/s"));
6163 0 : MVRadialVelocity mvStep(mDataStep_p.get("m/s"));
6164 : MRadialVelocity::Types
6165 0 : vType((MRadialVelocity::Types)mDataStart_p.getRefPtr()->getType());
6166 : logSink() << "Selecting "<< dataNchan_p
6167 : << " channels, starting at optical velocity " << mvStart
6168 : << " stepped by " << mvStep << ", reference frame is "
6169 0 : << MRadialVelocity::showType(vType) << LogIO::POST;
6170 0 : vs_p->iter().selectVelocity(Int(dataNchan_p), mvStart, mvStep,
6171 : vType, MDoppler::OPTICAL);
6172 0 : }
6173 :
6174 :
6175 0 : }
6176 :
6177 143 : Bool OldCalibrater::ok() {
6178 :
6179 143 : if(vs_p && ms_p && mssel_p && ve_p) {
6180 143 : return true;
6181 : }
6182 : else {
6183 0 : logSink() << "Calibrater is not yet initialized" << LogIO::POST;
6184 0 : return false;
6185 : }
6186 : }
6187 :
6188 2 : Bool OldCalibrater::genericGatherAndSolve() {
6189 :
6190 : #ifdef _OPENMP
6191 2 : Double Tsetup(0.0),Tgather(0.0),Tsolve(0.0);
6192 2 : Double time0=omp_get_wtime();
6193 : #endif
6194 :
6195 : //cout << "Generic gather and solve." << endl;
6196 :
6197 : // Create the solver
6198 2 : VisCalSolver vcs;
6199 :
6200 : // Inform logger/history
6201 2 : logSink() << "Solving for " << svc_p->typeName()
6202 2 : << LogIO::POST;
6203 :
6204 : // Initialize the svc according to current VisSet
6205 : // (this counts intervals, sizes CalSet)
6206 2 : Vector<Int> nChunkPerSol;
6207 2 : Int nSol = svc_p->sizeUpSolve(*vs_p,nChunkPerSol);
6208 :
6209 : // Create the in-memory (New)CalTable
6210 2 : svc_p->createMemCalTable();
6211 :
6212 : // The iterator, VisBuffer
6213 2 : VisIter& vi(vs_p->iter());
6214 2 : VisBuffer vb(vi);
6215 :
6216 2 : Vector<Int> slotidx(vs_p->numberSpw(),-1);
6217 :
6218 : // We will remember which spws couldn't be processed
6219 2 : Vector<Bool> unsolspw(vi.numberSpw());
6220 2 : unsolspw.set(false);
6221 :
6222 : // Manage verbosity of partial channel averaging
6223 2 : Vector<Bool> verb(vi.numberSpw(),true);
6224 :
6225 2 : Vector<Int64> nexp(vi.numberSpw(),0), natt(vi.numberSpw(),0),nsuc(vi.numberSpw(),0);
6226 :
6227 : #ifdef _OPENMP
6228 2 : Tsetup+=(omp_get_wtime()-time0);
6229 : #endif
6230 :
6231 2 : Int nGood(0);
6232 2 : vi.originChunks();
6233 41 : for (Int isol=0;isol<nSol && vi.moreChunks();++isol) {
6234 :
6235 : #ifdef _OPENMP
6236 39 : time0=omp_get_wtime();
6237 : #endif
6238 :
6239 39 : nexp(vi.spectralWindow())+=1;
6240 :
6241 : // capture obs, scan info so we can set it later
6242 : // (and not rely on what the VB averaging code can't properly do)
6243 39 : Vector<Int> scv,obsv;
6244 39 : Int solscan=vi.scan(scv)(0),solobs=vi.observationId(obsv)(0);
6245 :
6246 : // Arrange to accumulate
6247 : // VisBuffAccumulator vba(vs_p->numberAnt(),svc_p->preavg(),false);
6248 39 : VisBuffGroupAcc vbga(vs_p->numberAnt(),vs_p->numberSpw(),vs_p->numberFld(),svc_p->preavg());
6249 :
6250 163 : for (Int ichunk=0;ichunk<nChunkPerSol(isol);++ichunk) {
6251 :
6252 : // Current _chunk_'s spw
6253 124 : Int spw(vi.spectralWindow());
6254 :
6255 : // Only accumulate for solve if we can pre-calibrate
6256 124 : if (ve_p->spwOK(spw)) {
6257 :
6258 : // Collapse each timestamp in this chunk according to VisEq
6259 : // with calibration and averaging
6260 248 : for (vi.origin(); vi.more(); vi++) {
6261 :
6262 : // Force read of the field Id
6263 124 : vb.fieldId();
6264 :
6265 : // Apply the channel mask (~no-op, if unnecessary)
6266 124 : svc_p->applyChanMask(vb);
6267 :
6268 : // This forces the data/model/wt I/O, and applies
6269 : // any prior calibrations
6270 124 : ve_p->collapse(vb);
6271 :
6272 : // If permitted/required by solvable component, normalize
6273 124 : if (svc_p->normalizable())
6274 0 : vb.normalize();
6275 :
6276 : // If this solve not freqdep, and channels not averaged yet, do so
6277 124 : if (!svc_p->freqDepMat() && vb.nChannel()>1)
6278 0 : vb.freqAveCubes();
6279 :
6280 124 : if (svc_p->freqDepPar() &&
6281 124 : svc_p->fsolint()!="none" &&
6282 0 : svc_p->fintervalCh()>0.0) {
6283 : // cout << "svc_p->currSpw() = " << svc_p->currSpw() << endl;
6284 0 : if (verb(spw))
6285 : logSink() << " Reducing nchan in spw "
6286 : << spw
6287 0 : << " from " << vb.nChannel();
6288 0 : vb.channelAve(svc_p->chanAveBounds(spw));
6289 :
6290 : // Kludge for 3.4 to reset corr-indep flag to correct channel axis shape
6291 : // (because we use vb.flag() below, rather than vb.flagCube())
6292 0 : vb.flag().assign(operator>(partialNTrue(vb.flagCube(),IPosition(1,0)),0UL));
6293 :
6294 0 : if (verb(spw)) {
6295 : logSink() << " to "
6296 0 : << vb.nChannel() << LogIO::POST;
6297 0 : verb(spw)=false; // suppress future verbosity in this spw
6298 : }
6299 : }
6300 :
6301 : // Accumulate collapsed vb in a time average
6302 : // (only if the vb contains any unflagged data)
6303 124 : if (nfalse(vb.flag())>0)
6304 124 : vbga.accumulate(vb);
6305 :
6306 : }
6307 : }
6308 : else
6309 : // This spw not accumulated for solve
6310 0 : unsolspw(spw)=true;
6311 :
6312 : // Advance the VisIter, if possible
6313 124 : if (vi.moreChunks()) vi.nextChunk();
6314 :
6315 : }
6316 :
6317 : // Finalize the averged VisBuffer
6318 39 : vbga.finalizeAverage();
6319 :
6320 : // Establish meta-data for this interval
6321 : // (some of this may be used _during_ solve)
6322 : // (this sets currSpw() in the SVC)
6323 39 : Bool vbOk=(vbga.nBuf()>0 && svc_p->syncSolveMeta(vbga));
6324 :
6325 39 : svc_p->overrideObsScan(solobs,solscan);
6326 :
6327 : #ifdef _OPENMP
6328 39 : Tgather+=(omp_get_wtime()-time0);
6329 39 : time0=omp_get_wtime();
6330 : #endif
6331 :
6332 39 : if (vbOk) {
6333 :
6334 : // Use spw of first VB in vbga
6335 : // TBD: (currSpw==thisSpw) here?? (I.e., use svc_p->currSpw()? currSpw is prot!)
6336 39 : Int thisSpw=svc_p->spwMap()(vbga(0).spectralWindow());
6337 :
6338 39 : natt(thisSpw)+=1;
6339 :
6340 39 : slotidx(thisSpw)++;
6341 :
6342 : // Make data amp- or phase-only, if needed
6343 39 : vbga.enforceAPonData(svc_p->apmode());
6344 :
6345 : // Select on correlation via weights, according to the svc
6346 39 : vbga.enforceSolveCorrWeights(svc_p->phandonly());
6347 :
6348 39 : if (svc_p->useGenericSolveOne()) {
6349 : // generic individual solve
6350 :
6351 : //cout << "Generic individual solve: isol=" << isol << endl;
6352 :
6353 : // First guess
6354 0 : svc_p->guessPar(vbga(0));
6355 :
6356 : // Solve for each parameter channel (in curr Spw)
6357 :
6358 : // (NB: force const version of nChanPar() [why?])
6359 : // for (Int ich=0;ich<((const SolvableVisCal*)svc_p)->nChanPar();++ich) {
6360 0 : Bool totalGoodSol(false);
6361 0 : for (Int ich=((const SolvableVisCal*)svc_p)->nChanPar()-1;ich>-1;--ich) {
6362 : // for (Int ich=0;ich<((const SolvableVisCal*)svc_p)->nChanPar();++ich) {
6363 :
6364 : // If pars chan-dep, SVC mechanisms for only one channel at a time
6365 0 : svc_p->markTimer();
6366 0 : svc_p->focusChan()=ich;
6367 :
6368 : // svc_p->state();
6369 :
6370 : // cout << "Starting solution..." << endl;
6371 :
6372 : // Pass VE, SVC, VB to solver
6373 0 : Bool goodSoln=vcs.solve(*ve_p,*svc_p,vbga);
6374 :
6375 : // cout << "goodSoln= " << boolalpha << goodSoln << endl;
6376 :
6377 : // If good...
6378 0 : if (goodSoln) {
6379 0 : totalGoodSol=true;
6380 :
6381 0 : svc_p->formSolveSNR();
6382 0 : svc_p->applySNRThreshold();
6383 :
6384 : // ..and file this solution in the correct slot
6385 0 : if (svc_p->freqDepPar())
6386 0 : svc_p->keep1(ich);
6387 : // svc_p->keep(slotidx(thisSpw));
6388 : // Int n=svc_p->nSlots(thisSpw);
6389 : // svc_p->printActivity(n,slotidx(thisSpw),vi.fieldId(),thisSpw,nGood);
6390 :
6391 : }
6392 : else {
6393 : // report where this failure occured
6394 0 : svc_p->currMetaNote();
6395 0 : if (svc_p->freqDepPar())
6396 : // We must record a flagged solution for this channel
6397 0 : svc_p->keep1(ich);
6398 : }
6399 :
6400 : } // parameter channels
6401 :
6402 0 : if (totalGoodSol) {
6403 0 : svc_p->keepNCT();
6404 0 : nsuc(thisSpw)+=1;
6405 : }
6406 :
6407 : // Count good solutions.
6408 0 : if (totalGoodSol) nGood++;
6409 :
6410 : }
6411 : else {
6412 : //cout << "Self-directed individual solve: isol=" << isol << endl;
6413 : // self-directed individual solve
6414 : // TBD: selfSolveOne should return T/F for "good"
6415 39 : svc_p->selfSolveOne(vbga);
6416 :
6417 : // File this solution in the correct slot of the CalSet
6418 39 : svc_p->keepNCT();
6419 :
6420 39 : nGood++;
6421 39 : nsuc(thisSpw)+=1;
6422 : }
6423 :
6424 : } // vbOK
6425 :
6426 : #ifdef _OPENMP
6427 39 : Tsolve+=(omp_get_wtime()-time0);
6428 : #endif
6429 :
6430 39 : } // isol
6431 :
6432 : logSink() << " Found good "
6433 2 : << svc_p->typeName() << " solutions in "
6434 : << nGood << " slots."
6435 2 : << LogIO::POST;
6436 : #ifdef _OPENMP
6437 : #ifdef REPORT_CAL_TIMING
6438 : cout << "OldCalibrater::genericGatherAndSolve Timing: " << endl;
6439 : cout << " setup=" << Tsetup
6440 : << " gather=" << Tgather
6441 : << " solve=" << Tsolve
6442 : << " total=" << Tsetup+Tgather+Tsolve
6443 : << endl;
6444 : #endif
6445 : #endif
6446 :
6447 2 : summarize_uncalspws(unsolspw, "solv");
6448 :
6449 : // Store whole of result in a caltable
6450 2 : if (nGood==0) {
6451 : logSink() << "No output calibration table written."
6452 0 : << LogIO::POST;
6453 : }
6454 : else {
6455 :
6456 : // TBD: Remove BPOLY specificity here
6457 2 : if (svc_p->typeName()!="BPOLY") {
6458 : // Do global post-solve tinkering (e.g., phase-only, normalization, etc.)
6459 2 : svc_p->globalPostSolveTinker();
6460 :
6461 : // write the table
6462 2 : svc_p->storeNCT();
6463 :
6464 : }
6465 : }
6466 :
6467 : // Fill activity record
6468 2 : actRec_=Record();
6469 2 : actRec_.define("origin","Calibrater::genericGatherAndSolve");
6470 2 : actRec_.define("nExpected",nexp);
6471 2 : actRec_.define("nAttempt",natt);
6472 2 : actRec_.define("nSucceed",nsuc);
6473 :
6474 : {
6475 2 : Record solveRec=svc_p->solveActionRec();
6476 2 : if (solveRec.nfields()>0)
6477 0 : actRec_.merge(solveRec);
6478 2 : }
6479 :
6480 :
6481 :
6482 2 : return true;
6483 :
6484 2 : }
6485 :
6486 :
6487 : } //# NAMESPACE CASA - END
|