source: trunk/external-alma/atnf/PKSIO/PKSMS2reader.cc @ 1880

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

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

An implementation of asapmath.splitant() is changed since
the new filler doesn't support antenna parameter at the
moment.

The default behavior of MS filler also changed.


File size: 42.4 KB
Line 
1//#---------------------------------------------------------------------------
2//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
3//#---------------------------------------------------------------------------
4//# livedata - processing pipeline for single-dish, multibeam spectral data.
5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
6//#
7//# This file is part of livedata.
8//#
9//# livedata is free software: you can redistribute it and/or modify it under
10//# the terms of the GNU General Public License as published by the Free
11//# Software Foundation, either version 3 of the License, or (at your option)
12//# any later version.
13//#
14//# livedata is distributed in the hope that it will be useful, but WITHOUT
15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17//# more details.
18//#
19//# You should have received a copy of the GNU General Public License along
20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
21//#
22//# Correspondence concerning livedata may be directed to:
23//#        Internet email: mcalabre@atnf.csiro.au
24//#        Postal address: Dr. Mark Calabretta
25//#                        Australia Telescope National Facility, CSIRO
26//#                        PO Box 76
27//#                        Epping NSW 1710
28//#                        AUSTRALIA
29//#
30//# http://www.atnf.csiro.au/computing/software/livedata.html
31//# $Id: PKSMS2reader.cc,v 19.23 2009-09-29 07:33:38 cal103 Exp $
32//#---------------------------------------------------------------------------
33//# Original: 2000/08/03, Mark Calabretta, ATNF
34//#---------------------------------------------------------------------------
35
36// AIPS++ includes.
37#include <casa/stdio.h>
38#include <casa/Arrays/ArrayMath.h>
39#include <casa/Arrays/Slice.h>
40#include <ms/MeasurementSets/MSColumns.h>
41#include <tables/Tables.h>
42#include <casa/Quanta/MVTime.h>
43#include <casa/Quanta/MVAngle.h>
44#include <casa/BasicMath/Math.h>
45#include <casa/Logging/LogIO.h>
46#include <casa/Utilities/Sort.h>
47#include <measures/Measures/MeasConvert.h>
48#include <measures/Measures/MEpoch.h>
49#include <measures/Measures/MeasRef.h>
50
51
52// Parkes includes.
53#include <atnf/pks/pks_maths.h>
54#include <atnf/PKSIO/PKSrecord.h>
55#include <atnf/PKSIO/PKSMS2reader.h>
56
57
58//------------------------------------------------- PKSMS2reader::PKSMS2reader
59
60// Default constructor.
61
62PKSMS2reader::PKSMS2reader()
63{
64  cMSopen = False;
65}
66
67//------------------------------------------------ PKSMS2reader::~PKSMS2reader
68
69PKSMS2reader::~PKSMS2reader()
70{
71  close();
72}
73
74//--------------------------------------------------------- PKSMS2reader::open
75
76// Open the MS for reading.
77
78Int PKSMS2reader::open(
79        const String msName,
80        const String antenna,
81        Vector<Bool> &beams,
82        Vector<Bool> &IFs,
83        Vector<uInt> &nChan,
84        Vector<uInt> &nPol,
85        Vector<Bool> &haveXPol,
86        Bool   &haveBase,
87        Bool   &haveSpectra)
88{
89  // Check that MS is readable.
90  if (!MS::isReadable(msName)) {
91    return 1;
92  }
93
94  if (cMSopen) {
95    close();
96  }
97
98  cPKSMS  = MeasurementSet(msName);
99
100  // data selection by antenna
101  if ( antenna.length() == 0 ) {
102    cAntId.resize( 1 ) ;
103    //cAntId[0] = 0 ;
104    ROScalarColumn<Int> ant1Col( cPKSMS, "ANTENNA1" ) ;
105    cAntId[0] = ant1Col(0) ;
106  }
107  else {
108    setupAntennaList( antenna ) ;
109    if ( cAntId.size() > 1 ) {
110      LogIO os( LogOrigin( "PKSMS2reader", "open()", WHERE ) ) ;
111      os << LogIO::WARN << "PKSMS2reader is not ready for multiple antenna selection. Use first antenna id " << cAntId[0] << "."<< LogIO::POST ;
112      Int tmp = cAntId[0] ;
113      cAntId.resize( 1 ) ;
114      cAntId[0] = tmp ;
115    }
116    stringstream ss ;
117    ss << "SELECT FROM $1 WHERE ANTENNA1 == ANTENNA2 && ANTENNA1 IN [" ;
118    for ( uInt i = 0 ; i < cAntId.size() ; i++ ) {
119      ss << cAntId[i] ;
120      if ( i == cAntId.size()-1 ) {
121        ss << "]" ;
122      }
123      else {
124        ss << "," ;
125      }
126    }
127    string taql = ss.str() ;
128    //cerr << "taql = " << taql << endl ;
129    cPKSMS = MeasurementSet( tableCommand( taql, cPKSMS ) ) ;
130  }
131
132  // taql access to the syscal table
133  cHaveSysCal = False;
134  if (cHaveSysCal=Table::isReadable(cPKSMS.sysCalTableName())) {
135    cSysCalTab = Table(cPKSMS.sysCalTableName());
136  }
137
138  // Lock the table for read access.
139  cPKSMS.lock(False);
140
141  cIdx    = 0;
142  lastmjd = 0.0;
143  cNRow   = cPKSMS.nrow();
144  cMSopen = True;
145
146  // Main MS table and subtable column access.
147  ROMSMainColumns         msCols(cPKSMS);
148  ROMSDataDescColumns     dataDescCols(cPKSMS.dataDescription());
149  ROMSFeedColumns         feedCols(cPKSMS.feed());
150  ROMSFieldColumns        fieldCols(cPKSMS.field());
151  ROMSPointingColumns     pointingCols(cPKSMS.pointing());
152  ROMSPolarizationColumns polarizationCols(cPKSMS.polarization());
153  ROMSSourceColumns       sourceCols(cPKSMS.source());
154  ROMSSpWindowColumns     spWinCols(cPKSMS.spectralWindow());
155  ROMSStateColumns        stateCols(cPKSMS.state());
156  ROMSSysCalColumns       sysCalCols(cPKSMS.sysCal());
157  ROMSWeatherColumns      weatherCols(cPKSMS.weather());
158  ROMSAntennaColumns      antennaCols(cPKSMS.antenna());
159
160  // Column accessors for required columns.
161  cScanNoCol.reference(msCols.scanNumber());
162  cTimeCol.reference(msCols.time());
163  cIntervalCol.reference(msCols.interval());
164
165  cFieldIdCol.reference(msCols.fieldId());
166  cFieldNameCol.reference(fieldCols.name());
167  cFieldDelayDirCol.reference(fieldCols.delayDir());
168
169  cSrcIdCol.reference(fieldCols.sourceId());
170  cSrcId2Col.reference(sourceCols.sourceId());
171  cSrcNameCol.reference(sourceCols.name());
172  cSrcDirCol.reference(sourceCols.direction());
173  cSrcPMCol.reference(sourceCols.properMotion());
174  cSrcRestFrqCol.reference(sourceCols.restFrequency());
175
176  cStateIdCol.reference(msCols.stateId());
177  cObsModeCol.reference(stateCols.obsMode());
178  cCalCol.reference(stateCols.cal());
179  cSigStateCol.reference(stateCols.sig());
180  cRefStateCol.reference(stateCols.ref());
181
182  cDataDescIdCol.reference(msCols.dataDescId());
183  cSpWinIdCol.reference(dataDescCols.spectralWindowId());
184  cChanFreqCol.reference(spWinCols.chanFreq());
185  cTotBWCol.reference(spWinCols.totalBandwidth());
186
187  cWeatherTimeCol.reference(weatherCols.time());
188  cTemperatureCol.reference(weatherCols.temperature());
189  cPressureCol.reference(weatherCols.pressure());
190  cHumidityCol.reference(weatherCols.relHumidity());
191
192  cBeamNoCol.reference(msCols.feed1());
193  cPointingCol.reference(pointingCols.direction());
194  cPointingTimeCol.reference(pointingCols.time());
195  cSigmaCol.reference(msCols.sigma());
196  cNumReceptorCol.reference(feedCols.numReceptors());
197
198  // Optional columns.
199  cHaveTsys = False;
200  cHaveTcal = False;
201  if ((cHaveSrcVel = cPKSMS.source().tableDesc().isColumn("SYSVEL"))) {
202    cSrcVelCol.attach(cPKSMS.source(), "SYSVEL");
203  }
204
205  if (cHaveSysCal && (cHaveTsys = cPKSMS.sysCal().tableDesc().isColumn("TSYS"))) {
206    cTsysCol.attach(cPKSMS.sysCal(), "TSYS");
207  }
208 
209  if (cHaveSysCal && (cHaveTcal = cPKSMS.sysCal().tableDesc().isColumn("TCAL"))) {
210    cTcalCol.attach(cPKSMS.sysCal(), "TCAL");
211  }
212
213  if ((cHaveCalFctr = cPKSMS.tableDesc().isColumn("CALFCTR"))) {
214    cCalFctrCol.attach(cPKSMS, "CALFCTR");
215  }
216
217  if ((cHaveBaseLin = cPKSMS.tableDesc().isColumn("BASELIN"))) {
218    cBaseLinCol.attach(cPKSMS, "BASELIN");
219    cBaseSubCol.attach(cPKSMS, "BASESUB");
220  }
221
222  // Spectral data should always be present.
223  haveSpectra = True;
224  cHaveDataCol = False;
225  cHaveCorrectedDataCol = False;
226  ROMSObservationColumns observationCols(cPKSMS.observation());
227  //String telName = observationCols.telescopeName()(0);
228  cTelName = observationCols.telescopeName()(0);
229  //cATF = cTelName.contains("ATF");
230  //cOSF = cTelName.contains("OSF");
231  //cALMA = cTelName.contains("ALMA");
232  cALMA = cTelName.contains("ATF")||cTelName.contains("OSF")||
233           cTelName.contains("ALMA");
234
235  if (cHaveDataCol = cPKSMS.isColumn(MSMainEnums::DATA)) {
236    if (cALMA) {
237      //try to read a single baseline interferometeric data
238      //and treat it as single dish data
239      //maybe extended for ALMA commissioning later
240      cDataCol.reference(msCols.data());
241      if (cHaveCorrectedDataCol = cPKSMS.isColumn(MSMainEnums::CORRECTED_DATA)) {
242        //cerr<<"Do have CORRECTED_DATA column"<<endl;
243        cCorrectedDataCol.reference(msCols.correctedData());
244      }
245    }
246  }
247  else {
248    cFloatDataCol.reference(msCols.floatData());
249  }
250  cFlagCol.reference(msCols.flag());
251  cFlagRowCol.reference(msCols.flagRow());
252
253  if (cGetXPol = (cPKSMS.isColumn(MSMainEnums::DATA) && (!cALMA))) {
254    if ((cHaveXCalFctr = cPKSMS.tableDesc().isColumn("XCALFCTR"))) {
255      cXCalFctrCol.attach(cPKSMS, "XCALFCTR");
256    }
257
258    cDataCol.reference(msCols.data());
259  }
260
261  // Find which beams are present in the data.
262  Vector<Int> beamNos = cBeamNoCol.getColumn();
263  Int maxBeamNo = max(beamNos) + 1;
264  beams.resize(maxBeamNo);
265
266  beams = False;
267  for (uInt irow = 0; irow < beamNos.nelements(); irow++) {
268    beams(beamNos(irow)) = True;
269  }
270
271
272  // Number of IFs.
273  //uInt nIF = dataDescCols.nrow();
274  uInt nIF =spWinCols.nrow();
275  Vector<Int> spWinIds = cSpWinIdCol.getColumn() ;
276  IFs.resize(nIF);
277  IFs = True;
278  for ( Int ispw = 0 ; ispw < nIF ; ispw++ ) {
279    if ( allNE( ispw, spWinIds ) ) {
280      IFs(ispw) = False ;
281    }
282  }
283
284  // Number of polarizations and channels in each IF.
285  ROScalarColumn<Int> numChanCol(spWinCols.numChan());
286
287  ROScalarColumn<Int> polIdCol(dataDescCols.polarizationId());
288  ROScalarColumn<Int> numPolCol(polarizationCols.numCorr());
289
290  nChan.resize(nIF);
291  nPol.resize(nIF);
292  for (uInt iIF = 0; iIF < nIF; iIF++) {
293    if ( IFs(iIF) ) {
294      nChan(iIF) = numChanCol(cSpWinIdCol(iIF)) ;
295      nPol(iIF) = numPolCol(polIdCol(iIF)) ;
296    }
297    else {
298      nChan(iIF) = 0 ;
299      nPol(iIF) = 0 ;
300    }
301  }
302
303  // Cross-polarization data present?
304  haveXPol.resize(nIF);
305  haveXPol = False;
306
307  if (cGetXPol && !(cALMA)) {
308    for (Int irow = 0; irow < cNRow; irow++) {
309      if (cDataCol.isDefined(irow)) {
310        Int iIF = cDataDescIdCol(irow);
311        haveXPol(iIF) = True;
312      }
313    }
314  }
315
316
317  // Initialize member data.
318  cBeams.assign(beams);
319  cIFs.assign(IFs);
320  cNChan.assign(nChan);
321  cNPol.assign(nPol);
322  cHaveXPol.assign(haveXPol);
323
324
325  // Default channel range selection.
326  cStartChan.resize(nIF);
327  cEndChan.resize(nIF);
328  cRefChan.resize(nIF);
329
330  for (uInt iIF = 0; iIF < nIF; iIF++) {
331    cStartChan(iIF) = 1;
332    cEndChan(iIF)   = cNChan(iIF);
333    cRefChan(iIF)   = cNChan(iIF)/2 + 1;
334  }
335
336  Slice all;
337  cDataSel.resize(nIF);
338  cDataSel = Slicer(all, all);
339
340  cScanNo  = 0;
341  cCycleNo = 1;
342  cTime    = cTimeCol(0);
343
344  return 0;
345}
346
347//---------------------------------------------------- PKSMS2reader::getHeader
348
349// Get parameters describing the data.
350
351Int PKSMS2reader::getHeader(
352        String &observer,
353        String &project,
354        String &antName,
355        Vector<Double> &antPosition,
356        // before merge...
357        //String &obsMode,
358        String &obsType,
359        String &bunit,
360        Float  &equinox,
361        String &dopplerFrame,
362        Double &mjd,
363        Double &refFreq,
364        Double &bandwidth)
365{
366  if (!cMSopen) {
367    return 1;
368  }
369
370  // Observer and project.
371  ROMSObservationColumns observationCols(cPKSMS.observation());
372  observer = observationCols.observer()(0);
373  project  = observationCols.project()(0);
374
375  // Antenna name and ITRF coordinates.
376  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
377  //antName = antennaCols.name()(0);
378  antName = antennaCols.name()(cAntId[0]);
379  if (cALMA) {
380     antName = cTelName + "-" + antName;
381  }
382  //antPosition = antennaCols.position()(0);
383  antPosition = antennaCols.position()(cAntId[0]);
384
385  // Observation type.
386  if (cObsModeCol.nrow()) {
387    obsType = cObsModeCol(0);
388    if (obsType == "\0") obsType = "RF";
389  } else {
390    obsType = "RF";
391  }
392
393  bunit = "";
394  if (cHaveDataCol) {
395    const TableRecord& keywordSet2
396       = cDataCol.columnDesc().keywordSet();
397    if(keywordSet2.isDefined("UNIT")) {
398      bunit = keywordSet2.asString("UNIT");
399    }
400  } else {
401    const TableRecord& keywordSet
402       = cFloatDataCol.columnDesc().keywordSet();
403    if(keywordSet.isDefined("UNIT")) {
404      bunit = keywordSet.asString("UNIT");
405    }
406  }
407
408/***
409  const TableRecord& keywordSet
410       = cFloatDataCol.columnDesc().keywordSet();
411  if(keywordSet.isDefined("UNIT")) {
412    fluxunit = keywordSet.asString("UNIT");
413  }
414***/
415  // Coordinate equinox.
416  ROMSPointingColumns pointingCols(cPKSMS.pointing());
417  String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
418                    asString("Ref");
419  cDirRef = dirref;
420  if (dirref =="AZELGEO" || dirref == "AZEL") {
421     dirref = "J2000";
422  }
423  sscanf(dirref.chars()+1, "%f", &equinox);
424
425  // Frequency/velocity reference frame.
426  ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
427  dopplerFrame = MFrequency::showType(spWinCols.measFreqRef()(0));
428
429  // Translate to FITS standard names.
430  if (dopplerFrame == "TOPO") {
431    dopplerFrame = "TOPOCENT";
432  } else if (dopplerFrame == "GEO") {
433    dopplerFrame = "GEOCENTR";
434  } else if (dopplerFrame == "BARY") {
435    dopplerFrame = "BARYCENT";
436  } else if (dopplerFrame == "GALACTO") {
437    dopplerFrame = "GALACTOC";
438  } else if (dopplerFrame == "LGROUP") {
439    dopplerFrame = "LOCALGRP";
440  } else if (dopplerFrame == "CMB") {
441    dopplerFrame = "CMBDIPOL";
442  } else if (dopplerFrame == "REST") {
443    dopplerFrame = "SOURCE";
444  }
445
446  // MJD at start of observation.
447  mjd = cTimeCol(0)/86400.0;
448
449  // Reference frequency and bandwidth.
450  refFreq   = spWinCols.refFrequency()(0);
451  bandwidth = spWinCols.totalBandwidth()(0);
452
453  return 0;
454}
455
456//-------------------------------------------------- PKSMS2reader::getFreqInfo
457
458// Get frequency parameters for each IF.
459
460Int PKSMS2reader::getFreqInfo(
461        Vector<Double> &startFreq,
462        Vector<Double> &endFreq)
463{
464  uInt nIF = cIFs.nelements();
465  startFreq.resize(nIF);
466  endFreq.resize(nIF);
467
468  for (uInt iIF = 0; iIF < nIF; iIF++) {
469    Vector<Double> chanFreq = cChanFreqCol(iIF);
470
471    Int nChan = chanFreq.nelements();
472    startFreq(iIF) = chanFreq(0);
473    endFreq(iIF)   = chanFreq(nChan-1);
474  }
475
476  return 0;
477}
478
479//------------------------------------------------------- PKSMS2reader::select
480
481// Set data selection by beam number and channel.
482
483uInt PKSMS2reader::select(
484        const Vector<Bool> beamSel,
485        const Vector<Bool> IFsel,
486        const Vector<Int>  startChan,
487        const Vector<Int>  endChan,
488        const Vector<Int>  refChan,
489        const Bool getSpectra,
490        const Bool getXPol,
491        const Bool getFeedPos,
492        const Bool getPointing,
493        const Int  coordSys)
494{
495  if (!cMSopen) {
496    return 1;
497  }
498
499  // Beam selection.
500  uInt nBeam = cBeams.nelements();
501  uInt nBeamSel = beamSel.nelements();
502  for (uInt ibeam = 0; ibeam < nBeam; ibeam++) {
503    if (ibeam < nBeamSel) {
504      cBeams(ibeam) = beamSel(ibeam);
505    } else {
506      cBeams(ibeam) = False;
507    }
508  }
509
510  uInt nIF = cIFs.nelements();
511  uInt maxNChan = 0;
512  for (uInt iIF = 0; iIF < nIF; iIF++) {
513    // IF selection.
514    if (iIF < IFsel.nelements()) {
515      cIFs(iIF) = IFsel(iIF);
516    } else {
517      cIFs(iIF) = False;
518    }
519
520    if (!cIFs(iIF)) continue;
521
522
523    // Channel selection.
524    if (iIF < startChan.nelements()) {
525      cStartChan(iIF) = startChan(iIF);
526
527      if (cStartChan(iIF) <= 0) {
528        cStartChan(iIF) += cNChan(iIF);
529      } else if (cStartChan(iIF) > Int(cNChan(iIF))) {
530        cStartChan(iIF)  = cNChan(iIF);
531      }
532    }
533
534    if (iIF < endChan.nelements()) {
535      cEndChan(iIF) = endChan(iIF);
536
537      if (cEndChan(iIF) <= 0) {
538        cEndChan(iIF) += cNChan(iIF);
539      } else if (cEndChan(iIF) > Int(cNChan(iIF))) {
540        cEndChan(iIF)  = cNChan(iIF);
541      }
542    }
543
544    if (iIF < refChan.nelements()) {
545      cRefChan(iIF) = refChan(iIF);
546    } else {
547      cRefChan(iIF) = cStartChan(iIF);
548      if (cStartChan(iIF) <= cEndChan(iIF)) {
549        cRefChan(iIF) += (cEndChan(iIF) - cStartChan(iIF) + 1)/2;
550      } else {
551        cRefChan(iIF) -= (cStartChan(iIF) - cEndChan(iIF) + 1)/2;
552      }
553    }
554
555    uInt nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
556    if (maxNChan < nChan) {
557      maxNChan = nChan;
558    }
559
560    // Inverted Slices are not allowed.
561    Slice outPols;
562    Slice outChans(min(cStartChan(iIF),cEndChan(iIF))-1, nChan);
563    cDataSel(iIF) = Slicer(outPols, outChans);
564  }
565
566  // Get spectral data?
567  cGetSpectra = getSpectra;
568
569  // Get cross-polarization data?
570  cGetXPol = cGetXPol && getXPol;
571
572  // Get feed positions?  (Not available.)
573  cGetFeedPos = False;
574
575  // Get Pointing data (for MS)
576  cGetPointing = getPointing;
577
578  // Coordinate system?  (Only equatorial available.)
579  cCoordSys = 0;
580
581  return maxNChan;
582}
583
584//---------------------------------------------------- PKSMS2reader::findRange
585
586// Find the range of the data in time and position.
587
588Int PKSMS2reader::findRange(
589        Int    &nRow,
590        Int    &nSel,
591        Vector<Double> &timeSpan,
592        Matrix<Double> &positions)
593{
594  if (!cMSopen) {
595    return 1;
596  }
597
598  nRow = cNRow;
599
600  // Find the number of rows selected.
601  nSel = 0;
602  Vector<Bool> sel(nRow);
603  for (Int irow = 0; irow < nRow; irow++) {
604    if ((sel(irow) = cBeams(cBeamNoCol(irow)) &&
605                     cIFs(cDataDescIdCol(irow)))) {
606      nSel++;
607    }
608  }
609
610  // Find the time range (s).
611  timeSpan.resize(2);
612  timeSpan(0) = cTimeCol(0);
613  timeSpan(1) = cTimeCol(nRow-1);
614
615  // Retrieve positions for selected data.
616  Int isel = 0;
617  positions.resize(2,nSel);
618  for (Int irow = 0; irow < nRow; irow++) {
619    if (sel(irow)) {
620      Matrix<Double> pointingDir = cPointingCol(cFieldIdCol(irow));
621      positions.column(isel++) = pointingDir.column(0);
622    }
623  }
624
625  return 0;
626}
627
628//--------------------------------------------------------- PKSMS2reader::read
629
630// Read the next data record.
631
632/**
633Int PKSMS2reader::read(
634        Int             &scanNo,
635        Int             &cycleNo,
636        Double          &mjd,
637        Double          &interval,
638        String          &fieldName,
639        String          &srcName,
640        Vector<Double>  &srcDir,
641        Vector<Double>  &srcPM,
642        Double          &srcVel,
643        String          &obsMode,
644        Int             &IFno,
645        Double          &refFreq,
646        Double          &bandwidth,
647        Double          &freqInc,
648        Vector<Double>  &restFreq,
649        Vector<Float>   &tcal,
650        String          &tcalTime,
651        Float           &azimuth,
652        Float           &elevation,
653        Float           &parAngle,
654        Float           &focusAxi,
655        Float           &focusTan,
656        Float           &focusRot,
657        Float           &temperature,
658        Float           &pressure,
659        Float           &humidity,
660        Float           &windSpeed,
661        Float           &windAz,
662        Int             &refBeam,
663        Int             &beamNo,
664        Vector<Double>  &direction,
665        Vector<Double>  &scanRate,
666        Vector<Float>   &tsys,
667        Vector<Float>   &sigma,
668        Vector<Float>   &calFctr,
669        Matrix<Float>   &baseLin,
670        Matrix<Float>   &baseSub,
671        Matrix<Float>   &spectra,
672        Matrix<uChar>   &flagged,
673        uInt            &flagrow,
674        Complex         &xCalFctr,
675        Vector<Complex> &xPol)
676**/
677Int PKSMS2reader::read(PKSrecord &pksrec)
678{
679  LogIO os( LogOrigin( "PKSMS2reader", "read()", WHERE ) ) ;
680
681  if (!cMSopen) {
682    return 1;
683  }
684
685  // Check for EOF.
686  if (cIdx >= cNRow) {
687    return -1;
688  }
689
690  // Find the next selected beam and IF.
691  Int ibeam;
692  Int iIF;
693  Int iDataDesc;
694
695  while (True) {
696    ibeam = cBeamNoCol(cIdx);
697    iDataDesc   = cDataDescIdCol(cIdx);
698    iIF   =cSpWinIdCol(iDataDesc);
699    if (cBeams(ibeam) && cIFs(iIF)) {
700      break;
701    }
702
703    // Check for EOF.
704    if (++cIdx >= cNRow) {
705      return -1;
706    }
707  }
708  // Renumerate scan no. Here still is 1-based
709  //scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
710  //scanNo = cScanNoCol(cIdx);
711  pksrec.scanNo = cScanNoCol(cIdx);
712
713  if (pksrec.scanNo != cScanNo) {
714    // Start of new scan.
715    cScanNo  = pksrec.scanNo;
716    cCycleNo = 1;
717    cTime    = cTimeCol(cIdx);
718  }
719
720  Double time = cTimeCol(cIdx);
721  pksrec.mjd      = time/86400.0;
722  pksrec.interval = cIntervalCol(cIdx);
723
724  // Reconstruct the integration cycle number; due to small latencies the
725  // integration time is usually slightly less than the time between cycles,
726  // resetting cTime will prevent the difference from accumulating.
727  cCycleNo += nint((time - cTime)/pksrec.interval);
728  pksrec.cycleNo = cCycleNo;
729  cTime = time;
730
731  Int fieldId = cFieldIdCol(cIdx);
732  pksrec.fieldName = cFieldNameCol(fieldId);
733
734  Int srcId = cSrcIdCol(fieldId);
735  //For source with multiple spectral window setting, this is not
736  // correct. Source name of srcId may not be at 'srcId'th row of SrcNameCol
737  //srcName = cSrcNameCol(srcId);
738  for (uInt irow = 0; irow < cSrcId2Col.nrow(); irow++) {
739    if (cSrcId2Col(irow) == srcId) {
740      //srcName = cSrcNameCol(irow);
741      pksrec.srcName = cSrcNameCol(irow);
742    }
743  }
744
745  pksrec.srcDir  = cSrcDirCol(srcId);
746  pksrec.srcPM   = cSrcPMCol(srcId);
747
748  // Systemic velocity.
749  if (!cHaveSrcVel || cALMA) {
750    pksrec.srcVel = 0.0f;
751  } else {
752    pksrec.srcVel = cSrcVelCol(srcId)(IPosition(1,0));
753  }
754
755  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
756  //String telescope = antennaCols.name()(0);
757  String telescope = antennaCols.name()(cAntId[0]);
758  Bool cGBT = telescope.contains("GBT");
759  //Bool cPM = telescope.contains("PM"); // ACA TP antenna
760  //Bool cDV = telescope.contains("DV"); // VERTEX
761  //Bool cCM = telescope.contains("CM"); // ACA 7m antenna
762  //Bool cALMA = cPM || cDV || cCM ;
763  // Observation type.
764  // check if State Table exist
765  //Bool cHaveStateTab=Table::isReadable(cPKSMS.stateTableName());
766  Int stateId = 0;
767  Int StateNRow = 0;
768  StateNRow=cObsModeCol.nrow();
769  if (Table::isReadable(cPKSMS.stateTableName())) {
770        pksrec.obsType = " ";
771    if (StateNRow > 0) {
772      stateId = cStateIdCol(cIdx);
773      if (stateId == -1) {
774        //pksrec.obsType = " ";
775      } else {
776        pksrec.obsType = cObsModeCol(stateId);
777        Bool sigState =cSigStateCol(stateId);
778        Bool refState =cRefStateCol(stateId);
779        //DEBUG
780        //cerr <<"stateid="<<stateId<<" obsmode="<<pksrec.obsType<<endl;
781        if (cGBT) {
782          // split the obsType string and append a proper label
783          // (these are GBT specific)
784          int epos = pksrec.obsType.find_first_of(':');
785          int nextpos = pksrec.obsType.find_first_of(':',epos+1);
786          string obsMode1 = pksrec.obsType.substr(0,epos);
787          string obsMode2 = pksrec.obsType.substr(epos+1,nextpos-epos-1);
788     
789          //cerr <<"obsMode2= "<<obsMode2<<endl;
790          if (!pksrec.srcName.contains("_ps")
791              &&!pksrec.srcName.contains("_psr")
792              &&!pksrec.srcName.contains("_nod")
793              &&!pksrec.srcName.contains("_fs")
794              &&!pksrec.srcName.contains("_fsr")) {
795            // if Nod mode observation , append '_nod'
796            if (obsMode1 == "Nod") {
797              //pksrec.srcName.append("_nod");
798              pksrec.srcType = SrcType::NOD ;
799            } else if (obsMode1 == "OffOn") {
800            // for GBT position switch observations (OffOn or OnOff)
801              //if (obsMode2 == "PSWITCHON") pksrec.srcName.append("_ps");
802              //if (obsMode2 == "PSWITCHOFF") pksrec.srcName.append("_psr");
803              if (obsMode2 == "PSWITCHON") pksrec.srcType = SrcType::PSON ;
804              if (obsMode2 == "PSWITCHOFF") pksrec.srcType = SrcType::PSOFF ;
805            } else {
806              if (obsMode2 == "FSWITCH") {
807              // for GBT frequency switch mode
808                //if (sigState) pksrec.srcName.append("_fs");
809                //if (refState) pksrec.srcName.append("_fsr");
810                if (sigState) pksrec.srcType = SrcType::FSON ;
811                if (refState) pksrec.srcType = SrcType::FSOFF ;
812              }
813            }
814          }
815        }
816        else if (cALMA) {
817          // ALMA tag
818          // split the obsType string and append a proper label
819          string substr[1] ;
820          int numSubstr = split( pksrec.obsType, substr, 1, "," );
821          String obsType = String( substr[0] );
822          int epos = obsType.find_first_of('.');
823          int nextpos = obsType.find_first_of('.',epos+1);
824          string obsMode1 = obsType.substr(0,epos);
825          string obsMode2 = obsType.substr(epos+1,nextpos-epos-1);
826     
827          //cerr <<"obsMode2= "<<obsMode2<<endl;
828          // Current OBS_MODE format:
829          //
830          //     ON: OBSERVE_TARGET.ON_SOURCE
831          //    OFF: OBSERVE_TARGET.OFF_SOURCE
832          //
833          if (obsMode1 == "OBSERVE_TARGET") {
834            //if (obsMode2 == "ON_SOURCE") pksrec.srcName.append("_pson");
835            //if (obsMode2 == "OFF_SOURCE") pksrec.srcName.append("_psoff");
836            if (obsMode2 == "ON_SOURCE") pksrec.srcType = SrcType::PSON ;
837            if (obsMode2 == "OFF_SOURCE") pksrec.srcType = SrcType::PSOFF ;
838          }
839        }
840      }
841    }
842  }
843  // CAL state
844  // this should be apply just for GBT data?
845  Double Cal;
846  if (stateId==-1 || StateNRow==0) {
847    Cal = 0;
848  } else {
849    Cal = cCalCol(stateId);
850  }
851  if (cGBT) {
852    if (Cal > 0 && !pksrec.srcName.contains("_calon")) {
853      //pksrec.srcName.append("_calon");
854      if ( pksrec.srcType == SrcType::NOD )
855        pksrec.srcType = SrcType::NODCAL ;
856      else if ( pksrec.srcType == SrcType::PSON )
857        pksrec.srcType = SrcType::PONCAL ;
858      else if ( pksrec.srcType == SrcType::PSOFF )
859        pksrec.srcType = SrcType::POFFCAL ;
860      else if ( pksrec.srcType == SrcType::FSON )
861        pksrec.srcType = SrcType::FONCAL ;
862      else if ( pksrec.srcType == SrcType::FSOFF )
863        pksrec.srcType = SrcType::FOFFCAL ;
864      else
865        pksrec.srcName.append("_calon");
866    }
867  }
868
869  pksrec.IFno = iIF + 1;
870  Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
871 
872  // Minimal handling on continuum data.
873  Vector<Double> chanFreq = cChanFreqCol(iIF);
874  if (nChan == 1) {
875    //pksrec.freqInc  = chanFreq(0);
876    pksrec.freqInc  = cTotBWCol(iIF);
877    pksrec.refFreq  = chanFreq(0);
878    pksrec.restFreq.resize(1);
879    pksrec.restFreq[0] = 0.0f;
880  } else {
881 
882    if (cStartChan(iIF) <= cEndChan(iIF)) {
883      pksrec.freqInc = chanFreq(1) - chanFreq(0);
884    } else {
885      pksrec.freqInc = chanFreq(0) - chanFreq(1);
886    }
887
888    pksrec.refFreq  = chanFreq(cRefChan(iIF)-1);
889
890    Bool HaveSrcRestFreq= cSrcRestFrqCol.isDefined(srcId);
891    if (HaveSrcRestFreq) {
892      //restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
893      //restFreq = cSrcRestFrqCol(srcId);
894      pksrec.restFreq = cSrcRestFrqCol(srcId);
895    } else {
896      pksrec.restFreq.resize(1);
897      pksrec.restFreq[0] = 0.0f;
898    }
899  }
900  //pksrec.bandwidth = abs(pksrec.freqInc * nChan);
901  pksrec.bandwidth = abs(cTotBWCol(0));
902
903  pksrec.tcal.resize(cNPol(iIF));
904  pksrec.tcal      = 0.0f;
905  pksrec.tcalTime  = "";
906//  pksrec.azimuth   = 0.0f;
907//  pksrec.elevation = 0.0f;
908  pksrec.parAngle  = 0.0f;
909
910  pksrec.focusAxi  = 0.0f;
911  pksrec.focusTan  = 0.0f;
912  pksrec.focusRot  = 0.0f;
913
914  // Find the appropriate entry in the WEATHER subtable.
915  //Bool cHaveStateTab=Table::isReadable(cPKSMS.stateTableName());
916  Bool cHaveWeatherTab = Table::isReadable(cPKSMS.weatherTableName());
917  Int weatherIdx=-1;
918  if (cHaveWeatherTab) {
919    Vector<Double> wTimes = cWeatherTimeCol.getColumn();
920    for (weatherIdx = wTimes.nelements()-1; weatherIdx >= 0; weatherIdx--) {
921      if (cWeatherTimeCol(weatherIdx) <= time) {
922        break;
923      }
924    }
925  }
926
927  if (weatherIdx < 0 || !cHaveWeatherTab) {
928    // No appropriate WEATHER entry.
929    pksrec.temperature = 0.0f;
930    pksrec.pressure    = 0.0f;
931    pksrec.humidity    = 0.0f;
932  } else {
933    pksrec.temperature = cTemperatureCol(weatherIdx);
934    pksrec.pressure    = cPressureCol(weatherIdx);
935    pksrec.humidity    = cHumidityCol(weatherIdx);
936  }
937
938  pksrec.windSpeed = 0.0f;
939  pksrec.windAz    = 0.0f;
940
941  pksrec.refBeam = 0;
942  pksrec.beamNo  = ibeam + 1;
943
944  //pointing/azel
945  MVPosition mvpos(antennaCols.position()(cAntId[0]));
946  MPosition mp(mvpos);
947  Quantum<Double> qt(time,"s");
948  MVEpoch mvt(qt);
949  MEpoch me(mvt);
950  MeasFrame frame(mp, me);
951  MDirection md;
952  pksrec.pCode = 0;
953  pksrec.rateAge = 0.0f;
954  pksrec.paRate = 0.0f;
955  if (cGetPointing) {
956    //cerr << "get pointing data ...." << endl;
957    ROScalarColumn<Int> pAntIdCol ;
958    ROScalarColumn<Double> psTimeCol ;
959    Table ptTable = cPKSMS.pointing() ;
960    MSPointing selPtTab( ptTable( ptTable.col("ANTENNA_ID") == cAntId[0] ) ) ;
961    pAntIdCol.attach( selPtTab, "ANTENNA_ID" ) ;
962    Vector<Int> antIds = pAntIdCol.getColumn() ;
963    psTimeCol.attach( selPtTab, "TIME" ) ;
964    Vector<Double> pTimes = psTimeCol.getColumn();
965    Bool doInterp = False ;
966    Int PtIdx=-1;
967    for (PtIdx = pTimes.nelements()-1; PtIdx >= 0; PtIdx--) {
968      if ( pTimes[PtIdx] == time ) {
969        break ;
970      }
971      else if ( pTimes[PtIdx] < time ) {
972        if ( PtIdx != pTimes.nelements()-1 ) {
973          doInterp = True ;
974        }
975        break ;
976      }
977    }
978    if ( PtIdx == -1 ) {
979      PtIdx = 0 ;
980    }
981    //cerr << "got index=" << PtIdx << endl;
982    Matrix<Double> pointingDir = cPointingCol(PtIdx);
983    ROMSPointingColumns PtCols( selPtTab ) ;
984    Vector<Double> pointingDirVec ;
985    if ( doInterp ) {
986      Double dt1 = time - pTimes[PtIdx] ;
987      Double dt2 = pTimes[PtIdx+1] - time ;
988      Vector<Double> dirVec1 = pointingDir.column(0) ;
989      Matrix<Double> pointingDir2 = cPointingCol(PtIdx+1) ;
990      Vector<Double> dirVec2 = pointingDir2.column(0) ;
991      pointingDirVec = (dt1*dirVec2+dt2*dirVec1)/(dt1+dt2) ;
992      Vector<MDirection> vmd1(1) ;
993      Vector<MDirection> vmd2(1) ;
994      PtCols.directionMeasCol().get(PtIdx,vmd1) ;
995      Vector<Double> angle1 = vmd1(0).getAngle().getValue("rad") ;
996      PtCols.directionMeasCol().get(PtIdx+1,vmd2) ;
997      Vector<Double> angle2 = vmd2(0).getAngle().getValue("rad") ;
998      Vector<Double> angle = (dt1*angle2+dt2*angle1)/(dt1+dt2) ;
999      Quantum< Vector<Double> > qangle( angle, "rad" ) ;
1000      String typeStr = vmd1(0).getRefString() ;
1001      //cerr << "vmd1.getRefString()=" << typeStr << endl ;
1002      MDirection::Types mdType ;
1003      MDirection::getType( mdType, typeStr ) ;
1004      //cerr << "mdType=" << mdType << endl ;
1005      md = MDirection( qangle, mdType ) ;
1006      //cerr << "md=" << md.getAngle().getValue("rad") << endl ;
1007    }
1008    else {
1009      pointingDirVec = pointingDir.column(0) ;
1010      Vector<MDirection> vmd(1);
1011      PtCols.directionMeasCol().get(PtIdx,vmd);
1012      md = vmd[0];
1013    }
1014    // put J2000 coordinates in "direction"
1015    if (cDirRef =="J2000") {
1016      pksrec.direction = pointingDirVec ;
1017    }
1018    else {
1019      pksrec.direction =
1020        MDirection::Convert(md, MDirection::Ref(MDirection::J2000,
1021                                                frame)
1022                            )().getAngle("rad").getValue();
1023     
1024    }
1025    uInt ncols = pointingDir.ncolumn();
1026    pksrec.scanRate.resize(2);
1027    if (ncols == 1) {
1028      pksrec.scanRate = 0.0f;
1029    } else {
1030      pksrec.scanRate(0) = pointingDir.column(1)(0);
1031      pksrec.scanRate(1) = pointingDir.column(1)(1);
1032    }
1033  }
1034  else {
1035  // Get direction from FIELD table
1036  // here, assume direction to be the field direction not pointing
1037    Matrix<Double> delayDir = cFieldDelayDirCol(fieldId);
1038    pksrec.direction = delayDir.column(0);
1039    uInt ncols = delayDir.ncolumn();
1040    pksrec.scanRate.resize(2);
1041    if (ncols == 1) {
1042      pksrec.scanRate = 0.0f;
1043    } else {
1044      pksrec.scanRate(0)  = delayDir.column(1)(0);
1045      pksrec.scanRate(1)  = delayDir.column(1)(1);
1046    }
1047  }
1048  // caluculate azimuth and elevation
1049  // first, get the reference frame
1050 /**
1051  MVPosition mvpos(antennaCols.position()(0));
1052  MPosition mp(mvpos);
1053  Quantum<Double> qt(time,"s");
1054  MVEpoch mvt(qt);
1055  MEpoch me(mvt);
1056  MeasFrame frame(mp, me);
1057  **/
1058  //
1059  ROMSFieldColumns fldCols(cPKSMS.field());
1060  Vector<MDirection> vmd(1);
1061  //MDirection md;
1062  fldCols.delayDirMeasCol().get(fieldId,vmd);
1063  md = vmd[0];
1064  //Vector<Double> dircheck = md.getAngle("rad").getValue();
1065  //cerr<<"dircheck="<<dircheck<<endl;
1066
1067  Vector<Double> azel =
1068        MDirection::Convert(md, MDirection::Ref(MDirection::AZEL,
1069                                                frame)
1070                            )().getAngle("rad").getValue();
1071  //cerr<<"azel="<<azel<<endl;
1072  pksrec.azimuth = azel[0];
1073  pksrec.elevation = azel[1];
1074
1075  // Get Tsys assuming that entries in the SYSCAL table match the main table.
1076  if (cHaveTsys) {
1077    Int nTsysColRow = cTsysCol.nrow();
1078    if (nTsysColRow != cNRow) {
1079      cHaveTsys=0;
1080    }
1081  }
1082  if (cHaveTsys) {
1083    cTsysCol.get(cIdx, pksrec.tsys, True);
1084  } else {
1085    Int numReceptor;
1086    cNumReceptorCol.get(0, numReceptor);
1087    pksrec.tsys.resize(numReceptor);
1088    pksrec.tsys = 1.0f;
1089  }
1090  cSigmaCol.get(cIdx, pksrec.sigma, True);
1091
1092  //get Tcal if available
1093  if (cHaveTcal) {
1094    Int nTcalColRow = cTcalCol.nrow();
1095    uInt nBeam = cBeams.nelements();
1096    uInt nIF = cIFs.nelements();
1097    uInt nrws = nBeam * nIF;
1098    if (nTcalColRow > 0) { 
1099    // find tcal match with the data with the data time stamp
1100      Double mjds = pksrec.mjd*(24*3600);
1101      Double dtcalTime;
1102      if ( pksrec.mjd > lastmjd || cIdx==0 ) {
1103        //Table tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds));
1104        tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds), nrws);
1105        //DEBUG
1106        //if (cIdx == 0) {
1107        //  cerr<<"inital table retrieved"<<endl;
1108        //}
1109       
1110      }
1111
1112      if (nBeam == 1) {
1113        tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF, 1);
1114      } else {
1115        tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF &&
1116                              tmptab.col("FEED_ID") == ibeam , 1);
1117      }
1118      //cerr<<"first subtab rows="<<tmptab.nrow()<<endl;
1119      int syscalrow = tmptab2.nrow();
1120      ROArrayColumn<Float> tcalCol(tmptab2, "TCAL");
1121      ROScalarColumn<Double> tcalTimeCol(tmptab2, "TIME");
1122      if (syscalrow==0) {
1123        os << LogIO::NORMAL
1124           <<"Cannot find any matching Tcal at/near the data timestamp."
1125           << " Set Tcal=0.0" << LogIO::POST ;
1126      } else {
1127        tcalCol.get(0, pksrec.tcal);
1128        tcalTimeCol.get(0,dtcalTime);
1129        pksrec.tcalTime = MVTime(dtcalTime/(24*3600)).string(MVTime::YMD);
1130        //DEBUG
1131        //cerr<<"cIdx:"<<cIdx<<" tcal="<<tcal<<" tcalTime="<<tcalTime<<endl;
1132        tmptab.markForDelete();
1133        tmptab2.markForDelete();
1134      }
1135    }
1136    lastmjd = pksrec.mjd;
1137  }
1138
1139  // Calibration factors (if available).
1140  pksrec.calFctr.resize(cNPol(iIF));
1141  if (cHaveCalFctr) {
1142    cCalFctrCol.get(cIdx, pksrec.calFctr);
1143  } else {
1144    pksrec.calFctr = 0.0f;
1145  }
1146
1147  // Baseline parameters (if available).
1148  if (cHaveBaseLin) {
1149    pksrec.baseLin.resize(2,cNPol(iIF));
1150    cBaseLinCol.get(cIdx, pksrec.baseLin);
1151
1152    pksrec.baseSub.resize(24,cNPol(iIF));
1153    cBaseSubCol.get(cIdx, pksrec.baseSub);
1154
1155  } else {
1156    pksrec.baseLin.resize(0,0);
1157    pksrec.baseSub.resize(0,0);
1158  }
1159
1160
1161  // Get spectral data.
1162  if (cGetSpectra) {
1163    Matrix<Float> tmpData;
1164    Matrix<Bool>  tmpFlag;
1165    if (cHaveDataCol) {
1166      Matrix<Complex> tmpCmplxData;
1167      Matrix<Float> tmpReData;
1168      Matrix<Float> tmpImData;
1169      //cerr<<"reading spectra..."<<endl;
1170      //# TODO - should have a flag to user to select DATA or CORRECTED_DATA
1171      //# currently just automatically determined, --- read CORRECTED one
1172      //# if the column exist.
1173      if (cHaveCorrectedDataCol) {
1174        cCorrectedDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
1175      } else {
1176        cDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
1177      }
1178      tmpReData = real(tmpCmplxData);
1179      tmpImData = imag(tmpCmplxData);
1180      tmpData = sqrt(tmpReData*tmpReData + tmpImData*tmpImData);
1181    } else {
1182      cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
1183    }
1184    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
1185
1186    // Transpose spectra.
1187    Int nPol = tmpData.nrow();
1188    pksrec.spectra.resize(nChan, nPol);
1189    pksrec.flagged.resize(nChan, nPol);
1190    if (cEndChan(iIF) >= cStartChan(iIF)) {
1191      // Simple transposition.
1192      for (Int ipol = 0; ipol < nPol; ipol++) {
1193        for (Int ichan = 0; ichan < nChan; ichan++) {
1194          pksrec.spectra(ichan,ipol) = tmpData(ipol,ichan);
1195          pksrec.flagged(ichan,ipol) = tmpFlag(ipol,ichan);
1196        }
1197      }
1198
1199    } else {
1200      // Transpose with inversion.
1201      Int jchan = nChan - 1;
1202      for (Int ipol = 0; ipol < nPol; ipol++) {
1203        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
1204          pksrec.spectra(ichan,ipol) = tmpData(ipol,jchan);
1205          pksrec.flagged(ichan,ipol) = tmpFlag(ipol,jchan);
1206        }
1207      }
1208    }
1209
1210    // Row-based flagging info. (True:1, False:0)
1211    pksrec.flagrow = (cFlagRowCol(cIdx) ? 1 : 0);
1212  }
1213
1214  // Get cross-polarization data.
1215  if (cGetXPol) {
1216    //cerr<<"cGetXPol="<<cGetXPol<<endl;
1217    //cerr<<"cHaveXCalFctr="<<cHaveXCalFctr<<endl;
1218
1219    if (cHaveXCalFctr) {
1220      cXCalFctrCol.get(cIdx, pksrec.xCalFctr);
1221    } else {
1222      pksrec.xCalFctr = Complex(0.0f, 0.0f);
1223    }
1224
1225    if(!cALMA) {
1226      cDataCol.get(cIdx, pksrec.xPol, True);
1227
1228      if (cEndChan(iIF) < cStartChan(iIF)) {
1229        Complex ctmp;
1230        Int jchan = nChan - 1;
1231        for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
1232          ctmp = pksrec.xPol(ichan);
1233          pksrec.xPol(ichan) = pksrec.xPol(jchan);
1234          pksrec.xPol(jchan) = ctmp;
1235        }
1236      }
1237    }
1238  }
1239  /**
1240  cerr<<"scanNo="<<scanNo<<endl;
1241  cerr<<"cycleNo="<<cycleNo<<endl;
1242  cerr<<"mjd="<<mjd<<endl;
1243  cerr<<"interval="<<interval<<endl;
1244  cerr<<"fieldName="<<fieldName<<endl;
1245  cerr<<"srcNmae="<<srcName<<endl;
1246  cerr<<"srcDir="<<srcDir<<endl;
1247  cerr<<"srcPM="<<srcPM<<endl;
1248  cerr<<"srcVel="<<srcVel<<endl;
1249  cerr<<"obsMode="<<obsMode<<endl;
1250  cerr<<"IFno="<<IFno<<endl;
1251  cerr<<"refFreq="<<refFreq<<endl;
1252  cerr<<"tcal="<<tcal<<endl;
1253  cerr<<"direction="<<direction<<endl;
1254  cerr<<"scanRate="<<scanRate<<endl;
1255  cerr<<"tsys="<<tsys<<endl;
1256  cerr<<"sigma="<<sigma<<endl;
1257  cerr<<"calFctr="<<calFctr<<endl;
1258  cerr<<"baseLin="<<baseLin<<endl;
1259  cerr<<"baseSub="<<baseSub<<endl;
1260  cerr<<"spectra="<<spectra.shape()<<endl;
1261  cerr<<"flagged="<<flagged.shape()<<endl;
1262  cerr<<"xCalFctr="<<xCalFctr<<endl;
1263  cerr<<"xPol="<<xPol<<endl;
1264  **/
1265  cIdx++;
1266
1267  return 0;
1268}
1269
1270//--------------------------------------------------------- PKSMS2reader::read
1271
1272// Read the next data record, just the basics.
1273
1274Int PKSMS2reader::read(
1275        Int           &IFno,
1276        Vector<Float> &tsys,
1277        Vector<Float> &calFctr,
1278        Matrix<Float> &baseLin,
1279        Matrix<Float> &baseSub,
1280        Matrix<Float> &spectra,
1281        Matrix<uChar> &flagged)
1282{
1283  if (!cMSopen) {
1284    return 1;
1285  }
1286
1287  // Check for EOF.
1288  if (cIdx >= cNRow) {
1289    return -1;
1290  }
1291
1292  // Find the next selected beam and IF.
1293  Int ibeam;
1294  Int iIF;
1295  Int iDataDesc;
1296  while (True) {
1297    ibeam = cBeamNoCol(cIdx);
1298    //iIF   = cDataDescIdCol(cIdx);
1299    iDataDesc   = cDataDescIdCol(cIdx);
1300    iIF   = cSpWinIdCol(iDataDesc);
1301    if (cBeams(ibeam) && cIFs(iIF)) {
1302      break;
1303    }
1304
1305    // Check for EOF.
1306    if (++cIdx >= cNRow) {
1307      return -1;
1308    }
1309  }
1310
1311  IFno = iIF + 1;
1312  // Get Tsys assuming that entries in the SYSCAL table match the main table.
1313  cTsysCol.get(cIdx, tsys, True);
1314
1315  // Calibration factors (if available).
1316  if (cHaveCalFctr) {
1317    cCalFctrCol.get(cIdx, calFctr, True);
1318  } else {
1319    calFctr.resize(cNPol(iIF));
1320    calFctr = 0.0f;
1321  }
1322
1323  // Baseline parameters (if available).
1324  if (cHaveBaseLin) {
1325    baseLin.resize(2,cNPol(iIF));
1326    cBaseLinCol.get(cIdx, baseLin);
1327
1328    baseSub.resize(24,cNPol(iIF));
1329    cBaseSubCol.get(cIdx, baseSub);
1330
1331  } else {
1332    baseLin.resize(0,0);
1333    baseSub.resize(0,0);
1334  }
1335
1336  if (cGetSpectra) {
1337    // Get spectral data.
1338    Matrix<Float> tmpData;
1339    Matrix<Bool>  tmpFlag;
1340    if (cHaveDataCol) {
1341      Matrix<Complex> tmpCmplxData;
1342      cDataCol.getSlice(cIdx, cDataSel(iIF), tmpCmplxData, True);
1343      tmpData = real(tmpCmplxData);
1344    } else {
1345      cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
1346    }
1347    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
1348
1349    // Transpose spectra.
1350    Int nChan = tmpData.ncolumn();
1351    Int nPol  = tmpData.nrow();
1352    spectra.resize(nChan, nPol);
1353    flagged.resize(nChan, nPol);
1354    if (cEndChan(iIF) >= cStartChan(iIF)) {
1355      // Simple transposition.
1356      for (Int ipol = 0; ipol < nPol; ipol++) {
1357        for (Int ichan = 0; ichan < nChan; ichan++) {
1358          spectra(ichan,ipol) = tmpData(ipol,ichan);
1359          flagged(ichan,ipol) = tmpFlag(ipol,ichan);
1360        }
1361      }
1362
1363    } else {
1364      // Transpose with inversion.
1365      Int jchan = nChan - 1;
1366      for (Int ipol = 0; ipol < nPol; ipol++) {
1367        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
1368          spectra(ichan,ipol) = tmpData(ipol,jchan);
1369          flagged(ichan,ipol) = tmpFlag(ipol,jchan);
1370        }
1371      }
1372    }
1373  }
1374
1375  cIdx++;
1376
1377  return 0;
1378}
1379
1380//-------------------------------------------------------- PKSMS2reader::close
1381
1382// Close the MS.
1383
1384void PKSMS2reader::close()
1385{
1386  cPKSMS = MeasurementSet();
1387  cMSopen = False;
1388}
1389
1390//-------------------------------------------------------- PKSMS2reader::splitAntenanSelectionString
1391
1392// split antenna selection string
1393// delimiter is ','
1394
1395Vector<String> PKSMS2reader::splitAntennaSelectionString( const String s )
1396{
1397  Char delim = ',' ;
1398  Int n = s.freq( delim ) + 1 ;
1399  Vector<String> antlist ;
1400  string sl[n] ;
1401  Int numSubstr = split( s, sl, n, "," );
1402  antlist.resize( numSubstr ) ;
1403  for ( Int i = 0 ; i < numSubstr ; i++ ) {
1404    antlist[i] = String( sl[i] ) ;
1405    antlist[i].trim() ;
1406  }
1407  //cerr << "antlist = " << antlist << endl ;
1408  return antlist ;
1409}
1410
1411//-------------------------------------------------------- PKSMS2reader::setupAntennaList
1412
1413// Fill cAntenna and cAntId
1414
1415void PKSMS2reader::setupAntennaList( const String s )
1416{
1417  LogIO os( LogOrigin( "PKSMS2reader", "setupAntennaList()", WHERE ) ) ;
1418  //cerr << "antenna specification: " << s << endl ;
1419  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
1420  ROScalarColumn<String> antNames = antennaCols.name();
1421  Int nrow = antNames.nrow() ;
1422  Vector<String> antlist = splitAntennaSelectionString( s ) ;
1423  Int len = antlist.size() ;
1424  Vector<Int> AntId( len ) ;
1425  Regex re( "[0-9]+" ) ;
1426  for ( Int i = 0 ; i < len ; i++ ) {
1427    if ( antlist[i].matches( re ) ) {
1428      AntId[i] = atoi( antlist[i].c_str() ) ;
1429      if ( AntId[i] >= nrow ) {
1430        os << LogIO::SEVERE << "Antenna index out of range: " << AntId[i] << LogIO::EXCEPTION ;
1431      }
1432    }
1433    else {
1434      AntId[i] = -1 ;
1435      for ( uInt j = 0 ; j < antNames.nrow() ; j++ ) {
1436        if ( antlist[i] == antNames(j) ) {
1437          AntId[i] = j ;
1438          break ;
1439        }
1440      }
1441      if ( AntId[i] == -1 ) {
1442        os << LogIO::SEVERE << "Specified antenna name not found: " << antlist[i] << LogIO::EXCEPTION ;
1443      }
1444    }
1445  }
1446  //cerr << "AntId = " << AntId << endl ;
1447  vector<Int> uniqId ;
1448  uniqId.push_back( AntId(0) ) ;
1449  for ( uInt i = 1 ; i < AntId.size() ; i++ ) {
1450    if ( count(uniqId.begin(),uniqId.end(),AntId[i]) == 0 ) {
1451      uniqId.push_back( AntId[i] ) ;
1452    }
1453  }
1454  Vector<Int> newAntId( uniqId ) ;
1455  cAntId.assign( newAntId ) ;
1456  //cerr << "cAntId = " << cAntId << endl ;
1457}
Note: See TracBrowser for help on using the repository browser.