source: branches/alma/external/atnf/PKSIO/PKSMS2reader.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: 31.9 KB
Line 
1//#---------------------------------------------------------------------------
2//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
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$
29//#---------------------------------------------------------------------------
30//# Original: 2000/08/03, Mark Calabretta, ATNF
31//#---------------------------------------------------------------------------
32
33
34// AIPS++ includes.
35#include <casa/stdio.h>
36#include <casa/Arrays/ArrayMath.h>
37#include <casa/Arrays/Slice.h>
38#include <ms/MeasurementSets/MSColumns.h>
39#include <tables/Tables.h>
40#include <casa/Quanta/MVTime.h>
41#include <casa/Quanta/MVAngle.h>
42#include <casa/BasicMath/Math.h>
43#include <measures/Measures/MeasConvert.h>
44#include <measures/Measures/MEpoch.h>
45#include <measures/Measures/MeasRef.h>
46
47
48// Parkes includes.
49#include <atnf/pks/pks_maths.h>
50#include <atnf/PKSIO/PKSMS2reader.h>
51
52
53//------------------------------------------------- PKSMS2reader::PKSMS2reader
54
55// Default constructor.
56
57PKSMS2reader::PKSMS2reader()
58{
59  cMSopen = False;
60}
61
62//------------------------------------------------ PKSMS2reader::~PKSMS2reader
63
64PKSMS2reader::~PKSMS2reader()
65{
66  close();
67}
68
69//--------------------------------------------------------- PKSMS2reader::open
70
71// Open the MS for reading.
72
73Int PKSMS2reader::open(
74        const String msName,
75        Vector<Bool> &beams,
76        Vector<Bool> &IFs,
77        Vector<uInt> &nChan,
78        Vector<uInt> &nPol,
79        Vector<Bool> &haveXPol,
80        Bool   &haveBase,
81        Bool   &haveSpectra)
82{
83  // Check that MS is readable.
84  if (!MS::isReadable(msName)) {
85    return 1;
86  }
87
88  if (cMSopen) {
89    close();
90  }
91
92  cPKSMS  = MeasurementSet(msName);
93  // taql access to the syscal table
94  cHaveSysCal = False;
95  if (cHaveSysCal=Table::isReadable(cPKSMS.sysCalTableName())) {
96    cSysCalTab = Table(cPKSMS.sysCalTableName());
97  }
98
99  cIdx    = 0;
100  lastmjd = 0.0;
101  cNRow   = cPKSMS.nrow();
102  cMSopen = True;
103
104  // Lock the table for read access.
105  cPKSMS.lock(False);
106
107  // Main MS table and subtable column access.
108  ROMSMainColumns         msCols(cPKSMS);
109  ROMSDataDescColumns     dataDescCols(cPKSMS.dataDescription());
110  ROMSFeedColumns         feedCols(cPKSMS.feed());
111  ROMSFieldColumns        fieldCols(cPKSMS.field());
112  ROMSPointingColumns     pointingCols(cPKSMS.pointing());
113  ROMSPolarizationColumns polarizationCols(cPKSMS.polarization());
114  ROMSSourceColumns       sourceCols(cPKSMS.source());
115  ROMSSpWindowColumns     spWinCols(cPKSMS.spectralWindow());
116  ROMSStateColumns        stateCols(cPKSMS.state());
117  ROMSSysCalColumns       sysCalCols(cPKSMS.sysCal());
118  ROMSWeatherColumns      weatherCols(cPKSMS.weather());
119  ROMSAntennaColumns      antennaCols(cPKSMS.antenna());
120
121  // Column accessors for required columns.
122  cScanNoCol.reference(msCols.scanNumber());
123  cTimeCol.reference(msCols.time());
124  cIntervalCol.reference(msCols.interval());
125
126  cFieldIdCol.reference(msCols.fieldId());
127  cFieldNameCol.reference(fieldCols.name());
128  cFieldDelayDirCol.reference(fieldCols.delayDir());
129
130  cSrcIdCol.reference(fieldCols.sourceId());
131  cSrcId2Col.reference(sourceCols.sourceId());
132  cSrcNameCol.reference(sourceCols.name());
133  cSrcDirCol.reference(sourceCols.direction());
134  cSrcPMCol.reference(sourceCols.properMotion());
135  cSrcRestFrqCol.reference(sourceCols.restFrequency());
136
137  cStateIdCol.reference(msCols.stateId());
138  cObsModeCol.reference(stateCols.obsMode());
139  cCalCol.reference(stateCols.cal());
140  cSigStateCol.reference(stateCols.sig());
141  cRefStateCol.reference(stateCols.ref());
142  cDataDescIdCol.reference(msCols.dataDescId());
143  cSpWinIdCol.reference(dataDescCols.spectralWindowId());
144  cChanFreqCol.reference(spWinCols.chanFreq());
145
146  cWeatherTimeCol.reference(weatherCols.time());
147  cTemperatureCol.reference(weatherCols.temperature());
148  cPressureCol.reference(weatherCols.pressure());
149  cHumidityCol.reference(weatherCols.relHumidity());
150
151  cBeamNoCol.reference(msCols.feed1());
152  cPointingCol.reference(pointingCols.direction());
153  cSigmaCol.reference(msCols.sigma());
154  cNumReceptorCol.reference(feedCols.numReceptors());
155
156  // Optional columns.
157  cHaveTsys = False;
158  cHaveTcal = False;
159  if ((cHaveSrcVel = cPKSMS.source().tableDesc().isColumn("SYSVEL"))) {
160    cSrcVelCol.attach(cPKSMS.source(), "SYSVEL");
161  }
162
163  if (cHaveSysCal && (cHaveTsys = cPKSMS.sysCal().tableDesc().isColumn("TSYS"))) {
164    cTsysCol.attach(cPKSMS.sysCal(), "TSYS");
165  }
166 
167  if (cHaveSysCal && (cHaveTcal = cPKSMS.sysCal().tableDesc().isColumn("TCAL"))) {
168    cTcalCol.attach(cPKSMS.sysCal(), "TCAL");
169  }
170
171  if ((cHaveCalFctr = cPKSMS.tableDesc().isColumn("CALFCTR"))) {
172    cCalFctrCol.attach(cPKSMS, "CALFCTR");
173  }
174
175  if ((cHaveBaseLin = cPKSMS.tableDesc().isColumn("BASELIN"))) {
176    cBaseLinCol.attach(cPKSMS, "BASELIN");
177    cBaseSubCol.attach(cPKSMS, "BASESUB");
178  }
179
180  // Spectral data should always be present.
181  haveSpectra = True;
182  cHaveDataCol = False;
183  cHaveCorrectedDataCol = False;
184  //String telName = antennaCols.name()(0);
185  ROMSObservationColumns observationCols(cPKSMS.observation());
186  String telName = observationCols.telescopeName()(0);
187  //cATF = (telName.contains("DA41") || telName.contains("DV01"));
188  cATF = telName.contains("ATF");
189
190  if (cHaveDataCol = cPKSMS.isColumn(MSMainEnums::DATA)) {
191    if (cATF) {
192      //try to read a single baseline interferometeric data
193      //and treat it as single dish data
194      //maybe extended for ALMA commissioning later
195      cDataCol.reference(msCols.data());
196      if (cHaveCorrectedDataCol = cPKSMS.isColumn(MSMainEnums::CORRECTED_DATA)) {
197        //cerr<<"Do have CORRECTED_DATA column"<<endl;
198        cCorrectedDataCol.reference(msCols.correctedData());
199      }
200    }
201  }
202  else {
203    cFloatDataCol.reference(msCols.floatData());
204  }
205  cFlagCol.reference(msCols.flag());
206
207
208  if (cGetXPol = (cPKSMS.isColumn(MSMainEnums::DATA) && (!cATF))) {
209    if ((cHaveXCalFctr = cPKSMS.tableDesc().isColumn("XCALFCTR"))) {
210      cXCalFctrCol.attach(cPKSMS, "XCALFCTR");
211    }
212
213    cDataCol.reference(msCols.data());
214  }
215
216  // Find which beams are present in the data.
217  Vector<Int> beamNos = cBeamNoCol.getColumn();
218  Int maxBeamNo = max(beamNos) + 1;
219  beams.resize(maxBeamNo);
220
221  beams = False;
222  for (uInt irow = 0; irow < beamNos.nelements(); irow++) {
223    beams(beamNos(irow)) = True;
224  }
225
226
227  // Number of IFs.
228  //uInt nIF = dataDescCols.nrow();
229  uInt nIF =spWinCols.nrow();
230  IFs.resize(nIF);
231  IFs = True;
232
233  // Number of polarizations and channels in each IF.
234  ROScalarColumn<Int> spWinIdCol(dataDescCols.spectralWindowId());
235  ROScalarColumn<Int> numChanCol(spWinCols.numChan());
236
237  ROScalarColumn<Int> polIdCol(dataDescCols.polarizationId());
238  ROScalarColumn<Int> numPolCol(polarizationCols.numCorr());
239
240  nChan.resize(nIF);
241  nPol.resize(nIF);
242  for (uInt iIF = 0; iIF < nIF; iIF++) {
243    nChan(iIF) = numChanCol(spWinIdCol(iIF));
244    nPol(iIF)  = numPolCol(polIdCol(iIF));
245  }
246
247  // Cross-polarization data present?
248  haveXPol.resize(nIF);
249  haveXPol = False;
250
251  if (cGetXPol && !(cATF)) {
252    for (Int irow = 0; irow < cNRow; irow++) {
253      if (cDataCol.isDefined(irow)) {
254        Int iIF = cDataDescIdCol(irow);
255        haveXPol(iIF) = True;
256      }
257    }
258  }
259
260
261  // Initialize member data.
262  cBeams.assign(beams);
263  cIFs.assign(IFs);
264  cNChan.assign(nChan);
265  cNPol.assign(nPol);
266  cHaveXPol.assign(haveXPol);
267
268
269  // Default channel range selection.
270  cStartChan.resize(nIF);
271  cEndChan.resize(nIF);
272  cRefChan.resize(nIF);
273
274  for (uInt iIF = 0; iIF < nIF; iIF++) {
275    cStartChan(iIF) = 1;
276    cEndChan(iIF)   = cNChan(iIF);
277    cRefChan(iIF)   = cNChan(iIF)/2 + 1;
278  }
279
280  Slice all;
281  cDataSel.resize(nIF);
282  cDataSel = Slicer(all, all);
283
284  cScanNo  = 0;
285  cCycleNo = 1;
286  cTime    = cTimeCol(0);
287
288  return 0;
289}
290
291//---------------------------------------------------- PKSMS2reader::getHeader
292
293// Get parameters describing the data.
294
295Int PKSMS2reader::getHeader(
296        String &observer,
297        String &project,
298        String &antName,
299        Vector<Double> &antPosition,
300        String &obsMode,
301        Float  &equinox,
302        String &dopplerFrame,
303        Double &mjd,
304        Double &refFreq,
305        Double &bandwidth,
306        String &fluxunit)
307{
308  if (!cMSopen) {
309    return 1;
310  }
311
312  // Observer and project.
313  ROMSObservationColumns observationCols(cPKSMS.observation());
314  observer = observationCols.observer()(0);
315  project  = observationCols.project()(0);
316
317  // Antenna name and ITRF coordinates.
318  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
319  antName = antennaCols.name()(0);
320  antPosition = antennaCols.position()(0);
321
322  // Observation type.
323  if (cObsModeCol.nrow()) {
324    obsMode = cObsModeCol(0);
325    if (obsMode == "\0") obsMode = "RF";
326  } else {
327    obsMode = "RF";
328  }
329
330  fluxunit = "";
331  if (cHaveDataCol) {
332    const TableRecord& keywordSet2
333       = cDataCol.columnDesc().keywordSet();
334    if(keywordSet2.isDefined("UNIT")) {
335      fluxunit = keywordSet2.asString("UNIT");
336    }
337  } else {
338    const TableRecord& keywordSet
339       = cFloatDataCol.columnDesc().keywordSet();
340    if(keywordSet.isDefined("UNIT")) {
341      fluxunit = keywordSet.asString("UNIT");
342    }
343  }
344
345/***
346  const TableRecord& keywordSet
347       = cFloatDataCol.columnDesc().keywordSet();
348  if(keywordSet.isDefined("UNIT")) {
349    fluxunit = keywordSet.asString("UNIT");
350  }
351***/
352  // Coordinate equinox.
353  ROMSPointingColumns pointingCols(cPKSMS.pointing());
354  String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
355                    asString("Ref");
356  sscanf(dirref.chars()+1, "%f", &equinox);
357
358  // Frequency/velocity reference frame.
359  ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
360  dopplerFrame = MFrequency::showType(spWinCols.measFreqRef()(0));
361
362  // Translate to FITS standard names.
363  if (dopplerFrame == "TOPO") {
364    dopplerFrame = "TOPOCENT";
365  } else if (dopplerFrame == "GEO") {
366    dopplerFrame = "GEOCENTR";
367  } else if (dopplerFrame == "BARY") {
368    dopplerFrame = "BARYCENT";
369  } else if (dopplerFrame == "GALACTO") {
370    dopplerFrame = "GALACTOC";
371  } else if (dopplerFrame == "LGROUP") {
372    dopplerFrame = "LOCALGRP";
373  } else if (dopplerFrame == "CMB") {
374    dopplerFrame = "CMBDIPOL";
375  } else if (dopplerFrame == "REST") {
376    dopplerFrame = "SOURCE";
377  }
378
379  // MJD at start of observation.
380  mjd = cTimeCol(0)/86400.0;
381
382  // Reference frequency and bandwidth.
383  refFreq   = spWinCols.refFrequency()(0);
384  bandwidth = spWinCols.totalBandwidth()(0);
385
386  return 0;
387}
388
389//-------------------------------------------------- PKSMS2reader::getFreqInfo
390
391// Get frequency parameters for each IF.
392
393Int PKSMS2reader::getFreqInfo(
394        Vector<Double> &startFreq,
395        Vector<Double> &endFreq)
396{
397  uInt nIF = cIFs.nelements();
398  startFreq.resize(nIF);
399  endFreq.resize(nIF);
400
401  for (uInt iIF = 0; iIF < nIF; iIF++) {
402    Vector<Double> chanFreq = cChanFreqCol(iIF);
403
404    Int nChan = chanFreq.nelements();
405    startFreq(iIF) = chanFreq(0);
406    endFreq(iIF)   = chanFreq(nChan-1);
407  }
408
409  return 0;
410}
411
412//------------------------------------------------------- PKSMS2reader::select
413
414// Set data selection by beam number and channel.
415
416uInt PKSMS2reader::select(
417        const Vector<Bool> beamSel,
418        const Vector<Bool> IFsel,
419        const Vector<Int>  startChan,
420        const Vector<Int>  endChan,
421        const Vector<Int>  refChan,
422        const Bool getSpectra,
423        const Bool getXPol,
424        const Bool getFeedPos)
425{
426  if (!cMSopen) {
427    return 1;
428  }
429
430  // Beam selection.
431  uInt nBeam = cBeams.nelements();
432  uInt nBeamSel = beamSel.nelements();
433  for (uInt ibeam = 0; ibeam < nBeam; ibeam++) {
434    if (ibeam < nBeamSel) {
435      cBeams(ibeam) = beamSel(ibeam);
436    } else {
437      cBeams(ibeam) = False;
438    }
439  }
440
441  uInt nIF = cIFs.nelements();
442  uInt maxNChan = 0;
443  for (uInt iIF = 0; iIF < nIF; iIF++) {
444    // IF selection.
445    if (iIF < IFsel.nelements()) {
446      cIFs(iIF) = IFsel(iIF);
447    } else {
448      cIFs(iIF) = False;
449    }
450
451    if (!cIFs(iIF)) continue;
452
453
454    // Channel selection.
455    if (iIF < startChan.nelements()) {
456      cStartChan(iIF) = startChan(iIF);
457
458      if (cStartChan(iIF) <= 0) {
459        cStartChan(iIF) += cNChan(iIF);
460      } else if (cStartChan(iIF) > Int(cNChan(iIF))) {
461        cStartChan(iIF)  = cNChan(iIF);
462      }
463    }
464
465    if (iIF < endChan.nelements()) {
466      cEndChan(iIF) = endChan(iIF);
467
468      if (cEndChan(iIF) <= 0) {
469        cEndChan(iIF) += cNChan(iIF);
470      } else if (cEndChan(iIF) > Int(cNChan(iIF))) {
471        cEndChan(iIF)  = cNChan(iIF);
472      }
473    }
474
475    if (iIF < refChan.nelements()) {
476      cRefChan(iIF) = refChan(iIF);
477    } else {
478      cRefChan(iIF) = cStartChan(iIF);
479      if (cStartChan(iIF) <= cEndChan(iIF)) {
480        cRefChan(iIF) += (cEndChan(iIF) - cStartChan(iIF) + 1)/2;
481      } else {
482        cRefChan(iIF) -= (cStartChan(iIF) - cEndChan(iIF) + 1)/2;
483      }
484    }
485
486    uInt nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
487    if (maxNChan < nChan) {
488      maxNChan = nChan;
489    }
490
491    // Inverted Slices are not allowed.
492    Slice outPols;
493    Slice outChans(min(cStartChan(iIF),cEndChan(iIF))-1, nChan);
494    cDataSel(iIF) = Slicer(outPols, outChans);
495  }
496
497  // Get spectral data?
498  cGetSpectra = getSpectra;
499
500  // Get cross-polarization data?
501  cGetXPol = cGetXPol && getXPol;
502
503  // Get feed positions?  (Not available.)
504  cGetFeedPos = False;
505
506  return maxNChan;
507}
508
509//---------------------------------------------------- PKSMS2reader::findRange
510
511// Find the range of the data in time and position.
512
513Int PKSMS2reader::findRange(
514        Int    &nRow,
515        Int    &nSel,
516        Vector<Double> &timeSpan,
517        Matrix<Double> &positions)
518{
519  if (!cMSopen) {
520    return 1;
521  }
522
523  nRow = cNRow;
524
525  // Find the number of rows selected.
526  nSel = 0;
527  Vector<Bool> sel(nRow);
528  for (Int irow = 0; irow < nRow; irow++) {
529    if ((sel(irow) = cBeams(cBeamNoCol(irow)) &&
530                     cIFs(cDataDescIdCol(irow)))) {
531      nSel++;
532    }
533  }
534
535  // Find the time range (s).
536  timeSpan.resize(2);
537  timeSpan(0) = cTimeCol(0);
538  timeSpan(1) = cTimeCol(nRow-1);
539
540  // Retrieve positions for selected data.
541  Int isel = 0;
542  positions.resize(2,nSel);
543  for (Int irow = 0; irow < nRow; irow++) {
544    if (sel(irow)) {
545      Matrix<Double> pointingDir = cPointingCol(cFieldIdCol(irow));
546      positions.column(isel++) = pointingDir.column(0);
547    }
548  }
549
550  return 0;
551}
552
553//--------------------------------------------------------- PKSMS2reader::read
554
555// Read the next data record.
556
557Int PKSMS2reader::read(
558        Int             &scanNo,
559        Int             &cycleNo,
560        Double          &mjd,
561        Double          &interval,
562        String          &fieldName,
563        String          &srcName,
564        Vector<Double>  &srcDir,
565        Vector<Double>  &srcPM,
566        Double          &srcVel,
567        String          &obsMode,
568        Int             &IFno,
569        Double          &refFreq,
570        Double          &bandwidth,
571        Double          &freqInc,
572        Vector<Double>  &restFreq,
573        Vector<Float>   &tcal,
574        String          &tcalTime,
575        Float           &azimuth,
576        Float           &elevation,
577        Float           &parAngle,
578        Float           &focusAxi,
579        Float           &focusTan,
580        Float           &focusRot,
581        Float           &temperature,
582        Float           &pressure,
583        Float           &humidity,
584        Float           &windSpeed,
585        Float           &windAz,
586        Int             &refBeam,
587        Int             &beamNo,
588        Vector<Double>  &direction,
589        Vector<Double>  &scanRate,
590        Vector<Float>   &tsys,
591        Vector<Float>   &sigma,
592        Vector<Float>   &calFctr,
593        Matrix<Float>   &baseLin,
594        Matrix<Float>   &baseSub,
595        Matrix<Float>   &spectra,
596        Matrix<uChar>   &flagged,
597        Complex         &xCalFctr,
598        Vector<Complex> &xPol)
599{
600  if (!cMSopen) {
601    return 1;
602  }
603
604  // Check for EOF.
605  if (cIdx >= cNRow) {
606    return -1;
607  }
608
609  // Find the next selected beam and IF.
610  Int ibeam;
611  Int iIF;
612  Int iDataDesc;
613
614  while (True) {
615    ibeam = cBeamNoCol(cIdx);
616    iDataDesc   = cDataDescIdCol(cIdx);
617    iIF   =cSpWinIdCol(iDataDesc);
618    if (cBeams(ibeam) && cIFs(iIF)) {
619      break;
620    }
621
622    // Check for EOF.
623    if (++cIdx >= cNRow) {
624      return -1;
625    }
626  }
627  // Renumerate scan no. Here still is 1-based
628  //scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
629  scanNo = cScanNoCol(cIdx);
630 
631  if (scanNo != cScanNo) {
632    // Start of new scan.
633    cScanNo  = scanNo;
634    cCycleNo = 1;
635    cTime    = cTimeCol(cIdx);
636  }
637
638  Double time = cTimeCol(cIdx);
639  mjd      = time/86400.0;
640  interval = cIntervalCol(cIdx);
641
642  // Reconstruct the integration cycle number; due to small latencies the
643  // integration time is usually slightly less than the time between cycles,
644  // resetting cTime will prevent the difference from accumulating.
645  cCycleNo += nint((time - cTime)/interval);
646  cycleNo = cCycleNo;
647  cTime   = time;
648
649  Int fieldId = cFieldIdCol(cIdx);
650  fieldName = cFieldNameCol(fieldId);
651
652  Int srcId = cSrcIdCol(fieldId);
653  //For source with multiple spectral window setting, this is not
654  // correct. Source name of srcId may not be at 'srcId'th row of SrcNameCol
655  //srcName = cSrcNameCol(srcId);
656  for (uInt irow = 0; irow < cSrcId2Col.nrow(); irow++) {
657    if (cSrcId2Col(irow) == srcId) {
658      srcName = cSrcNameCol(irow);
659    }
660  }
661
662  srcDir  = cSrcDirCol(srcId);
663  srcPM   = cSrcPMCol(srcId);
664
665  // Systemic velocity.
666  if (!cHaveSrcVel || cATF) {
667    srcVel = 0.0f;
668  } else {
669    srcVel  = cSrcVelCol(srcId)(IPosition(1,0));
670  }
671
672  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
673  String telescope = antennaCols.name()(0);
674  Bool cGBT = telescope.contains("GBT");
675  // Observation type.
676  // check if State Table exist
677  //Bool cHaveStateTab=Table::isReadable(cPKSMS.stateTableName());
678  Int stateId = 0;
679  Int StateNRow = 0;
680  StateNRow=cObsModeCol.nrow();
681  if (Table::isReadable(cPKSMS.stateTableName())) {
682        obsMode = " ";
683    if (StateNRow > 0) {
684      stateId = cStateIdCol(cIdx);
685      if (stateId == -1) {
686        //obsMode = " ";
687      } else {
688        obsMode = cObsModeCol(stateId);
689        Bool sigState =cSigStateCol(stateId);
690        Bool refState =cRefStateCol(stateId);
691        //DEBUG
692        //cerr <<"stateid="<<stateId<<" obsmode="<<obsMode<<endl;
693        if (cGBT) {
694          // split the obsMode string and append a proper label
695          // (these are GBT specific)
696          int epos = obsMode.find_first_of(':');
697          int nextpos = obsMode.find_first_of(':',epos+1);
698          string obsMode1 = obsMode.substr(0,epos);
699          string obsMode2 = obsMode.substr(epos+1,nextpos-epos-1);
700     
701          //cerr <<"obsMode2= "<<obsMode2<<endl;
702          if (!srcName.contains("_ps")
703              &&!srcName.contains("_psr")
704              &&!srcName.contains("_nod")
705              &&!srcName.contains("_fs")
706              &&!srcName.contains("_fsr")) {
707            // if Nod mode observation , append '_nod'
708            if (obsMode1 == "Nod") {
709              srcName.append("_nod");
710            } else if (obsMode1 == "OffOn") {
711            // for GBT position switch observations (OffOn or OnOff)
712              if (obsMode2 == "PSWITCHON") srcName.append("_ps");
713              if (obsMode2 == "PSWITCHOFF") srcName.append("_psr");
714            } else {
715              if (obsMode2 == "FSWITCH") {
716              // for GBT frequency switch mode
717                if (sigState) srcName.append("_fs");
718                if (refState) srcName.append("_fsr");
719              }
720            }
721          }
722        }
723      }
724    }
725  }
726  // CAL state
727  // this should be apply just for GBT data?
728  Double Cal;
729  if (stateId==-1 || StateNRow==0) {
730    Cal = 0;
731  } else {
732    Cal = cCalCol(stateId);
733  }
734  if (cGBT) {
735    if (Cal > 0 && !srcName.contains("_calon")) {
736      srcName.append("_calon");
737    }
738  }
739
740  IFno = iIF + 1;
741  Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
742 
743  // Minimal handling on continuum data.
744  Vector<Double> chanFreq = cChanFreqCol(iIF);
745  if (nChan == 1) {
746    freqInc  = chanFreq(0);
747    refFreq  = chanFreq(0);
748    restFreq = 0.0f;
749  } else {
750 
751    if (cStartChan(iIF) <= cEndChan(iIF)) {
752      freqInc = chanFreq(1) - chanFreq(0);
753    } else {
754      freqInc = chanFreq(0) - chanFreq(1);
755    }
756    refFreq  = chanFreq(cRefChan(iIF)-1);
757    Bool HaveSrcRestFreq= cSrcRestFrqCol.isDefined(srcId);
758    if (HaveSrcRestFreq) {
759      //restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
760      restFreq = cSrcRestFrqCol(srcId);
761    } else {
762      restFreq = 0.0f;
763    }
764  }
765  bandwidth = abs(freqInc * nChan);
766
767  tcal.resize(cNPol(iIF));
768  tcal      = 0.0f;
769  tcalTime  = "";
770  //azimuth   = 0.0f;
771  //elevation = 0.0f;
772  parAngle  = 0.0f;
773  focusAxi  = 0.0f;
774  focusTan  = 0.0f;
775  focusRot  = 0.0f;
776
777  // Find the appropriate entry in the WEATHER subtable.
778  //Bool cHaveStateTab=Table::isReadable(cPKSMS.stateTableName());
779  Bool cHaveWeatherTab = Table::isReadable(cPKSMS.weatherTableName());
780  Int weatherIdx=-1;
781  if (cHaveWeatherTab) {
782    Vector<Double> wTimes = cWeatherTimeCol.getColumn();
783    for (weatherIdx = wTimes.nelements()-1; weatherIdx >= 0; weatherIdx--) {
784      if (cWeatherTimeCol(weatherIdx) <= time) {
785        break;
786      }
787    }
788  }
789  if (weatherIdx < 0 || !cHaveWeatherTab) {
790    // No appropriate WEATHER entry.
791    pressure    = 0.0f;
792    humidity    = 0.0f;
793    temperature = 0.0f;
794  } else {
795    pressure    = cPressureCol(weatherIdx);
796    humidity    = cHumidityCol(weatherIdx);
797    temperature = cTemperatureCol(weatherIdx);
798  }
799
800  windSpeed = 0.0f;
801  windAz    = 0.0f;
802
803  refBeam = 0;
804  beamNo  = ibeam + 1;
805
806  //Matrix<Double> pointingDir = cPointingCol(fieldId);
807  //pointingDir = cPointingCol(fieldId);
808  //direction = pointingDir.column(0);
809  //uInt ncols = pointingDir.ncolumn();
810  //if (ncols == 1) {
811  //  scanRate = 0.0f;
812  //} else {
813  //  scanRate  = pointingDir.column(1);
814  //}
815
816  // Get direction from FIELD table
817  // here, assume direction to be the field direction not pointing
818  Matrix<Double> delayDir = cFieldDelayDirCol(fieldId);
819  direction = delayDir.column(0);
820  uInt ncols = delayDir.ncolumn();
821  if (ncols == 1) {
822    scanRate = 0.0f;
823  } else {
824    scanRate  = delayDir.column(1);
825  }
826
827  // caluculate azimuth and elevation
828  // first, get the reference frame
829  MVPosition mvpos(antennaCols.position()(0));
830  MPosition mp(mvpos);
831  Quantum<Double> qt(time,"s");
832  MVEpoch mvt(qt);
833  MEpoch me(mvt);
834  MeasFrame frame(mp, me);
835  //
836  ROMSFieldColumns fldCols(cPKSMS.field());
837  Vector<MDirection> vmd(1);
838  MDirection md;
839  fldCols.delayDirMeasCol().get(fieldId,vmd);
840  md = vmd[0];
841  //Vector<Double> dircheck = md.getAngle("rad").getValue();
842  //cerr<<"dircheck="<<dircheck<<endl;
843
844  Vector<Double> azel =
845        MDirection::Convert(md, MDirection::Ref(MDirection::AZEL,
846                                                frame)
847                            )().getAngle("rad").getValue();
848  //cerr<<"azel="<<azel<<endl;
849  azimuth = azel[0];
850  elevation = azel[1];
851
852  // Get Tsys assuming that entries in the SYSCAL table match the main table.
853  if (cHaveTsys) {
854    Int nTsysColRow = cTsysCol.nrow();
855    if (nTsysColRow != cNRow) {
856      cHaveTsys=0;
857    }
858  }
859  if (cHaveTsys) {
860    cTsysCol.get(cIdx, tsys, True);
861  } else {
862    Int numReceptor;
863    cNumReceptorCol.get(0, numReceptor);
864    tsys.resize(numReceptor);
865    tsys = 1.0f;
866  }
867  cSigmaCol.get(cIdx, sigma, True);
868
869  //get Tcal if available
870  if (cHaveTcal) {
871    Int nTcalColRow = cTcalCol.nrow();
872    uInt nBeam = cBeams.nelements();
873    uInt nIF = cIFs.nelements();
874    uInt nrws = nBeam * nIF;
875    if (nTcalColRow > 0) { 
876    // find tcal match with the data with the data time stamp
877      Double mjds = mjd*(24*3600);
878      Double dtcalTime;
879      if ( mjd > lastmjd || cIdx==0 ) {
880        //Table tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds));
881        tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds), nrws);
882        //DEBUG
883        //if (cIdx == 0) {
884        //  cerr<<"inital table retrieved"<<endl;
885        //}
886       
887      }
888
889      if (nBeam == 1) {
890        tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF, 1);
891      } else {
892        tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF &&
893                              tmptab.col("FEED_ID") == ibeam , 1);
894      }
895      //cerr<<"first subtab rows="<<tmptab.nrow()<<endl;
896      int syscalrow = tmptab2.nrow();
897      ROArrayColumn<Float> tcalCol(tmptab2, "TCAL");
898      ROScalarColumn<Double> tcalTimeCol(tmptab2, "TIME");
899      if (syscalrow==0) {
900        cerr<<"Cannot find any matching Tcal at/near the data timestamp."
901           << " Set Tcal=0.0"<<endl;
902      } else {
903        tcalCol.get(0, tcal);
904        tcalTimeCol.get(0,dtcalTime);
905        tcalTime = MVTime(dtcalTime/(24*3600)).string(MVTime::YMD);
906        //DEBUG
907        //cerr<<"cIdx:"<<cIdx<<" tcal="<<tcal<<" tcalTime="<<tcalTime<<endl;
908        tmptab.markForDelete();
909        tmptab2.markForDelete();
910      }
911    }
912    lastmjd = mjd;
913  }
914
915  // Calibration factors (if available).
916  calFctr.resize(cNPol(iIF));
917  if (cHaveCalFctr) {
918    cCalFctrCol.get(cIdx, calFctr);
919  } else {
920    calFctr = 0.0f;
921  }
922
923  // Baseline parameters (if available).
924  if (cHaveBaseLin) {
925    baseLin.resize(2,cNPol(iIF));
926    cBaseLinCol.get(cIdx, baseLin);
927
928    baseSub.resize(9,cNPol(iIF));
929    cBaseSubCol.get(cIdx, baseSub);
930
931  } else {
932    baseLin.resize(0,0);
933    baseSub.resize(0,0);
934  }
935  // Get spectral data.
936  if (cGetSpectra) {
937    Matrix<Float> tmpData;
938    Matrix<Bool>  tmpFlag;
939    if (cHaveDataCol) {
940      Matrix<Complex> tmpCmplxData;
941      Matrix<Float> tmpReData;
942      Matrix<Float> tmpImData;
943      //cerr<<"reading spectra..."<<endl;
944      //# TODO - should have a flag to user to select DATA or CORRECTED_DATA
945      //# currently just automatically determined, --- read CORRECTED one
946      //# if the column exist.
947      if (cHaveCorrectedDataCol) {
948        cCorrectedDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
949      } else {
950        cDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
951      }
952      tmpReData = real(tmpCmplxData);
953      tmpImData = imag(tmpCmplxData);
954      tmpData = sqrt(tmpReData*tmpReData + tmpImData*tmpImData);
955    } else {
956      cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
957    }
958    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
959
960    // Transpose spectra.
961    Int nPol = tmpData.nrow();
962    spectra.resize(nChan, nPol);
963    flagged.resize(nChan, nPol);
964    if (cEndChan(iIF) >= cStartChan(iIF)) {
965      // Simple transposition.
966      for (Int ipol = 0; ipol < nPol; ipol++) {
967        for (Int ichan = 0; ichan < nChan; ichan++) {
968          spectra(ichan,ipol) = tmpData(ipol,ichan);
969          flagged(ichan,ipol) = tmpFlag(ipol,ichan);
970        }
971      }
972
973    } else {
974      // Transpose with inversion.
975      Int jchan = nChan - 1;
976      for (Int ipol = 0; ipol < nPol; ipol++) {
977        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
978          spectra(ichan,ipol) = tmpData(ipol,jchan);
979          flagged(ichan,ipol) = tmpFlag(ipol,jchan);
980        }
981      }
982    }
983  }
984
985  // Get cross-polarization data.
986  if (cGetXPol) {
987    //cerr<<"cGetXPol="<<cGetXPol<<endl;
988    //cerr<<"cHaveXCalFctr="<<cHaveXCalFctr<<endl;
989
990    if (cHaveXCalFctr) {
991      cXCalFctrCol.get(cIdx, xCalFctr);
992    } else {
993      xCalFctr = Complex(0.0f, 0.0f);
994    }
995
996    if(!cATF) {
997      cDataCol.get(cIdx, xPol, True);
998
999      if (cEndChan(iIF) < cStartChan(iIF)) {
1000        Complex ctmp;
1001        Int jchan = nChan - 1;
1002        for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
1003          ctmp = xPol(ichan);
1004          xPol(ichan) = xPol(jchan);
1005          xPol(jchan) = ctmp;
1006        }
1007      }
1008    }
1009  }
1010  /**
1011  cerr<<"scanNo="<<scanNo<<endl;
1012  cerr<<"cycleNo="<<cycleNo<<endl;
1013  cerr<<"mjd="<<mjd<<endl;
1014  cerr<<"interval="<<interval<<endl;
1015  cerr<<"fieldName="<<fieldName<<endl;
1016  cerr<<"srcNmae="<<srcName<<endl;
1017  cerr<<"srcDir="<<srcDir<<endl;
1018  cerr<<"srcPM="<<srcPM<<endl;
1019  cerr<<"srcVel="<<srcVel<<endl;
1020  cerr<<"obsMode="<<obsMode<<endl;
1021  cerr<<"IFno="<<IFno<<endl;
1022  cerr<<"refFreq="<<refFreq<<endl;
1023  cerr<<"tcal="<<tcal<<endl;
1024  cerr<<"direction="<<direction<<endl;
1025  cerr<<"scanRate="<<scanRate<<endl;
1026  cerr<<"tsys="<<tsys<<endl;
1027  cerr<<"sigma="<<sigma<<endl;
1028  cerr<<"calFctr="<<calFctr<<endl;
1029  cerr<<"baseLin="<<baseLin<<endl;
1030  cerr<<"baseSub="<<baseSub<<endl;
1031  cerr<<"spectra="<<spectra.shape()<<endl;
1032  cerr<<"flagged="<<flagged.shape()<<endl;
1033  cerr<<"xCalFctr="<<xCalFctr<<endl;
1034  cerr<<"xPol="<<xPol<<endl;
1035  **/
1036  cIdx++;
1037
1038  return 0;
1039}
1040
1041//--------------------------------------------------------- PKSMS2reader::read
1042
1043// Read the next data record, just the basics.
1044
1045Int PKSMS2reader::read(
1046        Int           &IFno,
1047        Vector<Float> &tsys,
1048        Vector<Float> &calFctr,
1049        Matrix<Float> &baseLin,
1050        Matrix<Float> &baseSub,
1051        Matrix<Float> &spectra,
1052        Matrix<uChar> &flagged)
1053{
1054  if (!cMSopen) {
1055    return 1;
1056  }
1057
1058  // Check for EOF.
1059  if (cIdx >= cNRow) {
1060    return -1;
1061  }
1062
1063  // Find the next selected beam and IF.
1064  Int ibeam;
1065  Int iIF;
1066  Int iDataDesc;
1067  while (True) {
1068    ibeam = cBeamNoCol(cIdx);
1069    //iIF   = cDataDescIdCol(cIdx);
1070    iDataDesc   = cDataDescIdCol(cIdx);
1071    iIF   = cSpWinIdCol(iDataDesc);
1072    if (cBeams(ibeam) && cIFs(iIF)) {
1073      break;
1074    }
1075
1076    // Check for EOF.
1077    if (++cIdx >= cNRow) {
1078      return -1;
1079    }
1080  }
1081
1082  IFno = iIF + 1;
1083  // Get Tsys assuming that entries in the SYSCAL table match the main table.
1084  cTsysCol.get(cIdx, tsys, True);
1085
1086  // Calibration factors (if available).
1087  if (cHaveCalFctr) {
1088    cCalFctrCol.get(cIdx, calFctr, True);
1089  } else {
1090    calFctr.resize(cNPol(iIF));
1091    calFctr = 0.0f;
1092  }
1093
1094  // Baseline parameters (if available).
1095  if (cHaveBaseLin) {
1096    baseLin.resize(2,cNPol(iIF));
1097    cBaseLinCol.get(cIdx, baseLin);
1098
1099    baseSub.resize(9,cNPol(iIF));
1100    cBaseSubCol.get(cIdx, baseSub);
1101
1102  } else {
1103    baseLin.resize(0,0);
1104    baseSub.resize(0,0);
1105  }
1106
1107  if (cGetSpectra) {
1108    // Get spectral data.
1109    Matrix<Float> tmpData;
1110    Matrix<Bool>  tmpFlag;
1111    if (cHaveDataCol) {
1112      Matrix<Complex> tmpCmplxData;
1113      cDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
1114      tmpData = real(tmpCmplxData);
1115    } else {
1116      cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
1117    }
1118    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
1119
1120    // Transpose spectra.
1121    Int nChan = tmpData.ncolumn();
1122    Int nPol  = tmpData.nrow();
1123    spectra.resize(nChan, nPol);
1124    flagged.resize(nChan, nPol);
1125    if (cEndChan(iIF) >= cStartChan(iIF)) {
1126      // Simple transposition.
1127      for (Int ipol = 0; ipol < nPol; ipol++) {
1128        for (Int ichan = 0; ichan < nChan; ichan++) {
1129          spectra(ichan,ipol) = tmpData(ipol,ichan);
1130          flagged(ichan,ipol) = tmpFlag(ipol,ichan);
1131        }
1132      }
1133
1134    } else {
1135      // Transpose with inversion.
1136      Int jchan = nChan - 1;
1137      for (Int ipol = 0; ipol < nPol; ipol++) {
1138        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
1139          spectra(ichan,ipol) = tmpData(ipol,jchan);
1140          flagged(ichan,ipol) = tmpFlag(ipol,jchan);
1141        }
1142      }
1143    }
1144  }
1145
1146  cIdx++;
1147
1148  return 0;
1149}
1150
1151//-------------------------------------------------------- PKSMS2reader::close
1152
1153// Close the MS.
1154
1155void PKSMS2reader::close()
1156{
1157  cPKSMS = MeasurementSet();
1158  cMSopen = False;
1159}
Note: See TracBrowser for help on using the repository browser.