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

Last change on this file since 1427 was 1399, checked in by Malte Marquarding, 17 years ago

Mark C added brightness unit to getHeader()

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