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

Last change on this file since 1453 was 1453, checked in by TakTsutsumi, 15 years ago

New Development: No

JIRA Issue: No

Ready to Release: Yes

Interface Changes: Yes

What Interface Changed: many

Test Programs: sd.scantable(), sd.scantable.save()

Put in Release Notes: N/A

Description: copied from current casapy code tree


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