source: trunk/external-alma/atnf/PKSIO/PKSMS2writer.cc @ 3067

Last change on this file since 3067 was 1941, checked in by Takeshi Nakazato, 14 years ago

New Development: Yes/No?

JIRA Issue: No/Yes? List JIRA ticket.

Ready for Test: Yes/No?

Interface Changes: Yes/No?

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Merged bug fix on PKSMS2writer (external-alma@asap4casa3.1.0) to trunk.


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