source: branches/alma/external/atnf/PKSIO/PKSMS2writer.cc@ 1430

Last change on this file since 1430 was 1393, checked in by TakTsutsumi, 17 years ago

Changes to handle GBT MS data

File size: 35.7 KB
Line 
1//#---------------------------------------------------------------------------
2//# PKSMS2writer.cc: Class to write Parkes multibeam data to a measurementset.
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2000-2006
5//# Associated Universities, Inc. Washington DC, USA.
6//#
7//# This library is free software; you can redistribute it and/or modify it
8//# under the terms of the GNU Library General Public License as published by
9//# the Free Software Foundation; either version 2 of the License, or (at your
10//# option) any later version.
11//#
12//# This library is distributed in the hope that it will be useful, but
13//# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14//# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15//# License for more details.
16//#
17//# You should have received a copy of the GNU Library General Public License
18//# along with this library; if not, write to the Free Software Foundation,
19//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20//#
21//# Correspondence concerning AIPS++ should be addressed as follows:
22//# Internet email: aips2-request@nrao.edu.
23//# Postal address: AIPS++ Project Office
24//# National Radio Astronomy Observatory
25//# 520 Edgemont Road
26//# Charlottesville, VA 22903-2475 USA
27//#
28//# $Id: PKSMS2writer.cc,v 19.11 2006/11/06 22:25:22 mmarquar Exp $
29//#---------------------------------------------------------------------------
30
31#include <atnf/PKSIO/PKSMS2writer.h>
32
33#include <casa/Arrays/ArrayUtil.h>
34#include <casa/Arrays/ArrayMath.h>
35#include <casa/Arrays/ArrayLogical.h>
36#include <casa/Arrays/Cube.h>
37#include <casa/BasicSL/Complex.h>
38#include <casa/BasicSL/Constants.h>
39#include <casa/Quanta/QC.h>
40#include <casa/Logging/LogIO.h>
41#include <measures/Measures/Stokes.h>
42#include <tables/Tables/ArrColDesc.h>
43#include <tables/Tables/IncrementalStMan.h>
44#include <tables/Tables/ScaColDesc.h>
45#include <tables/Tables/SetupNewTab.h>
46#include <tables/Tables/StandardStMan.h>
47#include <tables/Tables/Table.h>
48#include <tables/Tables/TableDesc.h>
49#include <tables/Tables/TiledShapeStMan.h>
50
51//------------------------------------------------- PKSMS2writer::PKSMS2writer
52
53// Default constructor.
54
55PKSMS2writer::PKSMS2writer()
56{
57}
58
59//------------------------------------------------ PKSMS2writer::~PKSMS2writer
60
61// Destructor.
62
63PKSMS2writer::~PKSMS2writer()
64{
65 close();
66}
67
68//------------------------------------------------------- PKSMS2writer::create
69
70// Create the output MS and and write static data.
71
72Int PKSMS2writer::create(
73 const String msName,
74 const String observer,
75 const String project,
76 const String antName,
77 const Vector<Double> antPosition,
78 const String obsMode,
79 const Float equinox,
80 const String dopplerFrame,
81 const Vector<uInt> nChan,
82 const Vector<uInt> nPol,
83 const Vector<Bool> haveXPol,
84 const Bool haveBase,
85 const String fluxUnit)
86{
87 // Open a MS table.
88 TableDesc pksDesc = MS::requiredTableDesc();
89
90 cNChan.assign(nChan);
91 cNPol.assign(nPol);
92 cHaveXPol.assign(haveXPol);
93
94 Int maxNPol = max(cNPol);
95
96 // check if it is GBT data
97 cGBT = antName.contains("GBT");
98
99 // Add the non-standard CALFCTR column.
100 pksDesc.addColumn(ArrayColumnDesc<Float>("CALFCTR", "Calibration factors",
101 IPosition(1,maxNPol), ColumnDesc::Direct));
102
103 // Add the optional FLOAT_DATA column.
104 MS::addColumnToDesc(pksDesc, MS::FLOAT_DATA, 2);
105 //pksDesc.rwColumnDesc(MS::columnName(MS::FLOAT_DATA)).rwKeywordSet().
106 // define("UNIT", String("Jy"));
107 pksDesc.rwColumnDesc(MS::columnName(MS::FLOAT_DATA)).rwKeywordSet().
108 define("UNIT", fluxUnit);
109 pksDesc.rwColumnDesc(MS::columnName(MS::FLOAT_DATA)).rwKeywordSet().
110 define("MEASURE_TYPE", "");
111
112 if ((cHaveBase = haveBase)) {
113 // Add the non-standard BASELIN and BASESUB columns.
114 pksDesc.addColumn(ArrayColumnDesc<Float>("BASELIN", "Linear baseline fit",
115 IPosition(2,2,maxNPol), ColumnDesc::Direct));
116 pksDesc.addColumn(ArrayColumnDesc<Float>("BASESUB", "Baseline subtracted",
117 IPosition(2,9,maxNPol), ColumnDesc::Direct));
118 }
119
120 // Add the optional DATA column if cross-polarizations are to be recorded.
121 if (ntrue(cHaveXPol)) {
122 // Add the non-standard XCALFCTR column.
123 pksDesc.addColumn(ScalarColumnDesc<Complex>("XCALFCTR",
124 "Cross-polarization calibration factor"));
125
126 MS::addColumnToDesc(pksDesc, MS::DATA, 2);
127 pksDesc.rwColumnDesc(MS::columnName(MS::DATA)).rwKeywordSet().
128 define("UNIT", "Jy");
129 pksDesc.rwColumnDesc(MS::columnName(MS::DATA)).rwKeywordSet().
130 define("MEASURE_TYPE", "");
131 }
132
133 // Define hypercube for the float data (without coordinates).
134 pksDesc.defineHypercolumn("TiledData", 3,
135 stringToVector(MS::columnName(MS::FLOAT_DATA)));
136
137 SetupNewTable newtab(msName, pksDesc, Table::New);
138
139 // Set Incremental Storage Manager as the default.
140 IncrementalStMan incrStMan("ISMData");
141 newtab.bindAll(incrStMan, True);
142
143 // Use TiledShapeStMan for the FLOAT_DATA hypercube with tile size 16 kiB.
144 TiledShapeStMan tiledStMan("TiledData", IPosition(3,1,128,32));
145 newtab.bindColumn(MS::columnName(MS::FLOAT_DATA), tiledStMan);
146
147 // Use Standard Storage Manager to handle columns that change for each row.
148 StandardStMan stdStMan;
149 newtab.bindColumn(MS::columnName(MS::SCAN_NUMBER), stdStMan);
150 newtab.bindColumn(MS::columnName(MS::TIME), stdStMan);
151 newtab.bindColumn(MS::columnName(MS::SIGMA), stdStMan);
152 if (maxNPol > 2) {
153 newtab.bindColumn(MS::columnName(MS::DATA), stdStMan);
154 }
155
156 // Create the measurementset.
157 cPKSMS = new MeasurementSet(newtab, 0);
158
159 // Create subtables.
160 TableDesc antennaDesc = MSAntenna::requiredTableDesc();
161 SetupNewTable antennaSetup(cPKSMS->antennaTableName(), antennaDesc,
162 Table::New);
163 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::ANTENNA),
164 Table(antennaSetup));
165
166 TableDesc dataDescDesc = MSDataDescription::requiredTableDesc();
167 SetupNewTable dataDescSetup(cPKSMS->dataDescriptionTableName(), dataDescDesc,
168 Table::New);
169 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::DATA_DESCRIPTION),
170 Table(dataDescSetup));
171
172 TableDesc dopplerDesc = MSDoppler::requiredTableDesc();
173 SetupNewTable dopplerSetup(cPKSMS->dopplerTableName(), dopplerDesc,
174 Table::New);
175 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::DOPPLER),
176 Table(dopplerSetup));
177
178 TableDesc feedDesc = MSFeed::requiredTableDesc();
179 MSFeed::addColumnToDesc(feedDesc, MSFeedEnums::FOCUS_LENGTH);
180 SetupNewTable feedSetup(cPKSMS->feedTableName(), feedDesc, Table::New);
181 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::FEED),
182 Table(feedSetup));
183
184 TableDesc fieldDesc = MSField::requiredTableDesc();
185 SetupNewTable fieldSetup(cPKSMS->fieldTableName(), fieldDesc, Table::New);
186 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::FIELD),
187 Table(fieldSetup));
188
189 TableDesc flagCmdDesc = MSFlagCmd::requiredTableDesc();
190 SetupNewTable flagCmdSetup(cPKSMS->flagCmdTableName(), flagCmdDesc,
191 Table::New);
192 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::FLAG_CMD),
193 Table(flagCmdSetup));
194
195 TableDesc historyDesc = MSHistory::requiredTableDesc();
196 SetupNewTable historySetup(cPKSMS->historyTableName(), historyDesc,
197 Table::New);
198 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::HISTORY),
199 Table(historySetup));
200
201 TableDesc observationDesc = MSObservation::requiredTableDesc();
202 SetupNewTable observationSetup(cPKSMS->observationTableName(),
203 observationDesc, Table::New);
204 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::OBSERVATION),
205 Table(observationSetup));
206
207 TableDesc pointingDesc = MSPointing::requiredTableDesc();
208 SetupNewTable pointingSetup(cPKSMS->pointingTableName(), pointingDesc,
209 Table::New);
210 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::POINTING),
211 Table(pointingSetup));
212
213 TableDesc polarizationDesc = MSPolarization::requiredTableDesc();
214 SetupNewTable polarizationSetup(cPKSMS->polarizationTableName(),
215 polarizationDesc, Table::New);
216 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::POLARIZATION),
217 Table(polarizationSetup));
218
219 TableDesc processorDesc = MSProcessor::requiredTableDesc();
220 SetupNewTable processorSetup(cPKSMS->processorTableName(), processorDesc,
221 Table::New);
222 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::PROCESSOR),
223 Table(processorSetup));
224
225 TableDesc sourceDesc = MSSource::requiredTableDesc();
226 MSSource::addColumnToDesc(sourceDesc, MSSourceEnums::TRANSITION, 1);
227 MSSource::addColumnToDesc(sourceDesc, MSSourceEnums::REST_FREQUENCY,
228 1);
229 MSSource::addColumnToDesc(sourceDesc, MSSourceEnums::SYSVEL, 1);
230 SetupNewTable sourceSetup(cPKSMS->sourceTableName(), sourceDesc,
231 Table::New);
232 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::SOURCE),
233 Table(sourceSetup));
234
235 TableDesc spectralWindowDesc = MSSpectralWindow::requiredTableDesc();
236 MSSpectralWindow::addColumnToDesc(spectralWindowDesc,
237 MSSpectralWindowEnums::DOPPLER_ID);
238 SetupNewTable spectralWindowSetup(cPKSMS->spectralWindowTableName(),
239 spectralWindowDesc, Table::New);
240 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::SPECTRAL_WINDOW),
241 Table(spectralWindowSetup));
242
243 TableDesc stateDesc = MSState::requiredTableDesc();
244 SetupNewTable stateSetup(cPKSMS->stateTableName(), stateDesc, Table::New);
245 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::STATE),
246 Table(stateSetup));
247
248 TableDesc sysCalDesc = MSSysCal::requiredTableDesc();
249 MSSysCal::addColumnToDesc(sysCalDesc, MSSysCalEnums::TCAL, 1);
250 MSSysCal::addColumnToDesc(sysCalDesc, MSSysCalEnums::TSYS, 1);
251 SetupNewTable sysCalSetup(cPKSMS->sysCalTableName(), sysCalDesc,
252 Table::New);
253 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::SYSCAL),
254 Table(sysCalSetup));
255
256 TableDesc weatherDesc = MSWeather::requiredTableDesc();
257 MSWeather::addColumnToDesc(weatherDesc, MSWeatherEnums::PRESSURE);
258 MSWeather::addColumnToDesc(weatherDesc, MSWeatherEnums::REL_HUMIDITY);
259 MSWeather::addColumnToDesc(weatherDesc, MSWeatherEnums::TEMPERATURE);
260 SetupNewTable weatherSetup(cPKSMS->weatherTableName(), weatherDesc,
261 Table::New);
262 cPKSMS->rwKeywordSet().defineTable(MS::keywordName(MS::WEATHER),
263 Table(weatherSetup));
264
265 cPKSMS->initRefs();
266
267 // Measurementset subtables.
268 cAntenna = cPKSMS->antenna();
269 cDataDescription = cPKSMS->dataDescription();
270 cDoppler = cPKSMS->doppler();
271 cFeed = cPKSMS->feed();
272 cField = cPKSMS->field();
273 cFlagCmd = cPKSMS->flagCmd();
274 cHistory = cPKSMS->history();
275 cObservation = cPKSMS->observation();
276 cPointing = cPKSMS->pointing();
277 cPolarization = cPKSMS->polarization();
278 cProcessor = cPKSMS->processor();
279 cSource = cPKSMS->source();
280 cSpectralWindow = cPKSMS->spectralWindow();
281 cState = cPKSMS->state();
282 cSysCal = cPKSMS->sysCal();
283 cWeather = cPKSMS->weather();
284
285 // Measurementset table columns;
286 cMSCols = new MSColumns(*cPKSMS);
287 cAntennaCols = new MSAntennaColumns(cAntenna);
288 cDataDescCols = new MSDataDescColumns(cDataDescription);
289 cDopplerCols = new MSDopplerColumns(cDoppler);
290 cFeedCols = new MSFeedColumns(cFeed);
291 cFieldCols = new MSFieldColumns(cField);
292 cFlagCmdCols = new MSFlagCmdColumns(cFlagCmd);
293 cHistoryCols = new MSHistoryColumns(cHistory);
294 cObservationCols = new MSObservationColumns(cObservation);
295 cPointingCols = new MSPointingColumns(cPointing);
296 cPolarizationCols = new MSPolarizationColumns(cPolarization);
297 cProcessorCols = new MSProcessorColumns(cProcessor);
298 cSourceCols = new MSSourceColumns(cSource);
299 cSpWindowCols = new MSSpWindowColumns(cSpectralWindow);
300 cStateCols = new MSStateColumns(cState);
301 cSysCalCols = new MSSysCalColumns(cSysCal);
302 cWeatherCols = new MSWeatherColumns(cWeather);
303
304 cCalFctrCol = new ArrayColumn<Float>(*cPKSMS, "CALFCTR");
305 if (cHaveBase) {
306 cBaseLinCol = new ArrayColumn<Float>(*cPKSMS, "BASELIN");
307 cBaseSubCol = new ArrayColumn<Float>(*cPKSMS, "BASESUB");
308 }
309 if (ntrue(cHaveXPol)) {
310 cXCalFctrCol = new ScalarColumn<Complex>(*cPKSMS, "XCALFCTR");
311 }
312
313
314 // Define Measure references.
315 Vector<String> flagCat(1, "BAD");
316 cMSCols->sigma().rwKeywordSet().define("UNIT", "K");
317 cMSCols->flagCategory().rwKeywordSet().define("CATEGORY", flagCat);
318
319 String dirref;
320 if (equinox == 1950.0f) {
321 dirref = "B1950";
322 } else {
323 dirref = "J2000";
324 }
325
326 cFieldCols->delayDir().rwKeywordSet().asrwRecord("MEASINFO").
327 define("Ref", dirref);
328 cFieldCols->phaseDir().rwKeywordSet().asrwRecord("MEASINFO").
329 define("Ref", dirref);
330 cFieldCols->referenceDir().rwKeywordSet().asrwRecord("MEASINFO").
331 define("Ref", dirref);
332
333 cPointingCols->direction().rwKeywordSet().asrwRecord("MEASINFO").
334 define("Ref", dirref);
335 cPointingCols->target().rwKeywordSet().asrwRecord("MEASINFO").
336 define("Ref", dirref);
337
338 cSourceCols->direction().rwKeywordSet().asrwRecord("MEASINFO").
339 define("Ref", dirref);
340 cSourceCols->restFrequency().rwKeywordSet().asrwRecord("MEASINFO").
341 define("Ref", "REST");
342
343 // Translate Doppler frame name.
344 if (dopplerFrame == "TOPOCENT") {
345 MFrequency::getType(cDopplerFrame, "TOPO");
346 } else if (dopplerFrame == "GEOCENTR") {
347 MFrequency::getType(cDopplerFrame, "GEO");
348 } else if (dopplerFrame == "BARYCENT") {
349 MFrequency::getType(cDopplerFrame, "BARY");
350 } else if (dopplerFrame == "GALACTOC") {
351 MFrequency::getType(cDopplerFrame, "GALACTO");
352 } else if (dopplerFrame == "LOCALGRP") {
353 MFrequency::getType(cDopplerFrame, "LGROUP");
354 } else if (dopplerFrame == "CMBDIPOL") {
355 MFrequency::getType(cDopplerFrame, "CMB");
356 } else if (dopplerFrame == "SOURCE") {
357 MFrequency::getType(cDopplerFrame, "REST");
358 } else if (dopplerFrame == "LSRK") {
359 MFrequency::getType(cDopplerFrame, "LSRK");
360 }
361
362
363 // Store static data.
364 addAntennaEntry(antName, antPosition);
365 addDopplerEntry();
366 addFeedEntry();
367 //addObservationEntry(observer, project);
368 addObservationEntry(observer, project, antName);
369 addProcessorEntry();
370
371 return 0;
372}
373
374//-------------------------------------------------------- PKSMS2writer::write
375
376// Write the next data record.
377
378Int PKSMS2writer::write(
379 const Int scanNo,
380 const Int cycleNo,
381 const Double mjd,
382 const Double interval,
383 const String fieldName,
384 const String srcName,
385 const Vector<Double> srcDir,
386 const Vector<Double> srcPM,
387 const Double srcVel,
388 const String obsMode,
389 const Int IFno,
390 const Double refFreq,
391 const Double bandwidth,
392 const Double freqInc,
393 const Double restFreq,
394 const Vector<Float> tcal,
395 const String tcalTime,
396 const Float azimuth,
397 const Float elevation,
398 const Float parAngle,
399 const Float focusAxi,
400 const Float focusTan,
401 const Float focusRot,
402 const Float temperature,
403 const Float pressure,
404 const Float humidity,
405 const Float windSpeed,
406 const Float windAz,
407 const Int refBeam,
408 const Int beamNo,
409 const Vector<Double> direction,
410 const Vector<Double> scanRate,
411 const Vector<Float> tsys,
412 const Vector<Float> sigma,
413 const Vector<Float> calFctr,
414 const Matrix<Float> baseLin,
415 const Matrix<Float> baseSub,
416 const Matrix<Float> &spectra,
417 const Matrix<uChar> &flagged,
418 const Complex xCalFctr,
419 const Vector<Complex> &xPol)
420{
421 // Extend the time range in the OBSERVATION subtable.
422 Vector<Double> timerange(2);
423 cObservationCols->timeRange().get(0, timerange);
424 Double time = mjd*86400.0;
425 if (timerange(0) == 0.0) {
426 timerange(0) = time;
427 }
428 timerange(1) = time;
429 cObservationCols->timeRange().put(0, timerange);
430
431 Int iIF = IFno - 1;
432 Int nChan = cNChan(iIF);
433 Int nPol = cNPol(iIF);
434
435 // IFno is the 1-relative row number in the DATA_DESCRIPTION,
436 // SPECTRAL_WINDOW, and POLARIZATION subtables.
437 if (Int(cDataDescription.nrow()) < IFno) {
438 // Add a new entry to each subtable.
439 addDataDescriptionEntry(IFno);
440 addSpectralWindowEntry(IFno, nChan, refFreq, bandwidth, freqInc);
441 addPolarizationEntry(IFno, nPol);
442 }
443
444 // Find or add the source to the SOURCE subtable.
445 Int srcId = addSourceEntry(srcName, srcDir, srcPM, restFreq, srcVel);
446
447 // Find or add the obsMode to the STATE subtable.
448 Int stateId = addStateEntry(obsMode);
449
450 // FIELD subtable.
451 Int fieldId = addFieldEntry(fieldName, time, direction, scanRate, srcId);
452
453 // POINTING subtable.
454 addPointingEntry(time, interval, fieldName, direction, scanRate);
455
456 // SYSCAL subtable.
457 addSysCalEntry(beamNo, iIF, time, interval, tcal, tsys, nPol);
458
459
460 // Handle weather information.
461 ROScalarColumn<Double> wTime(cWeather, "TIME");
462 Int nWeather = wTime.nrow();
463 if (nWeather == 0 || time > wTime(nWeather-1)) {
464 addWeatherEntry(time, interval, pressure, humidity, temperature);
465 }
466
467
468 // Extend the main table.
469 cPKSMS->addRow();
470 Int irow = cPKSMS->nrow() - 1;
471
472 // Keys.
473 cMSCols->time().put(irow, time);
474 cMSCols->antenna1().put(irow, 0);
475 cMSCols->antenna2().put(irow, 0);
476 cMSCols->feed1().put(irow, beamNo-1);
477 cMSCols->feed2().put(irow, beamNo-1);
478 cMSCols->dataDescId().put(irow, iIF);
479 cMSCols->processorId().put(irow, 0);
480 cMSCols->fieldId().put(irow, fieldId);
481
482 // Non-key attributes.
483 cMSCols->interval().put(irow, interval);
484 cMSCols->exposure().put(irow, interval);
485 cMSCols->timeCentroid().put(irow, time);
486 cMSCols->scanNumber().put(irow, scanNo);
487 cMSCols->arrayId().put(irow, 0);
488 cMSCols->observationId().put(irow, 0);
489 cMSCols->stateId().put(irow, stateId);
490
491 Vector<Double> uvw(3, 0.0);
492 cMSCols->uvw().put(irow, uvw);
493
494 // Baseline fit parameters.
495 if (cHaveBase) {
496 cBaseLinCol->put(irow, baseLin);
497
498 if (baseSub.nrow() == 9) {
499 cBaseSubCol->put(irow, baseSub);
500
501 } else {
502 Matrix<Float> tmp(9, 2, 0.0f);
503 for (Int ipol = 0; ipol < nPol; ipol++) {
504 for (uInt j = 0; j < baseSub.nrow(); j++) {
505 tmp(j,ipol) = baseSub(j,ipol);
506 }
507 }
508 cBaseSubCol->put(irow, tmp);
509 }
510 }
511 // Transpose spectra.
512 Matrix<Float> tmpData(nPol, nChan);
513 Matrix<Bool> tmpFlag(nPol, nChan);
514 for (Int ipol = 0; ipol < nPol; ipol++) {
515 for (Int ichan = 0; ichan < nChan; ichan++) {
516 tmpData(ipol,ichan) = spectra(ichan,ipol);
517 tmpFlag(ipol,ichan) = flagged(ichan,ipol);
518 }
519 }
520 cCalFctrCol->put(irow, calFctr);
521 cMSCols->floatData().put(irow, tmpData);
522 cMSCols->flag().put(irow, tmpFlag);
523
524 // Cross-polarization spectra.
525 if (cHaveXPol(iIF)) {
526 cXCalFctrCol->put(irow, xCalFctr);
527 cMSCols->data().put(irow, xPol);
528 }
529
530 cMSCols->sigma().put(irow, sigma);
531
532 //Vector<Float> weight(1, 1.0f);
533 Vector<Float> weight(nPol, 1.0f);
534 cMSCols->weight().put(irow, weight);
535
536 // Flag information.
537 Cube<Bool> flags(nPol, nChan, 1, False);
538 //cMSCols->flag().put(irow, flags.xyPlane(0));
539 cMSCols->flagCategory().put(irow, flags);
540 cMSCols->flagRow().put(irow, False);
541
542 return 0;
543}
544
545//-------------------------------------------------------- PKSMS2writer::close
546
547// Close the measurementset, flushing all associated tables.
548
549void PKSMS2writer::close()
550{
551 // Delete table column accessors.
552 delete cMSCols; cMSCols=0;
553 delete cAntennaCols; cAntennaCols=0;
554 delete cDataDescCols; cDataDescCols=0;
555 delete cDopplerCols; cDopplerCols=0;
556 delete cFeedCols; cFeedCols=0;
557 delete cFieldCols; cFieldCols=0;
558 delete cFlagCmdCols; cFlagCmdCols=0;
559 delete cHistoryCols; cHistoryCols=0;
560 delete cObservationCols; cObservationCols=0;
561 delete cPointingCols; cPointingCols=0;
562 delete cPolarizationCols; cPolarizationCols=0;
563 delete cProcessorCols; cProcessorCols=0;
564 delete cSourceCols; cSourceCols=0;
565 delete cSpWindowCols; cSpWindowCols=0;
566 delete cStateCols; cStateCols=0;
567 delete cSysCalCols; cSysCalCols=0;
568 delete cWeatherCols; cWeatherCols=0;
569
570 delete cCalFctrCol; cCalFctrCol=0;
571 if (cHaveBase) {
572 delete cBaseLinCol; cBaseLinCol=0;
573 delete cBaseSubCol; cBaseSubCol=0;
574 }
575 if (ntrue(cHaveXPol)) {
576 delete cXCalFctrCol; cXCalFctrCol=0;
577 }
578
579 // Release all subtables.
580 cAntenna = MSAntenna();
581 cDataDescription = MSDataDescription();
582 cDoppler = MSDoppler();
583 cFeed = MSFeed();
584 cField = MSField();
585 cFlagCmd = MSFlagCmd();
586 cHistory = MSHistory();
587 cObservation = MSObservation();
588 cPointing = MSPointing();
589 cPolarization = MSPolarization();
590 cProcessor = MSProcessor();
591 cSource = MSSource();
592 cSpectralWindow = MSSpectralWindow();
593 cState = MSState();
594 cSysCal = MSSysCal();
595 cWeather = MSWeather();
596 // Release the main table.
597 delete cPKSMS; cPKSMS=0;
598}
599
600//---------------------------------------------- PKSMS2writer::addAntennaEntry
601
602// Add an entry to the ANTENNA subtable.
603
604Int PKSMS2writer::addAntennaEntry(
605 const String antName,
606 const Vector<Double> &antPosition)
607{
608 // Extend the ANTENNA subtable.
609 cAntenna.addRow();
610 Int n = cAntenna.nrow() - 1;
611
612 // do specific things for GBT
613 // Data.
614 cAntennaCols->name().put(n, antName);
615 //cAntennaCols->station().put(n, "ATNF_PARKES");
616 if (cGBT) {
617 cAntennaCols->station().put(n, "GREENBANK");
618 }
619 else {
620 cAntennaCols->station().put(n, "ATNF_PARKES");
621 }
622 cAntennaCols->type().put(n, "GROUND-BASED");
623 cAntennaCols->mount().put(n, "ALT-AZ");
624 cAntennaCols->position().put(n, antPosition);
625 Vector<Double> antOffset(3, 0.0);
626 cAntennaCols->offset().put(n, antOffset);
627 //cAntennaCols->dishDiameter().put(n, 64.0);
628 if (cGBT) {
629 cAntennaCols->dishDiameter().put(n, 110.0);
630 }
631 else {
632 cAntennaCols->dishDiameter().put(n, 64.0);
633 }
634 // Flags.
635 cAntennaCols->flagRow().put(n, False);
636
637 return n;
638}
639
640//-------------------------------------- PKSMS2writer::addDataDescriptionEntry
641
642// Add an entry to the DATA_DESCRIPTION subtable.
643
644Int PKSMS2writer::addDataDescriptionEntry(
645 const Int IFno)
646{
647 // Extend the DATA_DESCRIPTION subtable.
648 while (Int(cDataDescription.nrow()) < IFno) {
649 cDataDescription.addRow();
650 }
651 Int n = IFno - 1;
652
653 // Data.
654 cDataDescCols->spectralWindowId().put(n, n);
655 cDataDescCols->polarizationId().put(n, n);
656
657 // Flags.
658 cDataDescCols->flagRow().put(n, False);
659
660 return n;
661}
662
663//---------------------------------------------- PKSMS2writer::addDopplerEntry
664
665// Add an entry to the DOPPLER subtable.
666
667Int PKSMS2writer::addDopplerEntry()
668{
669 // Extend the DOPPLER subtable.
670 cDoppler.addRow();
671 Int n = cDoppler.nrow() - 1;
672
673 // Keys.
674 cDopplerCols->dopplerId().put(n, n);
675 cDopplerCols->sourceId().put(n, 0);
676
677 // Data.
678 cDopplerCols->transitionId().put(n, 0);
679
680 return n;
681}
682
683//------------------------------------------------- PKSMS2writer::addFeedEntry
684
685// Add an entry to the FEED subtable.
686
687Int PKSMS2writer::addFeedEntry()
688{
689 Int n = cFeed.nrow() - 1;
690 for (Int iBeam = 0; iBeam < 13; iBeam++) {
691 // Extend the FEED subtable.
692 cFeed.addRow();
693 n++;
694
695 // Keys.
696 cFeedCols->antennaId().put(n, cAntenna.nrow()-1);
697 cFeedCols->feedId().put(n, iBeam);
698 cFeedCols->spectralWindowId().put(n, -1);
699 cFeedCols->time().put(n, 0.0);
700 cFeedCols->interval().put(n, -1.0);
701
702 // Data description.
703 cFeedCols->numReceptors().put(n, 2);
704
705 // Data.
706 cFeedCols->beamId().put(n, -1);
707
708 Matrix<Double> beamOffset(2, 2, 0.0);
709 cFeedCols->beamOffset().put(n, beamOffset);
710
711 cFeedCols->focusLength().put(n, 26.0);
712
713 Vector<String> polarizationType(2);
714 polarizationType(0) = "X";
715 polarizationType(1) = "Y";
716 cFeedCols->polarizationType().put(n, polarizationType);
717
718 Matrix<Complex> polResponse(2, 2, Complex(0.0));
719 for (Int i = 0; i < 2; i++) {
720 polResponse(i,i) = Complex(1.0, 0.0);
721 }
722 cFeedCols->polResponse().put(n, polResponse);
723
724 Vector<Double> position(3, 0.0);
725 cFeedCols->position().put(n, position);
726
727 Vector<Double> receptorAngle(2, C::pi_4);
728 receptorAngle(1) += C::pi_2;
729 cFeedCols->receptorAngle().put(n, receptorAngle);
730 }
731
732 return n;
733}
734
735//------------------------------------------------ PKSMS2writer::addFieldEntry
736
737// Add an entry to the FIELD subtable.
738
739Int PKSMS2writer::addFieldEntry(
740 const String fieldName,
741 const Double time,
742 const Vector<Double> direction,
743 const Vector<Double> scanRate,
744 const Int srcId)
745{
746
747 ROScalarColumn<String> fldn(cField, "NAME");
748 ROScalarColumn<Int> sourceid(cField, "SOURCE_ID");
749 Int n;
750 Int nFld = cField.nrow();
751 for (n = 0; n < nFld; n++) {
752 if (fldn(n) == fieldName && sourceid(n) == srcId) {
753 break;
754 }
755 }
756
757 // Extend the FIELD subtable.
758 if (n == nFld) {
759 cField.addRow();
760 //Int n = cField.nrow() - 1;
761
762 // Data.
763 cFieldCols->name().put(n, fieldName);
764 if (cGBT) {
765 cFieldCols->code().put(n, " ");
766 }
767 else {
768 cFieldCols->code().put(n, "DRIFT");
769 }
770 cFieldCols->time().put(n, time);
771
772 //Matrix<Double> track(2, 2);
773 Matrix<Double> track(2, 1);
774 track.column(0) = direction;
775 //track.column(1) = scanRate;
776 cFieldCols->numPoly().put(n, 1);
777 cFieldCols->delayDir().put(n, track);
778 cFieldCols->phaseDir().put(n, track);
779 cFieldCols->referenceDir().put(n, track);
780 cFieldCols->sourceId().put(n, srcId);
781
782 // Flags.
783 cFieldCols->flagRow().put(n, False);
784 }
785
786 return n;
787}
788
789//------------------------------------------ PKSMS2writer::addObservationEntry
790
791// Add an entry to the OBSERVATION subtable.
792
793Int PKSMS2writer::addObservationEntry(
794 const String observer,
795 const String project,
796 const String antName)
797{
798 // Extend the OBSERVATION subtable.
799 cObservation.addRow();
800 Int n = cObservation.nrow() - 1;
801
802 // Data.
803 //cObservationCols->telescopeName().put(n, "Parkes");
804 cObservationCols->telescopeName().put(n, antName);
805 Vector<Double> timerange(2, 0.0);
806 cObservationCols->timeRange().put(n, timerange);
807 cObservationCols->observer().put(n, observer);
808 Vector<String> log(1, "none");
809 cObservationCols->log().put(n, log);
810 //cObservationCols->scheduleType().put(n, "ATNF");
811 cObservationCols->scheduleType().put(n, "");
812 Vector<String> schedule(1, "Not available");
813 cObservationCols->schedule().put(n, schedule);
814 cObservationCols->project().put(n, project);
815 cObservationCols->releaseDate().put(n, 0.0);
816
817 // Flags.
818 cObservationCols->flagRow().put(n, False);
819
820 return n;
821}
822
823//--------------------------------------------- PKSMS2writer::addPointingEntry
824
825// Modified to fill pointing data if the direction is the pointing direction.
826// So the following comment is no longer true.
827
828// Add an entry to the POINTING subtable. This compulsory subtable simply
829// duplicates information in the FIELD subtable.
830
831Int PKSMS2writer::addPointingEntry(
832 const Double time,
833 const Double interval,
834 const String fieldName,
835 const Vector<Double> direction,
836 const Vector<Double> scanRate)
837{
838
839 ROScalarColumn<Double> tms(cPointing, "TIME");
840 Int n;
841 Int ntm = cPointing.nrow();
842 for (n = 0; n < ntm; n++) {
843 if (tms(n) == time) {
844 break;
845 }
846 }
847
848 if (n == ntm) {
849 // Extend the POINTING subtable.
850 cPointing.addRow();
851 //Int n = cPointing.nrow() - 1;
852
853 // Keys.
854 cPointingCols->antennaId().put(n, 0);
855 cPointingCols->time().put(n, time);
856 cPointingCols->interval().put(n, interval);
857
858 // Data.
859 cPointingCols->name().put(n, fieldName);
860 cPointingCols->numPoly().put(n, 1);
861 cPointingCols->timeOrigin().put(n, time);
862
863 //Matrix<Double> track(2, 2);
864 Matrix<Double> track(2, 1);
865 track.column(0) = direction;
866 //track.column(1) = scanRate;
867 cPointingCols->direction().put(n, track);
868 cPointingCols->target().put(n, track);
869 cPointingCols->tracking().put(n, True);
870 }
871 return n;
872}
873
874//----------------------------------------- PKSMS2writer::addPolarizationEntry
875
876// Add an entry to the POLARIZATION subtable.
877
878Int PKSMS2writer::addPolarizationEntry(
879 const Int IFno,
880 const Int nPol)
881{
882 // Extend the POLARIZATION subtable.
883 while (Int(cPolarization.nrow()) < IFno) {
884 cPolarization.addRow();
885 }
886 Int n = IFno - 1;
887
888 // Data description.
889 cPolarizationCols->numCorr().put(n, nPol);
890
891 // Data.
892 Vector<Int> corrType(2);
893 if (nPol == 1) {
894 corrType.resize(1);
895 corrType(0) = Stokes::XX;
896 }
897 else {
898 //Vector<Int> corrType(2);
899 corrType(0) = Stokes::XX;
900 corrType(1) = Stokes::YY;
901 }
902 cPolarizationCols->corrType().put(n, corrType);
903
904 Matrix<Int> corrProduct(2,2,1);
905 if (nPol == 1) {
906 corrProduct.resize(2,1,1);
907 corrProduct(1,0) = 0;
908 }
909 if (nPol == 2) {
910 corrProduct(1,0) = 0;
911 corrProduct(0,1) = 0;
912 }
913 cPolarizationCols->corrProduct().put(n, corrProduct);
914
915 // Flags.
916 cPolarizationCols->flagRow().put(n, False);
917
918 return n;
919}
920
921
922//-------------------------------------------- PKSMS2writer::addProcessorEntry
923
924// Add an entry to the PROCESSOR subtable.
925
926Int PKSMS2writer::addProcessorEntry()
927{
928 // Extend the PROCESSOR subtable.
929 cProcessor.addRow();
930 Int n = cProcessor.nrow() - 1;
931
932 // Data.
933 cProcessorCols->type().put(n, "SPECTROMETER");
934 cProcessorCols->subType().put(n, "MULTIBEAM");
935 cProcessorCols->typeId().put(n, -1);
936 cProcessorCols->modeId().put(n, -1);
937
938 // Flags.
939 cProcessorCols->flagRow().put(n, False);
940
941 return n;
942}
943
944//----------------------------------------------- PKSMS2writer::addSourceEntry
945
946// Add an entry to the SOURCE subtable.
947
948Int PKSMS2writer::addSourceEntry(
949 const String name,
950 const Vector<Double> direction,
951 const Vector<Double> properMotion,
952 const Double restFreq,
953 const Double radialVelocity)
954{
955 // Look for an entry in the SOURCE subtable.
956 ROScalarColumn<String> sources(cSource, "NAME");
957 Int n;
958 Int nSrc = sources.nrow();
959 for (n = 0; n < nSrc; n++) {
960 if (sources(n) == name) {
961 break;
962 }
963 }
964
965 if (n == nSrc) {
966 // Not found, add a new entry to the SOURCE subtable.
967 cSource.addRow();
968
969 // Keys.
970 cSourceCols->sourceId().put(n, n);
971 cSourceCols->time().put(n, 0.0);
972 cSourceCols->interval().put(n, -1.0);
973 cSourceCols->spectralWindowId().put(n, -1);
974
975 // Data description.
976 cSourceCols->numLines().put(n, 1);
977
978 // Data.
979 cSourceCols->name().put(n, name);
980 cSourceCols->calibrationGroup().put(n, 0);
981 cSourceCols->code().put(n, "");
982 cSourceCols->direction().put(n, direction);
983// Vector<Double> position(3, 0.0);
984// cSourceCols->position().put(n, position);
985 cSourceCols->properMotion().put(n, properMotion);
986 Vector<Double> restFrequency(1, restFreq);
987 cSourceCols->restFrequency().put(n, restFrequency);
988 Vector<Double> sysvel(1, radialVelocity);
989 cSourceCols->sysvel().put(n, sysvel);
990 }
991
992 return n;
993}
994
995//--------------------------------------- PKSMS2writer::addSpectralWindowEntry
996
997// Add an entry to the SPECTRAL_WINDOW subtable.
998
999Int PKSMS2writer::addSpectralWindowEntry(
1000 const Int IFno,
1001 const Int nChan,
1002 const Double refFreq,
1003 const Double bandwidth,
1004 const Double freqInc)
1005{
1006 // Extend the SPECTRAL_WINDOW subtable.
1007 while (Int(cSpectralWindow.nrow()) < IFno) {
1008 cSpectralWindow.addRow();
1009 }
1010 Int n = IFno - 1;
1011
1012 // Data description.
1013 cSpWindowCols->numChan().put(n, nChan);
1014
1015 // Data.
1016 //cSpWindowCols->name().put(n, "L-band");
1017 cSpWindowCols->name().put(n, " ");
1018 cSpWindowCols->refFrequency().put(n, refFreq);
1019
1020 // 0-relative reference channel number.
1021 Double refChan = nChan / 2;
1022 Vector<Double> freqs(nChan);
1023 for (Int i = 0; i < nChan; i++) {
1024 freqs(i) = refFreq + (i - refChan)*freqInc;
1025 }
1026 cSpWindowCols->chanFreq().put(n, freqs);
1027
1028 Vector<Double> chanWidths(nChan, freqInc);
1029 cSpWindowCols->chanWidth().put(n, chanWidths);
1030
1031 cSpWindowCols->measFreqRef().put(n, cDopplerFrame);
1032 cSpWindowCols->effectiveBW().put(n, chanWidths);
1033
1034 Vector<Double> resolution(nChan, fabs(freqInc));
1035 cSpWindowCols->resolution().put(n, resolution);
1036
1037 cSpWindowCols->totalBandwidth().put(n, bandwidth);
1038 cSpWindowCols->netSideband().put(n, 0);
1039 cSpWindowCols->ifConvChain().put(n, -1);
1040 cSpWindowCols->freqGroup().put(n, 0);
1041 cSpWindowCols->freqGroupName().put(n, " ");
1042 cSpWindowCols->dopplerId().put(n, 0);
1043
1044 // Flags.
1045 cSpWindowCols->flagRow().put(n, False);
1046
1047 return n;
1048}
1049
1050//------------------------------------------------ PKSMS2writer::addStateEntry
1051
1052// Add an entry to the STATE subtable.
1053
1054Int PKSMS2writer::addStateEntry(
1055 const String obsMode)
1056{
1057 // Look for an entry in the STATE subtable.
1058 for (uInt n = 0; n < cStateCols->nrow(); n++) {
1059 if (cStateCols->obsMode()(n) == obsMode) {
1060 return n;
1061 }
1062 }
1063
1064 // Not found, extend the STATE subtable.
1065 cState.addRow();
1066 uInt n = cStateCols->nrow() - 1;
1067
1068 // Data.
1069 if (obsMode.contains("RF")) {
1070 cStateCols->sig().put(n, False);
1071 cStateCols->ref().put(n, True);
1072 } else if (!obsMode.contains("PA")) {
1073 // Signal and reference are both false for "paddle" data.
1074 cStateCols->sig().put(n, True);
1075 cStateCols->ref().put(n, False);
1076 }
1077
1078 cStateCols->load().put(n, 0.0);
1079 cStateCols->cal().put(n, 0.0);
1080 cStateCols->subScan().put(n, 0);
1081 cStateCols->obsMode().put(n, obsMode);
1082
1083 // Flags.
1084 cStateCols->flagRow().put(n, False);
1085
1086 return n;
1087}
1088
1089//----------------------------------------------- PKSMS2writer::addSysCalEntry
1090
1091// Add an entry to the SYSCAL subtable.
1092
1093Int PKSMS2writer::addSysCalEntry(
1094 const Int beamNo,
1095 const Int spWinId,
1096 const Double time,
1097 const Double interval,
1098 const Vector<Float> tcal,
1099 const Vector<Float> tsys,
1100 const Int nPol)
1101{
1102 LogIO os(LogOrigin("PKSMS2writer", "addSysCalEntry()", WHERE));
1103
1104 // Extend the SYSCAL subtable.
1105 cSysCal.addRow();
1106 Int n = cSysCal.nrow() - 1;
1107
1108 //check fo consistency with n pol
1109 //here assume size of Tcal vector = npol
1110 Vector<Float> inTcal(nPol,0);
1111 Int ndim = tcal.shape()(0);
1112 Vector<Float> tmpTcal = tcal;
1113 if (nPol != ndim) {
1114 os << LogIO::WARN
1115 << "Found "<< ndim <<" Tcal value(s) for the data with "<<nPol<<" polarization(s)"
1116 << "(expecting one Tcal per pol)."<<endl
1117 << "First "<< nPol << " Tcal value(s) will be filled." << LogIO::POST;
1118 tmpTcal.resize(nPol, True);
1119 inTcal = tmpTcal;
1120 }
1121 // Keys.
1122 cSysCalCols->antennaId().put(n, 0);
1123 cSysCalCols->feedId().put(n, beamNo-1);
1124 cSysCalCols->spectralWindowId().put(n, spWinId);
1125 cSysCalCols->time().put(n, time);
1126 cSysCalCols->interval().put(n, interval);
1127
1128 // Data.
1129 //cSysCalCols->tcal().put(n, tcal);
1130 cSysCalCols->tcal().put(n, inTcal);
1131 cSysCalCols->tsys().put(n, tsys);
1132
1133 return n;
1134}
1135
1136//---------------------------------------------- PKSMS2writer::addWeatherEntry
1137
1138// Add an entry to the WEATHER subtable.
1139
1140Int PKSMS2writer::addWeatherEntry(
1141 const Double time,
1142 const Double interval,
1143 const Double pressure,
1144 const Double relHumidity,
1145 const Double temperature)
1146{
1147 // Extend the WEATHER subtable.
1148 cWeather.addRow();
1149 Int n = cWeather.nrow() - 1;
1150
1151 // Keys.
1152 cWeatherCols->antennaId().put(n, 0);
1153 cWeatherCols->time().put(n, time);
1154 cWeatherCols->interval().put(n, interval);
1155
1156 // Data.
1157 cWeatherCols->pressure().put(n, pressure);
1158 cWeatherCols->relHumidity().put(n, relHumidity);
1159 cWeatherCols->temperature().put(n, temperature);
1160
1161 return n;
1162}
Note: See TracBrowser for help on using the repository browser.