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

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

Update from livedata CVS

File size: 19.3 KB
RevLine 
[1325]1//#---------------------------------------------------------------------------
2//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
3//#---------------------------------------------------------------------------
[1635]4//# Copyright (C) 2000-2009
[1325]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//#
[1635]28//# $Id: PKSMS2reader.cc,v 19.22 2009-03-24 06:15:33 cal103 Exp $
[1325]29//#---------------------------------------------------------------------------
30//# Original: 2000/08/03, Mark Calabretta, ATNF
31//#---------------------------------------------------------------------------
32
[1452]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>
[1325]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;
[1452]51
52 // By default, messages are written to stderr.
53 initMsg();
[1325]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,
[1427]251 String &obsType,
[1399]252 String &bunit,
[1325]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()) {
[1427]275 obsType = cObsModeCol(0);
276 if (obsType == "\0") obsType = "RF";
[1325]277 } else {
[1427]278 obsType = "RF";
[1325]279 }
280
[1399]281 // Brightness units.
282 bunit = cPKSMS.unit(MSMainEnums::FLOAT_DATA);
[1325]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,
[1452]356 const Int coordSys)
[1325]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
[1452]435 // Coordinate system? (Only equatorial available.)
436 cCoordSys = 0;
[1325]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
[1452]489Int PKSMS2reader::read(PKSrecord &pksrec)
[1325]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
[1452]517 pksrec.scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
[1325]518
[1452]519 if (pksrec.scanNo != cScanNo) {
[1325]520 // Start of new scan.
[1452]521 cScanNo = pksrec.scanNo;
[1325]522 cCycleNo = 1;
523 cTime = cTimeCol(cIdx);
524 }
525
526 Double time = cTimeCol(cIdx);
[1452]527 pksrec.mjd = time/86400.0;
528 pksrec.interval = cIntervalCol(cIdx);
[1325]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.
[1452]533 cCycleNo += nint((time - cTime)/pksrec.interval);
534 pksrec.cycleNo = cCycleNo;
535 cTime = time;
[1325]536
537 Int fieldId = cFieldIdCol(cIdx);
[1452]538 pksrec.fieldName = cFieldNameCol(fieldId);
[1325]539
540 Int srcId = cSrcIdCol(fieldId);
[1452]541 pksrec.srcName = cSrcNameCol(srcId);
542 pksrec.srcDir = cSrcDirCol(srcId);
543 pksrec.srcPM = cSrcPMCol(srcId);
[1325]544
545 // Systemic velocity.
546 if (!cHaveSrcVel) {
[1452]547 pksrec.srcVel = 0.0f;
[1325]548 } else {
[1452]549 pksrec.srcVel = cSrcVelCol(srcId)(IPosition(1,0));
[1325]550 }
551
552 // Observation type.
553 Int stateId = cStateIdCol(cIdx);
[1452]554 pksrec.obsType = cObsModeCol(stateId);
[1325]555
[1452]556 pksrec.IFno = iIF + 1;
[1325]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;
[1452]563 pksrec.freqInc = chanFreq(0);
564 pksrec.refFreq = chanFreq(0);
565 pksrec.restFreq = 0.0f;
[1325]566 } else {
567 if (cStartChan(iIF) <= cEndChan(iIF)) {
[1452]568 pksrec.freqInc = chanFreq(1) - chanFreq(0);
[1325]569 } else {
[1452]570 pksrec.freqInc = chanFreq(0) - chanFreq(1);
[1325]571 }
572
[1452]573 pksrec.refFreq = chanFreq(cRefChan(iIF)-1);
574 pksrec.restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
[1325]575 }
[1452]576 pksrec.bandwidth = abs(pksrec.freqInc * nChan);
[1325]577
[1452]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;
[1325]584
[1452]585 pksrec.focusAxi = 0.0f;
586 pksrec.focusTan = 0.0f;
587 pksrec.focusRot = 0.0f;
588
[1325]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.
[1452]600 pksrec.temperature = 0.0f;
601 pksrec.pressure = 0.0f;
602 pksrec.humidity = 0.0f;
[1325]603 } else {
[1452]604 pksrec.temperature = cTemperatureCol(weatherIdx);
605 pksrec.pressure = cPressureCol(weatherIdx);
606 pksrec.humidity = cHumidityCol(weatherIdx);
[1325]607 }
608
[1452]609 pksrec.windSpeed = 0.0f;
610 pksrec.windAz = 0.0f;
[1325]611
[1452]612 pksrec.refBeam = 0;
613 pksrec.beamNo = ibeam + 1;
[1325]614
615 Matrix<Double> pointingDir = cPointingCol(fieldId);
[1452]616 pksrec.direction = pointingDir.column(0);
617 pksrec.pCode = 0;
618 pksrec.rateAge = 0.0f;
[1325]619 uInt ncols = pointingDir.ncolumn();
620 if (ncols == 1) {
[1452]621 pksrec.scanRate = 0.0f;
[1325]622 } else {
[1452]623 pksrec.scanRate(0) = pointingDir.column(1)(0);
624 pksrec.scanRate(1) = pointingDir.column(1)(1);
[1325]625 }
[1452]626 pksrec.paRate = 0.0f;
[1325]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) {
[1452]636 cTsysCol.get(cIdx, pksrec.tsys, True);
[1325]637 } else {
638 Int numReceptor;
639 cNumReceptorCol.get(0, numReceptor);
[1452]640 pksrec.tsys.resize(numReceptor);
641 pksrec.tsys = 1.0f;
[1325]642 }
[1452]643 cSigmaCol.get(cIdx, pksrec.sigma, True);
[1325]644
645 // Calibration factors (if available).
[1452]646 pksrec.calFctr.resize(cNPol(iIF));
[1325]647 if (cHaveCalFctr) {
[1452]648 cCalFctrCol.get(cIdx, pksrec.calFctr);
[1325]649 } else {
[1452]650 pksrec.calFctr = 0.0f;
[1325]651 }
652
653 // Baseline parameters (if available).
654 if (cHaveBaseLin) {
[1452]655 pksrec.baseLin.resize(2,cNPol(iIF));
656 cBaseLinCol.get(cIdx, pksrec.baseLin);
[1325]657
[1635]658 pksrec.baseSub.resize(24,cNPol(iIF));
[1452]659 cBaseSubCol.get(cIdx, pksrec.baseSub);
[1325]660
661 } else {
[1452]662 pksrec.baseLin.resize(0,0);
663 pksrec.baseSub.resize(0,0);
[1325]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();
[1452]676 pksrec.spectra.resize(nChan, nPol);
677 pksrec.flagged.resize(nChan, nPol);
[1325]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++) {
[1452]682 pksrec.spectra(ichan,ipol) = tmpData(ipol,ichan);
683 pksrec.flagged(ichan,ipol) = tmpFlag(ipol,ichan);
[1325]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--) {
[1452]692 pksrec.spectra(ichan,ipol) = tmpData(ipol,jchan);
693 pksrec.flagged(ichan,ipol) = tmpFlag(ipol,jchan);
[1325]694 }
695 }
696 }
697 }
698
699 // Get cross-polarization data.
700 if (cGetXPol) {
701 if (cHaveXCalFctr) {
[1452]702 cXCalFctrCol.get(cIdx, pksrec.xCalFctr);
[1325]703 } else {
[1452]704 pksrec.xCalFctr = Complex(0.0f, 0.0f);
[1325]705 }
706
[1452]707 cDataCol.get(cIdx, pksrec.xPol, True);
[1325]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--) {
[1452]713 ctmp = pksrec.xPol(ichan);
714 pksrec.xPol(ichan) = pksrec.xPol(jchan);
715 pksrec.xPol(jchan) = ctmp;
[1325]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.