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

Last change on this file since 1635 was 1635, checked in by Malte Marquarding, 15 years ago

Update from livedata CVS

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