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

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

Changes to handle GBT MS data

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