source: trunk/external/atnf/PKSIO/PKSMS2reader.cc @ 1399

Last change on this file since 1399 was 1399, checked in by Malte Marquarding, 17 years ago

Mark C added brightness unit to getHeader()

File size: 22.3 KB
Line 
1//#---------------------------------------------------------------------------
2//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2000-2007
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: PKSMS2reader.cc,v 19.12 2007/11/12 03:37:56 cal103 Exp $
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
41// Parkes includes.
42#include <atnf/pks/pks_maths.h>
43#include <atnf/PKSIO/PKSMS2reader.h>
44
45
46//------------------------------------------------- PKSMS2reader::PKSMS2reader
47
48// Default constructor.
49
50PKSMS2reader::PKSMS2reader()
51{
52  cMSopen = False;
53}
54
55//------------------------------------------------ PKSMS2reader::~PKSMS2reader
56
57PKSMS2reader::~PKSMS2reader()
58{
59  close();
60}
61
62//--------------------------------------------------------- PKSMS2reader::open
63
64// Open the MS for reading.
65
66Int PKSMS2reader::open(
67        const String msName,
68        Vector<Bool> &beams,
69        Vector<Bool> &IFs,
70        Vector<uInt> &nChan,
71        Vector<uInt> &nPol,
72        Vector<Bool> &haveXPol,
73        Bool   &haveBase,
74        Bool   &haveSpectra)
75{
76  // Check that MS is readable.
77  if (!MS::isReadable(msName)) {
78    return 1;
79  }
80
81  if (cMSopen) {
82    close();
83  }
84
85  cPKSMS  = MeasurementSet(msName);
86  cIdx    = 0;
87  cNRow   = cPKSMS.nrow();
88  cMSopen = True;
89
90  // Lock the table for read access.
91  cPKSMS.lock(False);
92
93  // Main MS table and subtable column access.
94  ROMSMainColumns         msCols(cPKSMS);
95  ROMSDataDescColumns     dataDescCols(cPKSMS.dataDescription());
96  ROMSFeedColumns         feedCols(cPKSMS.feed());
97  ROMSFieldColumns        fieldCols(cPKSMS.field());
98  ROMSPointingColumns     pointingCols(cPKSMS.pointing());
99  ROMSPolarizationColumns polarizationCols(cPKSMS.polarization());
100  ROMSSourceColumns       sourceCols(cPKSMS.source());
101  ROMSSpWindowColumns     spWinCols(cPKSMS.spectralWindow());
102  ROMSStateColumns        stateCols(cPKSMS.state());
103  ROMSSysCalColumns       sysCalCols(cPKSMS.sysCal());
104  ROMSWeatherColumns      weatherCols(cPKSMS.weather());
105
106  // Column accessors for required columns.
107  cScanNoCol.reference(msCols.scanNumber());
108  cTimeCol.reference(msCols.time());
109  cIntervalCol.reference(msCols.interval());
110
111  cFieldIdCol.reference(msCols.fieldId());
112  cFieldNameCol.reference(fieldCols.name());
113
114  cSrcIdCol.reference(fieldCols.sourceId());
115  cSrcNameCol.reference(sourceCols.name());
116  cSrcDirCol.reference(sourceCols.direction());
117  cSrcPMCol.reference(sourceCols.properMotion());
118  cSrcRestFrqCol.reference(sourceCols.restFrequency());
119
120  cStateIdCol.reference(msCols.stateId());
121  cObsModeCol.reference(stateCols.obsMode());
122
123  cDataDescIdCol.reference(msCols.dataDescId());
124  cChanFreqCol.reference(spWinCols.chanFreq());
125
126  cWeatherTimeCol.reference(weatherCols.time());
127  cTemperatureCol.reference(weatherCols.temperature());
128  cPressureCol.reference(weatherCols.pressure());
129  cHumidityCol.reference(weatherCols.relHumidity());
130
131  cBeamNoCol.reference(msCols.feed1());
132  cPointingCol.reference(pointingCols.direction());
133  cSigmaCol.reference(msCols.sigma());
134  cNumReceptorCol.reference(feedCols.numReceptors());
135
136  // Optional columns.
137  if ((cHaveSrcVel = cPKSMS.source().tableDesc().isColumn("SYSVEL"))) {
138    cSrcVelCol.attach(cPKSMS.source(), "SYSVEL");
139  }
140
141  if ((cHaveTsys = cPKSMS.sysCal().tableDesc().isColumn("TSYS"))) {
142    cTsysCol.attach(cPKSMS.sysCal(), "TSYS");
143  }
144
145  if ((cHaveCalFctr = cPKSMS.tableDesc().isColumn("CALFCTR"))) {
146    cCalFctrCol.attach(cPKSMS, "CALFCTR");
147  }
148
149  if ((cHaveBaseLin = cPKSMS.tableDesc().isColumn("BASELIN"))) {
150    cBaseLinCol.attach(cPKSMS, "BASELIN");
151    cBaseSubCol.attach(cPKSMS, "BASESUB");
152  }
153
154  // Spectral data should always be present.
155  haveSpectra = True;
156  cFloatDataCol.reference(msCols.floatData());
157  cFlagCol.reference(msCols.flag());
158
159  if ((cGetXPol = cPKSMS.isColumn(MSMainEnums::DATA))) {
160    if ((cHaveXCalFctr = cPKSMS.tableDesc().isColumn("XCALFCTR"))) {
161      cXCalFctrCol.attach(cPKSMS, "XCALFCTR");
162    }
163
164    cDataCol.reference(msCols.data());
165  }
166
167  // Find which beams are present in the data.
168  Vector<Int> beamNos = cBeamNoCol.getColumn();
169  Int maxBeamNo = max(beamNos) + 1;
170  beams.resize(maxBeamNo);
171
172  beams = False;
173  for (uInt irow = 0; irow < beamNos.nelements(); irow++) {
174    beams(beamNos(irow)) = True;
175  }
176
177
178  // Number of IFs.
179  uInt nIF = dataDescCols.nrow();
180  IFs.resize(nIF);
181  IFs = True;
182
183  // Number of polarizations and channels in each IF.
184  ROScalarColumn<Int> spWinIdCol(dataDescCols.spectralWindowId());
185  ROScalarColumn<Int> numChanCol(spWinCols.numChan());
186
187  ROScalarColumn<Int> polIdCol(dataDescCols.polarizationId());
188  ROScalarColumn<Int> numPolCol(polarizationCols.numCorr());
189
190  nChan.resize(nIF);
191  nPol.resize(nIF);
192  for (uInt iIF = 0; iIF < nIF; iIF++) {
193    nChan(iIF) = numChanCol(spWinIdCol(iIF));
194    nPol(iIF)  = numPolCol(polIdCol(iIF));
195  }
196
197  // Cross-polarization data present?
198  haveXPol.resize(nIF);
199  haveXPol = False;
200
201  if (cGetXPol) {
202    for (Int irow = 0; irow < cNRow; irow++) {
203      if (cDataCol.isDefined(irow)) {
204        Int iIF = cDataDescIdCol(irow);
205        haveXPol(iIF) = True;
206      }
207    }
208  }
209
210
211  // Initialize member data.
212  cBeams.assign(beams);
213  cIFs.assign(IFs);
214  cNChan.assign(nChan);
215  cNPol.assign(nPol);
216  cHaveXPol.assign(haveXPol);
217
218
219  // Default channel range selection.
220  cStartChan.resize(nIF);
221  cEndChan.resize(nIF);
222  cRefChan.resize(nIF);
223
224  for (uInt iIF = 0; iIF < nIF; iIF++) {
225    cStartChan(iIF) = 1;
226    cEndChan(iIF)   = cNChan(iIF);
227    cRefChan(iIF)   = cNChan(iIF)/2 + 1;
228  }
229
230  Slice all;
231  cDataSel.resize(nIF);
232  cDataSel = Slicer(all, all);
233
234  cScanNo  = 0;
235  cCycleNo = 1;
236  cTime    = cTimeCol(0);
237
238  return 0;
239}
240
241//---------------------------------------------------- PKSMS2reader::getHeader
242
243// Get parameters describing the data.
244
245Int PKSMS2reader::getHeader(
246        String &observer,
247        String &project,
248        String &antName,
249        Vector<Double> &antPosition,
250        String &obsMode,
251        String &bunit,
252        Float  &equinox,
253        String &dopplerFrame,
254        Double &mjd,
255        Double &refFreq,
256        Double &bandwidth)
257{
258  if (!cMSopen) {
259    return 1;
260  }
261
262  // Observer and project.
263  ROMSObservationColumns observationCols(cPKSMS.observation());
264  observer = observationCols.observer()(0);
265  project  = observationCols.project()(0);
266
267  // Antenna name and ITRF coordinates.
268  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
269  antName = antennaCols.name()(0);
270  antPosition = antennaCols.position()(0);
271
272  // Observation type.
273  if (cObsModeCol.nrow()) {
274    obsMode = cObsModeCol(0);
275    if (obsMode == "\0") obsMode = "RF";
276  } else {
277    obsMode = "RF";
278  }
279
280  // Brightness units.
281  bunit = cPKSMS.unit(MSMainEnums::FLOAT_DATA);
282
283  // Coordinate equinox.
284  ROMSPointingColumns pointingCols(cPKSMS.pointing());
285  String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
286                    asString("Ref");
287  sscanf(dirref.chars()+1, "%f", &equinox);
288
289  // Frequency/velocity reference frame.
290  ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
291  dopplerFrame = MFrequency::showType(spWinCols.measFreqRef()(0));
292
293  // Translate to FITS standard names.
294  if (dopplerFrame == "TOPO") {
295    dopplerFrame = "TOPOCENT";
296  } else if (dopplerFrame == "GEO") {
297    dopplerFrame = "GEOCENTR";
298  } else if (dopplerFrame == "BARY") {
299    dopplerFrame = "BARYCENT";
300  } else if (dopplerFrame == "GALACTO") {
301    dopplerFrame = "GALACTOC";
302  } else if (dopplerFrame == "LGROUP") {
303    dopplerFrame = "LOCALGRP";
304  } else if (dopplerFrame == "CMB") {
305    dopplerFrame = "CMBDIPOL";
306  } else if (dopplerFrame == "REST") {
307    dopplerFrame = "SOURCE";
308  }
309
310  // MJD at start of observation.
311  mjd = cTimeCol(0)/86400.0;
312
313  // Reference frequency and bandwidth.
314  refFreq   = spWinCols.refFrequency()(0);
315  bandwidth = spWinCols.totalBandwidth()(0);
316
317  return 0;
318}
319
320//-------------------------------------------------- PKSMS2reader::getFreqInfo
321
322// Get frequency parameters for each IF.
323
324Int PKSMS2reader::getFreqInfo(
325        Vector<Double> &startFreq,
326        Vector<Double> &endFreq)
327{
328  uInt nIF = cIFs.nelements();
329  startFreq.resize(nIF);
330  endFreq.resize(nIF);
331
332  for (uInt iIF = 0; iIF < nIF; iIF++) {
333    Vector<Double> chanFreq = cChanFreqCol(iIF);
334
335    Int nChan = chanFreq.nelements();
336    startFreq(iIF) = chanFreq(0);
337    endFreq(iIF)   = chanFreq(nChan-1);
338  }
339
340  return 0;
341}
342
343//------------------------------------------------------- PKSMS2reader::select
344
345// Set data selection by beam number and channel.
346
347uInt PKSMS2reader::select(
348        const Vector<Bool> beamSel,
349        const Vector<Bool> IFsel,
350        const Vector<Int>  startChan,
351        const Vector<Int>  endChan,
352        const Vector<Int>  refChan,
353        const Bool getSpectra,
354        const Bool getXPol,
355        const Bool getFeedPos)
356{
357  if (!cMSopen) {
358    return 1;
359  }
360
361  // Beam selection.
362  uInt nBeam = cBeams.nelements();
363  uInt nBeamSel = beamSel.nelements();
364  for (uInt ibeam = 0; ibeam < nBeam; ibeam++) {
365    if (ibeam < nBeamSel) {
366      cBeams(ibeam) = beamSel(ibeam);
367    } else {
368      cBeams(ibeam) = False;
369    }
370  }
371
372  uInt nIF = cIFs.nelements();
373  uInt maxNChan = 0;
374  for (uInt iIF = 0; iIF < nIF; iIF++) {
375    // IF selection.
376    if (iIF < IFsel.nelements()) {
377      cIFs(iIF) = IFsel(iIF);
378    } else {
379      cIFs(iIF) = False;
380    }
381
382    if (!cIFs(iIF)) continue;
383
384
385    // Channel selection.
386    if (iIF < startChan.nelements()) {
387      cStartChan(iIF) = startChan(iIF);
388
389      if (cStartChan(iIF) <= 0) {
390        cStartChan(iIF) += cNChan(iIF);
391      } else if (cStartChan(iIF) > Int(cNChan(iIF))) {
392        cStartChan(iIF)  = cNChan(iIF);
393      }
394    }
395
396    if (iIF < endChan.nelements()) {
397      cEndChan(iIF) = endChan(iIF);
398
399      if (cEndChan(iIF) <= 0) {
400        cEndChan(iIF) += cNChan(iIF);
401      } else if (cEndChan(iIF) > Int(cNChan(iIF))) {
402        cEndChan(iIF)  = cNChan(iIF);
403      }
404    }
405
406    if (iIF < refChan.nelements()) {
407      cRefChan(iIF) = refChan(iIF);
408    } else {
409      cRefChan(iIF) = cStartChan(iIF);
410      if (cStartChan(iIF) <= cEndChan(iIF)) {
411        cRefChan(iIF) += (cEndChan(iIF) - cStartChan(iIF) + 1)/2;
412      } else {
413        cRefChan(iIF) -= (cStartChan(iIF) - cEndChan(iIF) + 1)/2;
414      }
415    }
416
417    uInt nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
418    if (maxNChan < nChan) {
419      maxNChan = nChan;
420    }
421
422    // Inverted Slices are not allowed.
423    Slice outPols;
424    Slice outChans(min(cStartChan(iIF),cEndChan(iIF))-1, nChan);
425    cDataSel(iIF) = Slicer(outPols, outChans);
426  }
427
428  // Get spectral data?
429  cGetSpectra = getSpectra;
430
431  // Get cross-polarization data?
432  cGetXPol = cGetXPol && getXPol;
433
434  // Get feed positions?  (Not available.)
435  cGetFeedPos = False;
436
437  return maxNChan;
438}
439
440//---------------------------------------------------- PKSMS2reader::findRange
441
442// Find the range of the data in time and position.
443
444Int PKSMS2reader::findRange(
445        Int    &nRow,
446        Int    &nSel,
447        Vector<Double> &timeSpan,
448        Matrix<Double> &positions)
449{
450  if (!cMSopen) {
451    return 1;
452  }
453
454  nRow = cNRow;
455
456  // Find the number of rows selected.
457  nSel = 0;
458  Vector<Bool> sel(nRow);
459  for (Int irow = 0; irow < nRow; irow++) {
460    if ((sel(irow) = cBeams(cBeamNoCol(irow)) &&
461                     cIFs(cDataDescIdCol(irow)))) {
462      nSel++;
463    }
464  }
465
466  // Find the time range (s).
467  timeSpan.resize(2);
468  timeSpan(0) = cTimeCol(0);
469  timeSpan(1) = cTimeCol(nRow-1);
470
471  // Retrieve positions for selected data.
472  Int isel = 0;
473  positions.resize(2,nSel);
474  for (Int irow = 0; irow < nRow; irow++) {
475    if (sel(irow)) {
476      Matrix<Double> pointingDir = cPointingCol(cFieldIdCol(irow));
477      positions.column(isel++) = pointingDir.column(0);
478    }
479  }
480
481  return 0;
482}
483
484//--------------------------------------------------------- PKSMS2reader::read
485
486// Read the next data record.
487
488Int PKSMS2reader::read(
489        Int             &scanNo,
490        Int             &cycleNo,
491        Double          &mjd,
492        Double          &interval,
493        String          &fieldName,
494        String          &srcName,
495        Vector<Double>  &srcDir,
496        Vector<Double>  &srcPM,
497        Double          &srcVel,
498        String          &obsMode,
499        Int             &IFno,
500        Double          &refFreq,
501        Double          &bandwidth,
502        Double          &freqInc,
503        Double          &restFreq,
504        Vector<Float>   &tcal,
505        String          &tcalTime,
506        Float           &azimuth,
507        Float           &elevation,
508        Float           &parAngle,
509        Float           &focusAxi,
510        Float           &focusTan,
511        Float           &focusRot,
512        Float           &temperature,
513        Float           &pressure,
514        Float           &humidity,
515        Float           &windSpeed,
516        Float           &windAz,
517        Int             &refBeam,
518        Int             &beamNo,
519        Vector<Double>  &direction,
520        Vector<Double>  &scanRate,
521        Vector<Float>   &tsys,
522        Vector<Float>   &sigma,
523        Vector<Float>   &calFctr,
524        Matrix<Float>   &baseLin,
525        Matrix<Float>   &baseSub,
526        Matrix<Float>   &spectra,
527        Matrix<uChar>   &flagged,
528        Complex         &xCalFctr,
529        Vector<Complex> &xPol)
530{
531  if (!cMSopen) {
532    return 1;
533  }
534
535  // Check for EOF.
536  if (cIdx >= cNRow) {
537    return -1;
538  }
539
540  // Find the next selected beam and IF.
541  Int ibeam;
542  Int iIF;
543  while (True) {
544    ibeam = cBeamNoCol(cIdx);
545    iIF   = cDataDescIdCol(cIdx);
546    if (cBeams(ibeam) && cIFs(iIF)) {
547      break;
548    }
549
550    // Check for EOF.
551    if (++cIdx >= cNRow) {
552      return -1;
553    }
554  }
555
556  // Renumerate scan no. Here still is 1-based
557  scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
558
559  if (scanNo != cScanNo) {
560    // Start of new scan.
561    cScanNo  = scanNo;
562    cCycleNo = 1;
563    cTime    = cTimeCol(cIdx);
564  }
565
566  Double time = cTimeCol(cIdx);
567  mjd      = time/86400.0;
568  interval = cIntervalCol(cIdx);
569
570  // Reconstruct the integration cycle number; due to small latencies the
571  // integration time is usually slightly less than the time between cycles,
572  // resetting cTime will prevent the difference from accumulating.
573  cCycleNo += nint((time - cTime)/interval);
574  cycleNo = cCycleNo;
575  cTime   = time;
576
577  Int fieldId = cFieldIdCol(cIdx);
578  fieldName = cFieldNameCol(fieldId);
579
580  Int srcId = cSrcIdCol(fieldId);
581  srcName = cSrcNameCol(srcId);
582  srcDir  = cSrcDirCol(srcId);
583  srcPM   = cSrcPMCol(srcId);
584
585  // Systemic velocity.
586  if (!cHaveSrcVel) {
587    srcVel = 0.0f;
588  } else {
589    srcVel  = cSrcVelCol(srcId)(IPosition(1,0));
590  }
591
592  // Observation type.
593  Int stateId = cStateIdCol(cIdx);
594  obsMode = cObsModeCol(stateId);
595
596  IFno = iIF + 1;
597  Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
598
599  // Minimal handling on continuum data.
600  Vector<Double> chanFreq = cChanFreqCol(iIF);
601  if (nChan == 1) {
602    cout << "The input is continuum data. "<< endl;
603    freqInc  = chanFreq(0);
604    refFreq  = chanFreq(0);
605    restFreq = 0.0f;
606  } else {
607    if (cStartChan(iIF) <= cEndChan(iIF)) {
608      freqInc = chanFreq(1) - chanFreq(0);
609    } else {
610      freqInc = chanFreq(0) - chanFreq(1);
611    }
612
613    refFreq  = chanFreq(cRefChan(iIF)-1);
614    restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
615  }
616  bandwidth = abs(freqInc * nChan);
617
618  tcal.resize(cNPol(iIF));
619  tcal      = 0.0f;
620  tcalTime  = "";
621  azimuth   = 0.0f;
622  elevation = 0.0f;
623  parAngle  = 0.0f;
624  focusAxi  = 0.0f;
625  focusTan  = 0.0f;
626  focusRot  = 0.0f;
627
628  // Find the appropriate entry in the WEATHER subtable.
629  Vector<Double> wTimes = cWeatherTimeCol.getColumn();
630  Int weatherIdx;
631  for (weatherIdx = wTimes.nelements()-1; weatherIdx >= 0; weatherIdx--) {
632    if (cWeatherTimeCol(weatherIdx) <= time) {
633      break;
634    }
635  }
636
637  if (weatherIdx < 0) {
638    // No appropriate WEATHER entry.
639    pressure    = 0.0f;
640    humidity    = 0.0f;
641    temperature = 0.0f;
642  } else {
643    pressure    = cPressureCol(weatherIdx);
644    humidity    = cHumidityCol(weatherIdx);
645    temperature = cTemperatureCol(weatherIdx);
646  }
647
648  windSpeed = 0.0f;
649  windAz    = 0.0f;
650
651  refBeam = 0;
652  beamNo  = ibeam + 1;
653
654  Matrix<Double> pointingDir = cPointingCol(fieldId);
655  direction = pointingDir.column(0);
656  uInt ncols = pointingDir.ncolumn();
657  if (ncols == 1) {
658    scanRate = 0.0f;
659  } else {
660    scanRate  = pointingDir.column(1);
661  }
662
663  // Get Tsys assuming that entries in the SYSCAL table match the main table.
664  if (cHaveTsys) {
665    Int nTsysColRow = cTsysCol.nrow();
666    if (nTsysColRow != cNRow) {
667      cHaveTsys=0;
668    }
669  }
670  if (cHaveTsys) {
671    cTsysCol.get(cIdx, tsys, True);
672  } else {
673    Int numReceptor;
674    cNumReceptorCol.get(0, numReceptor);
675    tsys.resize(numReceptor);
676    tsys = 1.0f;
677  }
678  cSigmaCol.get(cIdx, sigma, True);
679
680  // Calibration factors (if available).
681  calFctr.resize(cNPol(iIF));
682  if (cHaveCalFctr) {
683    cCalFctrCol.get(cIdx, calFctr);
684  } else {
685    calFctr = 0.0f;
686  }
687
688  // Baseline parameters (if available).
689  if (cHaveBaseLin) {
690    baseLin.resize(2,cNPol(iIF));
691    cBaseLinCol.get(cIdx, baseLin);
692
693    baseSub.resize(9,cNPol(iIF));
694    cBaseSubCol.get(cIdx, baseSub);
695
696  } else {
697    baseLin.resize(0,0);
698    baseSub.resize(0,0);
699  }
700
701
702  // Get spectral data.
703  if (cGetSpectra) {
704    Matrix<Float> tmpData;
705    Matrix<Bool>  tmpFlag;
706    cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
707    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
708
709    // Transpose spectra.
710    Int nPol = tmpData.nrow();
711    spectra.resize(nChan, nPol);
712    flagged.resize(nChan, nPol);
713    if (cEndChan(iIF) >= cStartChan(iIF)) {
714      // Simple transposition.
715      for (Int ipol = 0; ipol < nPol; ipol++) {
716        for (Int ichan = 0; ichan < nChan; ichan++) {
717          spectra(ichan,ipol) = tmpData(ipol,ichan);
718          flagged(ichan,ipol) = tmpFlag(ipol,ichan);
719        }
720      }
721
722    } else {
723      // Transpose with inversion.
724      Int jchan = nChan - 1;
725      for (Int ipol = 0; ipol < nPol; ipol++) {
726        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
727          spectra(ichan,ipol) = tmpData(ipol,jchan);
728          flagged(ichan,ipol) = tmpFlag(ipol,jchan);
729        }
730      }
731    }
732  }
733
734  // Get cross-polarization data.
735  if (cGetXPol) {
736    if (cHaveXCalFctr) {
737      cXCalFctrCol.get(cIdx, xCalFctr);
738    } else {
739      xCalFctr = Complex(0.0f, 0.0f);
740    }
741
742    cDataCol.get(cIdx, xPol, True);
743
744    if (cEndChan(iIF) < cStartChan(iIF)) {
745      Complex ctmp;
746      Int jchan = nChan - 1;
747      for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
748        ctmp = xPol(ichan);
749        xPol(ichan) = xPol(jchan);
750        xPol(jchan) = ctmp;
751      }
752    }
753  }
754
755  cIdx++;
756
757  return 0;
758}
759
760//--------------------------------------------------------- PKSMS2reader::read
761
762// Read the next data record, just the basics.
763
764Int PKSMS2reader::read(
765        Int           &IFno,
766        Vector<Float> &tsys,
767        Vector<Float> &calFctr,
768        Matrix<Float> &baseLin,
769        Matrix<Float> &baseSub,
770        Matrix<Float> &spectra,
771        Matrix<uChar> &flagged)
772{
773  if (!cMSopen) {
774    return 1;
775  }
776
777  // Check for EOF.
778  if (cIdx >= cNRow) {
779    return -1;
780  }
781
782  // Find the next selected beam and IF.
783  Int ibeam;
784  Int iIF;
785  while (True) {
786    ibeam = cBeamNoCol(cIdx);
787    iIF   = cDataDescIdCol(cIdx);
788    if (cBeams(ibeam) && cIFs(iIF)) {
789      break;
790    }
791
792    // Check for EOF.
793    if (++cIdx >= cNRow) {
794      return -1;
795    }
796  }
797
798  IFno = iIF + 1;
799
800  // Get Tsys assuming that entries in the SYSCAL table match the main table.
801  cTsysCol.get(cIdx, tsys, True);
802
803  // Calibration factors (if available).
804  if (cHaveCalFctr) {
805    cCalFctrCol.get(cIdx, calFctr, True);
806  } else {
807    calFctr.resize(cNPol(iIF));
808    calFctr = 0.0f;
809  }
810
811  // Baseline parameters (if available).
812  if (cHaveBaseLin) {
813    baseLin.resize(2,cNPol(iIF));
814    cBaseLinCol.get(cIdx, baseLin);
815
816    baseSub.resize(9,cNPol(iIF));
817    cBaseSubCol.get(cIdx, baseSub);
818
819  } else {
820    baseLin.resize(0,0);
821    baseSub.resize(0,0);
822  }
823
824  if (cGetSpectra) {
825    // Get spectral data.
826    Matrix<Float> tmpData;
827    Matrix<Bool>  tmpFlag;
828    cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
829    cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
830
831    // Transpose spectra.
832    Int nChan = tmpData.ncolumn();
833    Int nPol  = tmpData.nrow();
834    spectra.resize(nChan, nPol);
835    flagged.resize(nChan, nPol);
836    if (cEndChan(iIF) >= cStartChan(iIF)) {
837      // Simple transposition.
838      for (Int ipol = 0; ipol < nPol; ipol++) {
839        for (Int ichan = 0; ichan < nChan; ichan++) {
840          spectra(ichan,ipol) = tmpData(ipol,ichan);
841          flagged(ichan,ipol) = tmpFlag(ipol,ichan);
842        }
843      }
844
845    } else {
846      // Transpose with inversion.
847      Int jchan = nChan - 1;
848      for (Int ipol = 0; ipol < nPol; ipol++) {
849        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
850          spectra(ichan,ipol) = tmpData(ipol,jchan);
851          flagged(ichan,ipol) = tmpFlag(ipol,jchan);
852        }
853      }
854    }
855  }
856
857  cIdx++;
858
859  return 0;
860}
861
862//-------------------------------------------------------- PKSMS2reader::close
863
864// Close the MS.
865
866void PKSMS2reader::close()
867{
868  cPKSMS = MeasurementSet();
869  cMSopen = False;
870}
Note: See TracBrowser for help on using the repository browser.