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

Last change on this file since 1720 was 1720, checked in by Malte Marquarding, 14 years ago

Update from livedata CVS repository

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