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

Last change on this file since 1824 was 1720, checked in by Malte Marquarding, 15 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.