source: trunk/external/atnf/PKSIO/PKSMS2writer.cc@ 1373

Last change on this file since 1373 was 1325, checked in by mar637, 17 years ago

Changes to use casacore instead of casa_asap/aips++\nAdded atnf PKSIO library snapshot to external and linking against this local copy

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