Line data Source code
1 : //# CalSummary.cc: Helper class for listing a CalTable
2 : //# Copyright (C) 2018
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //#
27 :
28 : #include <synthesis/CalTables/CalSummary.h>
29 : #include <synthesis/CalTables/CalMainColumns.h>
30 : #include <synthesis/CalTables/CalDescColumns.h>
31 : #include <synthesis/CalTables/CalIter.h>
32 : #include <synthesis/CalTables/CalBuffer.h>
33 : #include <synthesis/CalTables/CalSetMetaInfo.h>
34 : #include <synthesis/MeasurementComponents/MSMetaInfoForCal.h>
35 :
36 : #include <casacore/casa/Quanta/QVector.h>
37 : #include <casacore/casa/iomanip.h>
38 : #include <casacore/casa/iostream.h>
39 : #include <casacore/casa/OS/Path.h>
40 : #include <casacore/measures/Measures/MeasTable.h>
41 : #include <casacore/ms/MSOper/MSMetaData.h>
42 : #include <casacore/tables/Tables/TableRecord.h>
43 : #include <casacore/casa/Utilities/GenSort.h>
44 :
45 : using namespace casacore;
46 : namespace casa { //# NAMESPACE CASA - BEGIN
47 :
48 : //
49 : // Constructor assigns pointer. If CT goes out of scope you
50 : // will get rubbish. Also sets string to separate subtable output.
51 : //
52 0 : CalSummary::CalSummary (CalTable& ct)
53 0 : : pCT(&ct),
54 0 : msname_p(""),
55 0 : haveMS_p(false),
56 0 : dashlin1(replicate("-",80)),
57 0 : dashlin2(replicate("=",80))
58 0 : { setMSname(); }
59 :
60 0 : CalSummary::CalSummary (CalTable* ct)
61 0 : : pCT(ct),
62 0 : msname_p(""),
63 0 : haveMS_p(false),
64 0 : dashlin1(replicate("-",80)),
65 0 : dashlin2(replicate("=",80))
66 0 : { setMSname(); }
67 :
68 0 : CalSummary::~CalSummary () { }
69 :
70 :
71 : //
72 : // Retrieve number of rows
73 : //
74 0 : Int CalSummary::nrow () const
75 : {
76 0 : return pCT->nRowMain();
77 : }
78 :
79 :
80 : //
81 : // Get cal table name
82 : //
83 0 : const String CalSummary::name () const
84 : {
85 0 : return pCT->tableName();
86 : }
87 :
88 :
89 : //
90 : // Reassign pointer.
91 : //
92 0 : Bool CalSummary::setCT (CalTable& ct)
93 : {
94 : CalTable* pTemp;
95 0 : pTemp = &ct;
96 0 : if (pTemp == 0) {
97 0 : return False;
98 : } else {
99 0 : pCT = pTemp;
100 0 : setMSname();
101 0 : return True;
102 : }
103 : }
104 :
105 0 : void CalSummary::setMSname() {
106 0 : ROCalDescColumns calDescCol(*pCT);
107 0 : Path filepath(name());
108 0 : String msname(calDescCol.msName()(0)), path(filepath.dirName());
109 0 : if (!path.empty())
110 0 : path += "/";
111 0 : String fullmsname = path + msname;
112 0 : if (!msname.empty() && Table::isReadable(fullmsname)) {
113 0 : msname_p = fullmsname;
114 0 : haveMS_p = true;
115 : } else {
116 0 : haveMS_p = false;
117 : }
118 0 : }
119 :
120 : //
121 : // List information about a ct to the logger
122 : //
123 0 : void CalSummary::list (LogIO& os, Bool verbose) const
124 : {
125 : // List a title for the Summary
126 0 : listTitle (os);
127 : // List the main table and subtables in a useful order and format
128 0 : listWhere(os, verbose);
129 0 : os << dashlin1 << endl;
130 0 : listWhat(os, verbose);
131 0 : os << dashlin1 << endl;
132 0 : listHow(os, verbose);
133 0 : os << dashlin1 << endl;
134 : // Post it
135 0 : os.post();
136 0 : }
137 :
138 : //
139 : // List a title for the Summary
140 : //
141 0 : void CalSummary::listTitle (LogIO& os) const
142 : {
143 0 : os << LogIO::NORMAL;
144 : // Type of cal table
145 0 : casacore::String type("unknown");
146 0 : os << dashlin2 << endl << "Cal Table Name: " << this->name();
147 0 : type = pCT->type();
148 0 : os << " Cal Type: " << type;
149 0 : os << endl << dashlin2 << endl;
150 0 : }
151 :
152 :
153 : //
154 : // Convenient table groupings
155 : //
156 0 : void CalSummary::listWhere (LogIO& os, Bool verbose) const
157 : {
158 0 : listObservation (os,verbose);
159 0 : }
160 :
161 0 : void CalSummary::listWhat (LogIO& os, Bool verbose) const
162 : {
163 0 : listMain(os, verbose);
164 0 : os << dashlin1 << endl;
165 0 : listField(os, verbose);
166 0 : }
167 :
168 0 : void CalSummary::listHow (LogIO& os, Bool verbose) const
169 : {
170 0 : listSpectralWindow(os, verbose);
171 0 : os << dashlin1 << endl;
172 0 : listAntenna(os, verbose);
173 0 : }
174 :
175 : //
176 : // SUBTABLES
177 : //
178 0 : void CalSummary::listMain (LogIO& os, Bool verbose) const
179 : {
180 0 : if (nrow() <= 0) {
181 0 : os << "The MAIN table is empty: there are no data!!!" << endl << LogIO::POST;
182 0 : return;
183 : }
184 : // to get columns from main and subtables
185 0 : ROCalMainColumns ctmain(*pCT);
186 0 : ROCalDescColumns ctdesc(*pCT);
187 :
188 : // Time:
189 0 : casacore::Vector<casacore::Double> times = ctmain.time().getColumn();
190 0 : casacore::Double startTime = times(0);
191 0 : casacore::Double stopTime = times(times.size()-1);
192 0 : casacore::Double exposTime = stopTime - startTime;
193 0 : casacore::String timeref = ctmain.time().keywordSet().subRecord("MEASINFO").asString("Ref");
194 : // Output info
195 : os << " Data records: " << nrow() << " Total elapsed time = "
196 : << exposTime << " seconds" << endl
197 : << " Observed from "
198 0 : << MVTime(startTime/C::day).string(MVTime::DMY,7)
199 : << " to "
200 0 : << MVTime(stopTime/C::day).string(MVTime::DMY,7)
201 : << " (" << timeref << ")"
202 0 : << endl << endl;
203 0 : os << LogIO::POST;
204 :
205 0 : if (verbose) {
206 : // Field names from MS:
207 0 : casacore::Vector<casacore::String> fieldnames;
208 0 : if (haveMS_p) {
209 0 : MSMetaInfoForCal msmeta(msname_p);
210 0 : msmeta.fieldNames(fieldnames);
211 0 : }
212 : // Spw Ids from CAL_DESC table
213 0 : casacore::Array<casacore::Int> spwids(ctdesc.spwId().getColumn());
214 :
215 : // Field widths for printing:
216 0 : casacore::Int width_lead(2),
217 0 : width_scan(4),
218 0 : width_time(22),
219 0 : width_fieldId(5),
220 0 : width_fieldname(20),
221 0 : width_nrow(10);
222 :
223 : // Sort order
224 0 : casacore::Vector<casacore::Int> icols(3);
225 0 : icols[0] = MSC::OBSERVATION_ID;
226 0 : icols[1] = MSC::SCAN_NUMBER;
227 0 : icols[2] = MSC::FIELD_ID;
228 0 : CalIter* iter = new CalIter(*pCT, icols);
229 0 : CalBuffer* buff = new CalBuffer(*iter);
230 : // values from main table
231 0 : casacore::Vector<casacore::Int> obs = buff->obsId();
232 0 : casacore::Vector<casacore::Double> times = buff->time();
233 0 : casacore::Vector<casacore::Int> scans = buff->scanNo();
234 0 : casacore::Vector<casacore::Int> fieldIds = buff->fieldId();
235 0 : casacore::Vector<casacore::Double> intervals = buff->interval();
236 0 : casacore::Vector<casacore::Int> calDescIds = buff->calDescId();
237 0 : casacore::Int lastobs(-2); // print obsid when changes
238 0 : casacore::Double lastday(0.0), lastTime(0.0); // print date when changes
239 0 : casacore::Int lastScan(-2), lastField(-2), lastCaldesc(-1), lastInt(-1);
240 0 : casacore::Int rowTotal(1);
241 0 : delete iter;
242 0 : delete buff;
243 0 : for (uInt i=0; i<obs.size(); ++i) {
244 0 : Int thisobs = obs(i);
245 : // print heading for each obs id
246 0 : if (thisobs != lastobs) {
247 0 : lastobs = thisobs;
248 0 : lastday = 0.0; // force printing date
249 0 : os << endl << " ObservationID = " << thisobs << endl;
250 0 : os << LogIO::POST;
251 : // print header for output columns
252 0 : casacore::String datetime = " Date Time ( ";
253 : // variable-len timeref string
254 0 : datetime.replace(20,timeref.length(),timeref);
255 0 : datetime.replace(20+timeref.length(),1,")");
256 0 : os << datetime;
257 0 : os << " Scan FldId FieldName nRows ";
258 0 : os << "SpwIds Interval" << endl;
259 0 : os << LogIO::POST;
260 0 : }
261 :
262 : // get values for this iteration
263 0 : Double time = times(i);
264 0 : casacore::Double day = floor(MVTime(time/C::day).day());
265 0 : casacore::Int scan = scans(i);
266 0 : casacore::Int fieldid = fieldIds(i);
267 0 : casacore::Int caldescid = calDescIds(i);
268 0 : casacore::Int interval = intervals(i);
269 :
270 0 : bool lastrow = (i==obs.size()-1);
271 : // print line when something changes and at end
272 0 : if ((time!=lastTime) || (scan!=lastScan) || (fieldid!=lastField) ||
273 0 : (caldescid!=lastCaldesc) || (interval!=lastInt) || lastrow) {
274 0 : if (rowTotal>1) { // but not first row
275 0 : os.output().precision(3);
276 0 : os.output().setf(ios::right, ios::adjustfield);
277 0 : os.output().width(width_lead); os << " ";
278 : // Timerange beginning time
279 0 : os.output().width(width_time);
280 0 : if (day!=lastday) { // print date
281 0 : os << MVTime(lastTime/C::day).string(MVTime::DMY,7);
282 : } else { // omit date
283 0 : os << MVTime(lastTime/C::day).string(MVTime::TIME,7);
284 : }
285 : // Scan
286 0 : os.output().width(width_lead); os << " ";
287 0 : os.output().setf(ios::right, ios::adjustfield);
288 0 : os.output().width(width_scan);
289 0 : os << lastScan;
290 : // FldId
291 0 : os.output().width(width_lead); os << " ";
292 0 : os.output().setf(ios::right, ios::adjustfield);
293 0 : os.output().width(width_fieldId);
294 0 : casacore::String fieldname("");
295 0 : os << lastField << " ";
296 0 : if (lastField >= 0 && !fieldnames.empty())
297 0 : fieldname = fieldnames(lastField);
298 : // FieldName
299 0 : os.output().setf(ios::left, ios::adjustfield);
300 0 : if (fieldname.length()>20)
301 0 : fieldname.replace(19,1,'*');
302 0 : os.output().width(width_fieldname);
303 0 : os << fieldname.at(0,20);
304 : // nRows
305 0 : os.output().width(width_nrow);
306 0 : os.output().setf(ios::left, ios::adjustfield);
307 0 : if (!lastrow) --rowTotal;
308 0 : os << rowTotal;
309 : // SpwIds
310 0 : os.output().width(width_lead); os << " ";
311 0 : Slicer spwSlicer = Slicer(Slice(), Slice(lastCaldesc));
312 0 : casacore::Vector<casacore::Int> spws = spwids(spwSlicer);
313 0 : os << spws;
314 : // Interval
315 0 : os.output().width(width_lead); os << " ";
316 0 : os << " " << interval;
317 0 : os << endl;
318 0 : os << LogIO::POST;
319 :
320 0 : lastday = day; // next lastday is this day
321 0 : rowTotal = 1; // restart counter
322 0 : }
323 0 : lastTime = time;
324 0 : lastScan = scan;
325 0 : lastField = fieldid;
326 0 : lastCaldesc = caldescid;
327 0 : lastInt = interval;
328 : }
329 0 : ++rowTotal;
330 : }
331 0 : os << LogIO::POST;
332 0 : }
333 0 : clearFormatFlags(os);
334 0 : }
335 :
336 0 : void CalSummary::listAntenna (LogIO& os, Bool verbose) const
337 : {
338 : // Get unique antenna ids present in the main table
339 0 : ROCalMainColumns ctmain(*pCT);
340 0 : std::vector<casacore::Int> ant1col = ctmain.antenna1().getColumn().tovector();
341 0 : std::set<casacore::Int> antIds = std::set<casacore::Int>(ant1col.begin(), ant1col.end());
342 0 : uInt nAnt = antIds.size();
343 0 : os << "Antennas: " << nAnt << endl;
344 :
345 : // Antenna info from MS
346 0 : casacore::Vector<casacore::String> antnames, stations;
347 0 : if (!haveMS_p) {
348 0 : os << "MS is not available for detailed antenna listing" << LogIO::POST;
349 : } else {
350 0 : MSMetaInfoForCal msmeta(msname_p);
351 0 : msmeta.antennaNames(antnames);
352 0 : stations = casacore::Vector<casacore::String>(msmeta.msmd().getAntennaStations());
353 :
354 0 : if (verbose) {
355 : // Detailed antenna list
356 0 : casacore::String indent(" ");
357 0 : casacore::uInt indwidth(5),
358 0 : namewidth(6),
359 0 : statwidth(10),
360 0 : diamwidth(5),
361 0 : latwidth(13),
362 0 : longwidth(14),
363 0 : offsetwidth(14),
364 0 : positionwidth(17);
365 0 : casacore::Int diamprec(1);
366 :
367 : // Antenna info from MS
368 0 : MSMetaInfoForCal msmeta(msname_p);
369 0 : QVector<Double> diameters = msmeta.msmd().getAntennaDiameters();
370 0 : vector<MPosition> positions = msmeta.msmd().getAntennaPositions();
371 0 : vector<QVector<Double> > offsets = msmeta.msmd().getAntennaOffsets();
372 0 : Bool posIsITRF = (positions[0].getRef().getType() == MPosition::ITRF);
373 :
374 : // Get observatory position info for antenna offsets
375 : // *not read from antenna table OFFSET column!*
376 0 : casacore::MPosition obsPos;
377 0 : casacore::String telname;
378 0 : bool doOffset = getObservatoryPosition(obsPos, telname);
379 0 : casacore::Double rObs = 0.0, longObs = 0.0, latObs = 0.0;
380 0 : if (!doOffset) {
381 0 : os << "Warning: Telescope name '" << telname << "' is not recognized by CASA. Cannot compute offsets." << endl << endl;
382 : } else {
383 0 : casacore::Vector<casacore::Double> obsXYZ = obsPos.get("m").getValue();
384 0 : casacore::Double xo(obsXYZ[0]), yo(obsXYZ[1]), zo(obsXYZ[2]);
385 0 : rObs = sqrt(xo*xo + yo*yo + zo*zo);
386 0 : casacore::Vector<casacore::Double> obsLongLat = obsPos.getAngle("rad").getValue();
387 0 : longObs = obsLongLat[0];
388 0 : latObs = obsLongLat[1];
389 0 : }
390 :
391 0 : os.output().setf(ios::fixed, ios::floatfield);
392 0 : os.output().setf(ios::left, ios::adjustfield);
393 : // Write the column headings:
394 0 : os << indent;
395 0 : os.output().width(indwidth); os << "ID";
396 0 : os.output().width(namewidth); os << "Name";
397 0 : os.output().width(statwidth); os << "Station";
398 0 : os.output().width(diamwidth+4); os << "Diam.";
399 0 : os.output().width(longwidth); os << "Long.";
400 0 : os.output().width(latwidth); os << "Lat.";
401 0 : if (doOffset) {
402 0 : os.output().width(3 * offsetwidth);
403 0 : os << " Offset from array center (m)";
404 : }
405 0 : os.output().width(3 * positionwidth);
406 0 : os << " ITRF Geocentric coordinates (m)";
407 0 : os << endl << indent;
408 0 : os.output().width(indwidth + namewidth + statwidth + diamwidth + 4 + longwidth + latwidth);
409 0 : os << " ";
410 0 : os.output().setf(ios::right, ios::adjustfield);
411 0 : if (doOffset) {
412 0 : os.output().width(offsetwidth); os << "East";
413 0 : os.output().width(offsetwidth); os << "North";
414 0 : os.output().width(offsetwidth); os << "Elevation";
415 : }
416 0 : os.output().width(positionwidth); os << "x";
417 0 : os.output().width(positionwidth); os << "y";
418 0 : os.output().width(positionwidth); os << "z";
419 0 : os << endl;
420 : // Iterator through antennas and log info for each
421 0 : const static Unit diamUnit("m");
422 0 : std::set<Int>::const_iterator iter = antIds.begin();
423 0 : std::set<Int>::const_iterator end = antIds.end();
424 0 : for (; iter!=end; ++iter) {
425 0 : Int antId = *iter;
426 : // diameter
427 0 : const Quantity& diam = diameters[antId];
428 : // xyz
429 0 : casacore::Vector<casacore::Double> xyz = positions[antId].get("m").getValue();
430 0 : casacore::Double x = xyz(0);
431 0 : casacore::Double y = xyz(1);
432 0 : casacore::Double z = xyz(2);
433 0 : casacore::Double rAnt = sqrt(x*x + y*y + z*z);
434 : // offsets
435 0 : const MPosition& mLongLat = positions[antId];
436 0 : casacore::Vector<casacore::Double> antOffset;
437 0 : if (doOffset) {
438 0 : casacore::Vector<casacore::Double> longLatRad = mLongLat.getAngle("rad").getValue();
439 0 : casacore::Double longAnt = longLatRad(0);
440 0 : casacore::Double latAnt = longLatRad(1);
441 0 : casacore::Vector<casacore::Double> offset(3);
442 0 : offset[0] = (longAnt - longObs) * rObs * cos(latObs);
443 0 : offset[1] = (latAnt - latObs) * rObs;
444 0 : offset[2] = rAnt - rObs;
445 0 : casacore::QVD qoffset(offset, "m");
446 0 : antOffset = qoffset.getValue("m");
447 0 : }
448 : // lat/long
449 0 : MVAngle mvLong = mLongLat.getAngle().getValue()(0);
450 0 : MVAngle mvLat = mLongLat.getAngle().getValue()(1);
451 0 : if (!posIsITRF) {
452 0 : MeasConvert<MPosition> toItrf(positions[antId], MPosition::ITRF);
453 0 : positions[antId] = toItrf(positions[antId]);
454 0 : }
455 : // write the row
456 0 : os.output().setf(ios::left, ios::adjustfield);
457 0 : os << indent;
458 : // ID, Name, Station
459 0 : os.output().width(indwidth); os << antId;
460 0 : os.output().width(namewidth); os << antnames(antId);
461 0 : os.output().width(statwidth); os << stations(antId);
462 : // Diam.
463 0 : os.output().precision(diamprec);
464 0 : os.output().width(diamwidth);
465 0 : os << diam.getValue(diamUnit) << "m ";
466 : // Long. and Lat.
467 0 : os.output().width(longwidth);
468 0 : os << mvLong.string(MVAngle::ANGLE,7);
469 0 : os.output().width(latwidth);
470 0 : os << mvLat.string(MVAngle::DIG2,7);
471 0 : if (doOffset) {
472 : // Offset from array center (m) (East, North, Elevation)
473 0 : os.output().setf(ios::right, ios::adjustfield);
474 0 : os.output().precision(4);
475 0 : os.output().width(offsetwidth); os << antOffset(0);
476 0 : os.output().width(offsetwidth); os << antOffset(1);
477 0 : os.output().width(offsetwidth); os << antOffset(2);
478 : }
479 : // ITRF Geocentric coordinates (m) (x, y, z)
480 0 : os.output().precision(6);
481 0 : os.output().width(positionwidth); os << x;
482 0 : os.output().width(positionwidth); os << y;
483 0 : os.output().width(positionwidth); os << z;
484 0 : os << endl;
485 0 : }
486 0 : } else {
487 : // Horizontal list of the stations names:
488 0 : os << " ('name'@'station') " << endl;
489 0 : casacore::String line, leader;
490 : // track last id of previous line for leader
491 0 : casacore::Int lastIdInLine = *antIds.begin() - 1;
492 0 : std::set<casacore::Int>::const_iterator iter = antIds.begin();
493 0 : std::set<casacore::Int>::const_iterator end = antIds.end();
494 0 : casacore::Int maxAnt = *std::max_element(antIds.begin(), antIds.end());
495 0 : for (; iter!=end; ++iter) {
496 0 : Int antId = *iter;
497 : // Build the line
498 0 : if (!antnames.empty())
499 0 : line = line + "'" + antnames(antId) + "'" + "@";
500 0 : if (!stations.empty())
501 0 : line = line + "'" + stations(antId) + "'";
502 : // Add comma if not at the end
503 0 : if (antId != maxAnt) line = line + ", ";
504 0 : if (line.length() > 55 || antId == maxAnt) {
505 : // This line is finished, dump it after the line leader
506 0 : leader = String::toString(lastIdInLine+1) + "-" + String::toString(antId) +": ";
507 0 : os << " ID=";
508 0 : os.output().setf(ios::right, ios::adjustfield);
509 0 : os.output().width(8); os << leader;
510 0 : os << line << endl;
511 0 : line = "";
512 0 : lastIdInLine = antId;
513 : }
514 : }
515 0 : }
516 0 : }
517 0 : os << LogIO::POST;
518 0 : clearFormatFlags(os);
519 0 : }
520 :
521 0 : bool CalSummary::getObservatoryPosition(casacore::MPosition& obspos,
522 : casacore::String& name) const {
523 : // Returns observatory position in ITRF
524 0 : bool obsposOk(false);
525 0 : MSMetaInfoForCal msmeta(msname_p);
526 : // get telescope name
527 0 : name = msmeta.msmd().getObservatoryNames()[0];
528 0 : obsposOk = MeasTable::Observatory(obspos, name);
529 0 : if (obsposOk && (obspos.getRef().getType() != MPosition::ITRF)) {
530 0 : MeasConvert<MPosition> toItrf(obspos, MPosition::ITRF);
531 0 : obspos = toItrf(obspos);
532 0 : }
533 0 : return obsposOk;
534 0 : }
535 :
536 0 : void CalSummary::listField (LogIO& os, Bool /*verbose*/) const
537 : {
538 : // Get unique field ids present in the main table
539 0 : ROCalMainColumns ctmain(*pCT);
540 0 : std::vector<casacore::Int> fieldcol = ctmain.fieldId().getColumn().tovector();
541 0 : std::set<casacore::Int> fieldIds = std::set<casacore::Int>(fieldcol.begin(), fieldcol.end());
542 0 : uInt nfield = fieldIds.size();
543 :
544 0 : os << "Fields: " << nfield << endl;
545 0 : if (!haveMS_p)
546 0 : os << "MS is not available for detailed field listing" << LogIO::POST;
547 : else {
548 0 : casacore::Int widthLead(2),
549 0 : widthField(6),
550 0 : widthCode(5),
551 0 : widthName(20),
552 0 : widthRA(16),
553 0 : widthDec(16),
554 0 : widthType(8),
555 0 : widthSrc(6);
556 :
557 : // Print heading
558 0 : os.output().setf(ios::left, ios::adjustfield);
559 0 : os.output().width(widthLead); os << " ";
560 0 : os.output().width(widthField); os << "FldId";
561 0 : if (haveMS_p) {
562 0 : os.output().width(widthCode); os << "Code";
563 0 : os.output().width(widthName); os << "Name";
564 0 : os.output().width(widthRA); os << "RA";
565 0 : os.output().width(widthDec); os << " Decl";
566 0 : os.output().width(widthType); os << "Epoch";
567 0 : os.output().width(widthSrc); os << "SrcId";
568 : }
569 0 : os << endl;
570 :
571 : // get values from MS
572 0 : casacore::Vector<casacore::String> fieldNames, codes;
573 0 : vector<MDirection> phaseDirs;
574 0 : vector<Int> sourceIds;
575 0 : if (haveMS_p) {
576 0 : MSMetaInfoForCal msmeta(msname_p);
577 0 : msmeta.fieldNames(fieldNames);
578 0 : codes = casacore::Vector<casacore::String>(msmeta.msmd().getFieldCodes());
579 0 : phaseDirs = msmeta.msmd().getPhaseDirs();
580 0 : sourceIds = msmeta.msmd().getFieldTableSourceIDs();
581 0 : }
582 :
583 : // loop through fields
584 0 : std::set<Int>::const_iterator fiter = fieldIds.begin();
585 0 : std::set<Int>::const_iterator fend = fieldIds.end();
586 0 : static const MEpoch ezero(Quantity(0, "s"));
587 0 : for (; fiter!=fend; ++fiter) {
588 0 : Int fieldId = *fiter;
589 0 : if (fieldId >=0) {
590 0 : os.output().setf(ios::left, ios::adjustfield);
591 0 : os.output().width(widthLead); os << " ";
592 0 : os.output().width(widthField); os << fieldId;
593 0 : if (haveMS_p) {
594 0 : casacore::MDirection mRaDec = phaseDirs[fieldId];
595 0 : MVAngle mvRa = mRaDec.getAngle().getValue()(0);
596 0 : MVAngle mvDec = mRaDec.getAngle().getValue()(1);
597 0 : String name = fieldNames(fieldId);
598 0 : if (name.length()>20)
599 0 : name.replace(19,1,"*");
600 0 : os.output().width(widthCode); os << codes(fieldId);
601 0 : os.output().width(widthName); os << name.at(0,20);
602 0 : os.output().width(widthRA); os << mvRa(0.0).string(MVAngle::TIME,12);
603 0 : os.output().width(widthDec); os << mvDec.string(MVAngle::DIG2,11);
604 0 : os.output().width(widthType);
605 0 : os << MDirection::showType(mRaDec.getRefPtr()->getType());
606 0 : os.output().width(widthSrc); os << sourceIds[fieldId];
607 0 : }
608 0 : os << endl;
609 : } else {
610 0 : os.output().setf(ios::left, ios::adjustfield);
611 0 : os.output().width(widthLead); os << " ";
612 0 : os.output().width(widthField); os << fieldId;
613 0 : os << endl;
614 : }
615 : }
616 0 : os << LogIO::POST;
617 0 : }
618 0 : clearFormatFlags(os);
619 0 : }
620 :
621 0 : void CalSummary::listObservation (LogIO& os, Bool /*verbose*/) const
622 : {
623 : // Get unique obs ids present in the main table
624 0 : ROCalMainColumns ctmain(*pCT);
625 0 : std::vector<casacore::Int> obscol = ctmain.obsId().getColumn().tovector();
626 0 : std::set<casacore::Int> obsIds = std::set<casacore::Int>(obscol.begin(), obscol.end());
627 0 : os << "Observation IDs in main table: " << obsIds << endl;
628 :
629 0 : Int nrow = pCT->nRowObservation();
630 0 : if (nrow <= 0) {
631 0 : os << "The OBSERVATION table is empty";
632 : } else {
633 0 : os << "Observation table entries: " << nrow << LogIO::POST;
634 0 : for (Int irow=0 ; irow < nrow; irow++) {
635 0 : Record obsRow = pCT->getRowObservation(irow);
636 0 : String observer = obsRow.asString("OBSERVER");
637 0 : if (!observer.empty())
638 0 : os << " Observer: " << observer;
639 0 : String project = obsRow.asString("PROJECT");
640 0 : if (!project.empty())
641 0 : os << " Project: " << project;
642 0 : String telescope = obsRow.asString("TELESCOPE_NAME");
643 0 : if (!telescope.empty())
644 0 : os << " Telescope: " << telescope;
645 : // TIME_RANGE values don't match main table or ms!
646 0 : }
647 : }
648 0 : os << LogIO::POST;
649 0 : clearFormatFlags(os);
650 0 : }
651 :
652 0 : void CalSummary::listHistory (LogIO& os) const
653 : {
654 0 : Int nrow = pCT->nRowHistory();
655 0 : if (nrow <= 0) {
656 0 : os << "The HISTORY table is empty" << endl;
657 : } else {
658 0 : os << "History table entries: " << nrow << endl << LogIO::POST;
659 0 : for (Int irow=0 ; irow < nrow; irow++) {
660 0 : Record histRow = pCT->getRowHistory(irow);
661 0 : os << "ROW " << irow << " ";
662 0 : os << "PARMS: " << histRow.asString("CAL_PARMS") << endl;
663 0 : os << "TABLES: " << histRow.asString("CAL_TABLES") << endl;
664 0 : os << "SELECT: " << histRow.asString("CAL_SELECT") << endl;
665 0 : os << "NOTES: " << histRow.asString("CAL_NOTES") << endl;
666 0 : }
667 : }
668 0 : os << LogIO::POST;
669 0 : }
670 :
671 0 : void CalSummary::listSpectralWindow (LogIO& os, Bool /*verbose*/) const
672 : {
673 0 : ROCalDescColumns ctdesc(*pCT);
674 0 : casacore::Array<casacore::Int> spwIdArray = ctdesc.spwId().getColumn();
675 0 : IPosition vshape(1, spwIdArray.nelements());
676 0 : casacore::Vector<casacore::Int> spwIds(spwIdArray.reform(vshape));
677 0 : Int nSpws = GenSort<Int>::sort(spwIds, Sort::Ascending, Sort::NoDuplicates);
678 0 : spwIds.resize(nSpws, true);
679 0 : os << "Spectral Windows: " << nSpws;
680 0 : Bool noSpws = (nSpws==1 && spwIds(0)==-1);
681 0 : if (noSpws)
682 0 : os << " " << spwIds;
683 0 : os << endl;
684 :
685 0 : if (!noSpws) {
686 0 : if (haveMS_p) {
687 0 : MSMetaInfoForCal msmeta(msname_p);
688 0 : vector<MFrequency> refFreqs = msmeta.msmd().getRefFreqs();
689 0 : vector<uInt> nChans = msmeta.msmd().nChans();
690 0 : vector<Double> totalBWs = msmeta.msmd().getBandWidths();
691 0 : vector<QVD> resolution = msmeta.msmd().getChanResolutions(False);
692 :
693 : // Header: SpwId Ref.Freq #Chans Resolution TotalBW
694 0 : casacore::Int widthLead(2), widthId(7), widthFreq(13), widthFrqNum(7), widthNumChan(8);
695 0 : os.output().setf(ios::left, ios::adjustfield);
696 0 : os.output().width(widthLead); os << " ";
697 0 : os.output().width(widthId); os << "SpwId";
698 0 : os.output().width(widthFreq); os << "Ref.Freq";
699 0 : os.output().width(widthNumChan); os << "#Chans";
700 0 : os.output().width(widthFreq); os << "Resolution";
701 0 : os.output().width(widthFreq); os << "TotalBW";
702 0 : os << endl;
703 :
704 0 : for (Int ispw=0; ispw<nSpws; ispw++) {
705 0 : Int spwId = spwIds(ispw);
706 0 : os.output().setf(ios::left, ios::adjustfield);
707 0 : os.output().width(widthLead); os << " ";
708 0 : os.output().width(widthId); os << spwId;
709 0 : if (spwId >= 0) {
710 0 : os.output().width(widthFrqNum);
711 0 : os << refFreqs[spwId].get("MHz"); // MFreqency
712 0 : os.output().width(widthLead); os << " ";
713 0 : os.output().width(widthNumChan);
714 0 : os << nChans[spwId];
715 0 : os.output().width(widthFrqNum);
716 0 : os << resolution[spwId][0].get("kHz"); // QVD
717 0 : os.output().width(widthLead); os << " ";
718 0 : os.output().width(widthLead); os << " ";
719 0 : os.output().width(widthFrqNum);
720 0 : os << totalBWs[spwId] / 1000.0; // convert Hz to kHz
721 0 : os << " kHz";
722 0 : os << endl;
723 : }
724 : }
725 0 : } else {
726 0 : os << "MS is not available for detailed spw listing" << endl;
727 : }
728 : }
729 0 : os << LogIO::POST;
730 0 : clearFormatFlags(os);
731 0 : }
732 :
733 0 : void CalSummary::listTables (LogIO& os, Bool verbose) const
734 : {
735 : // Get nrows for each table (=-1 if table absent)
736 0 : uInt nTables = 4;
737 0 : casacore::Vector<casacore::Int> tableRows(nTables);
738 0 : tableRows(0) = pCT->nRowMain();
739 0 : tableRows(1) = pCT->nRowDesc();
740 0 : tableRows(2) = pCT->nRowHistory();
741 0 : tableRows(3) = pCT->nRowObservation();
742 :
743 0 : casacore::Vector<casacore::String> tableStrings(nTables);
744 0 : tableStrings(0) = "MAIN";
745 0 : tableStrings(1) = "CAL_DESC";
746 0 : tableStrings(2) = "CAL_HISTORY";
747 0 : tableStrings(3) = "OBSERVATION";
748 :
749 : // Just to make things read better
750 0 : casacore::Vector<casacore::String> rowStrings(6);
751 0 : rowStrings = " rows";
752 0 : for (uInt i=0; i<nTables; i++) {
753 0 : if (tableRows(i)==1) rowStrings(i) = " row";
754 : // if table exists, but empty:
755 0 : if (tableRows(i)==0) rowStrings(i) = " <empty>";
756 : // if table absent:
757 0 : if (tableRows(i)==-1) rowStrings(i) = "<absent>";
758 : }
759 :
760 0 : if (verbose) {
761 0 : os << " Tables" << endl;
762 0 : for (uInt i=0; i<nTables; i++) {
763 0 : os.output().setf(ios::left, ios::adjustfield);
764 0 : os.output().width(3); os << " ";
765 0 : os.output().width(20); os << tableStrings(i);
766 0 : os.output().setf(ios::right, ios::adjustfield);
767 0 : os.output().width(8); os << tableRows(i);
768 0 : os.output().setf(ios::left, ios::adjustfield);
769 0 : os.output().width(10); os << rowStrings(i);
770 0 : os << endl;
771 : }
772 : } else {
773 0 : os << " Tables (rows): (-1 = table absent)" << endl;
774 0 : for (uInt i=0; i<nTables; i++) {
775 0 : casacore::String tableinfo = tableStrings(i) + " (" +
776 0 : casacore::String::toString(tableRows(i)) + ")";
777 0 : os.output().setf(ios::left, ios::adjustfield);
778 0 : casacore::Int infowidth = 15;
779 0 : if (i==1 || i==4) infowidth = 25;
780 0 : os.output().width(infowidth);
781 0 : os << tableinfo;
782 0 : if ((i+1) % 3==0) os << endl;
783 0 : }
784 : }
785 0 : os << LogIO::POST;
786 0 : clearFormatFlags(os);
787 0 : }
788 :
789 : //
790 : // Clear all the formatting flags
791 : //
792 0 : void CalSummary::clearFormatFlags(LogIO& os) const
793 : {
794 0 : os.output().unsetf(ios::left);
795 0 : os.output().unsetf(ios::right);
796 0 : os.output().unsetf(ios::internal);
797 :
798 0 : os.output().unsetf(ios::dec);
799 0 : os.output().unsetf(ios::oct);
800 0 : os.output().unsetf(ios::hex);
801 :
802 0 : os.output().unsetf(ios::showbase | ios::showpos | ios::uppercase | ios::showpoint);
803 :
804 0 : os.output().unsetf(ios::scientific);
805 0 : os.output().unsetf(ios::fixed);
806 0 : }
807 :
808 : } //# NAMESPACE CASA - END
809 :
|