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

Last change on this file since 1331 was 1325, checked in by mar637, 18 years ago

Changes to use casacore instead of casa_asap/aips++\nAdded atnf PKSIO library snapshot to external and linking against this local copy

File size: 22.2 KB
Line 
1//#---------------------------------------------------------------------------
2//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
3//#---------------------------------------------------------------------------
4//# Copyright (C) 2000-2006
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.11 2006/07/05 04:59:20 mcalabre 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 Float &equinox,
252 String &dopplerFrame,
253 Double &mjd,
254 Double &refFreq,
255 Double &bandwidth)
256{
257 if (!cMSopen) {
258 return 1;
259 }
260
261 // Observer and project.
262 ROMSObservationColumns observationCols(cPKSMS.observation());
263 observer = observationCols.observer()(0);
264 project = observationCols.project()(0);
265
266 // Antenna name and ITRF coordinates.
267 ROMSAntennaColumns antennaCols(cPKSMS.antenna());
268 antName = antennaCols.name()(0);
269 antPosition = antennaCols.position()(0);
270
271 // Observation type.
272 if (cObsModeCol.nrow()) {
273 obsMode = cObsModeCol(0);
274 if (obsMode == "\0") obsMode = "RF";
275 } else {
276 obsMode = "RF";
277 }
278
279
280 // Coordinate equinox.
281 ROMSPointingColumns pointingCols(cPKSMS.pointing());
282 String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
283 asString("Ref");
284 sscanf(dirref.chars()+1, "%f", &equinox);
285
286 // Frequency/velocity reference frame.
287 ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
288 dopplerFrame = MFrequency::showType(spWinCols.measFreqRef()(0));
289
290 // Translate to FITS standard names.
291 if (dopplerFrame == "TOPO") {
292 dopplerFrame = "TOPOCENT";
293 } else if (dopplerFrame == "GEO") {
294 dopplerFrame = "GEOCENTR";
295 } else if (dopplerFrame == "BARY") {
296 dopplerFrame = "BARYCENT";
297 } else if (dopplerFrame == "GALACTO") {
298 dopplerFrame = "GALACTOC";
299 } else if (dopplerFrame == "LGROUP") {
300 dopplerFrame = "LOCALGRP";
301 } else if (dopplerFrame == "CMB") {
302 dopplerFrame = "CMBDIPOL";
303 } else if (dopplerFrame == "REST") {
304 dopplerFrame = "SOURCE";
305 }
306
307 // MJD at start of observation.
308 mjd = cTimeCol(0)/86400.0;
309
310 // Reference frequency and bandwidth.
311 refFreq = spWinCols.refFrequency()(0);
312 bandwidth = spWinCols.totalBandwidth()(0);
313
314 return 0;
315}
316
317//-------------------------------------------------- PKSMS2reader::getFreqInfo
318
319// Get frequency parameters for each IF.
320
321Int PKSMS2reader::getFreqInfo(
322 Vector<Double> &startFreq,
323 Vector<Double> &endFreq)
324{
325 uInt nIF = cIFs.nelements();
326 startFreq.resize(nIF);
327 endFreq.resize(nIF);
328
329 for (uInt iIF = 0; iIF < nIF; iIF++) {
330 Vector<Double> chanFreq = cChanFreqCol(iIF);
331
332 Int nChan = chanFreq.nelements();
333 startFreq(iIF) = chanFreq(0);
334 endFreq(iIF) = chanFreq(nChan-1);
335 }
336
337 return 0;
338}
339
340//------------------------------------------------------- PKSMS2reader::select
341
342// Set data selection by beam number and channel.
343
344uInt PKSMS2reader::select(
345 const Vector<Bool> beamSel,
346 const Vector<Bool> IFsel,
347 const Vector<Int> startChan,
348 const Vector<Int> endChan,
349 const Vector<Int> refChan,
350 const Bool getSpectra,
351 const Bool getXPol,
352 const Bool getFeedPos)
353{
354 if (!cMSopen) {
355 return 1;
356 }
357
358 // Beam selection.
359 uInt nBeam = cBeams.nelements();
360 uInt nBeamSel = beamSel.nelements();
361 for (uInt ibeam = 0; ibeam < nBeam; ibeam++) {
362 if (ibeam < nBeamSel) {
363 cBeams(ibeam) = beamSel(ibeam);
364 } else {
365 cBeams(ibeam) = False;
366 }
367 }
368
369 uInt nIF = cIFs.nelements();
370 uInt maxNChan = 0;
371 for (uInt iIF = 0; iIF < nIF; iIF++) {
372 // IF selection.
373 if (iIF < IFsel.nelements()) {
374 cIFs(iIF) = IFsel(iIF);
375 } else {
376 cIFs(iIF) = False;
377 }
378
379 if (!cIFs(iIF)) continue;
380
381
382 // Channel selection.
383 if (iIF < startChan.nelements()) {
384 cStartChan(iIF) = startChan(iIF);
385
386 if (cStartChan(iIF) <= 0) {
387 cStartChan(iIF) += cNChan(iIF);
388 } else if (cStartChan(iIF) > Int(cNChan(iIF))) {
389 cStartChan(iIF) = cNChan(iIF);
390 }
391 }
392
393 if (iIF < endChan.nelements()) {
394 cEndChan(iIF) = endChan(iIF);
395
396 if (cEndChan(iIF) <= 0) {
397 cEndChan(iIF) += cNChan(iIF);
398 } else if (cEndChan(iIF) > Int(cNChan(iIF))) {
399 cEndChan(iIF) = cNChan(iIF);
400 }
401 }
402
403 if (iIF < refChan.nelements()) {
404 cRefChan(iIF) = refChan(iIF);
405 } else {
406 cRefChan(iIF) = cStartChan(iIF);
407 if (cStartChan(iIF) <= cEndChan(iIF)) {
408 cRefChan(iIF) += (cEndChan(iIF) - cStartChan(iIF) + 1)/2;
409 } else {
410 cRefChan(iIF) -= (cStartChan(iIF) - cEndChan(iIF) + 1)/2;
411 }
412 }
413
414 uInt nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
415 if (maxNChan < nChan) {
416 maxNChan = nChan;
417 }
418
419 // Inverted Slices are not allowed.
420 Slice outPols;
421 Slice outChans(min(cStartChan(iIF),cEndChan(iIF))-1, nChan);
422 cDataSel(iIF) = Slicer(outPols, outChans);
423 }
424
425 // Get spectral data?
426 cGetSpectra = getSpectra;
427
428 // Get cross-polarization data?
429 cGetXPol = cGetXPol && getXPol;
430
431 // Get feed positions? (Not available.)
432 cGetFeedPos = False;
433
434 return maxNChan;
435}
436
437//---------------------------------------------------- PKSMS2reader::findRange
438
439// Find the range of the data in time and position.
440
441Int PKSMS2reader::findRange(
442 Int &nRow,
443 Int &nSel,
444 Vector<Double> &timeSpan,
445 Matrix<Double> &positions)
446{
447 if (!cMSopen) {
448 return 1;
449 }
450
451 nRow = cNRow;
452
453 // Find the number of rows selected.
454 nSel = 0;
455 Vector<Bool> sel(nRow);
456 for (Int irow = 0; irow < nRow; irow++) {
457 if ((sel(irow) = cBeams(cBeamNoCol(irow)) &&
458 cIFs(cDataDescIdCol(irow)))) {
459 nSel++;
460 }
461 }
462
463 // Find the time range (s).
464 timeSpan.resize(2);
465 timeSpan(0) = cTimeCol(0);
466 timeSpan(1) = cTimeCol(nRow-1);
467
468 // Retrieve positions for selected data.
469 Int isel = 0;
470 positions.resize(2,nSel);
471 for (Int irow = 0; irow < nRow; irow++) {
472 if (sel(irow)) {
473 Matrix<Double> pointingDir = cPointingCol(cFieldIdCol(irow));
474 positions.column(isel++) = pointingDir.column(0);
475 }
476 }
477
478 return 0;
479}
480
481//--------------------------------------------------------- PKSMS2reader::read
482
483// Read the next data record.
484
485Int PKSMS2reader::read(
486 Int &scanNo,
487 Int &cycleNo,
488 Double &mjd,
489 Double &interval,
490 String &fieldName,
491 String &srcName,
492 Vector<Double> &srcDir,
493 Vector<Double> &srcPM,
494 Double &srcVel,
495 String &obsMode,
496 Int &IFno,
497 Double &refFreq,
498 Double &bandwidth,
499 Double &freqInc,
500 Double &restFreq,
501 Vector<Float> &tcal,
502 String &tcalTime,
503 Float &azimuth,
504 Float &elevation,
505 Float &parAngle,
506 Float &focusAxi,
507 Float &focusTan,
508 Float &focusRot,
509 Float &temperature,
510 Float &pressure,
511 Float &humidity,
512 Float &windSpeed,
513 Float &windAz,
514 Int &refBeam,
515 Int &beamNo,
516 Vector<Double> &direction,
517 Vector<Double> &scanRate,
518 Vector<Float> &tsys,
519 Vector<Float> &sigma,
520 Vector<Float> &calFctr,
521 Matrix<Float> &baseLin,
522 Matrix<Float> &baseSub,
523 Matrix<Float> &spectra,
524 Matrix<uChar> &flagged,
525 Complex &xCalFctr,
526 Vector<Complex> &xPol)
527{
528 if (!cMSopen) {
529 return 1;
530 }
531
532 // Check for EOF.
533 if (cIdx >= cNRow) {
534 return -1;
535 }
536
537 // Find the next selected beam and IF.
538 Int ibeam;
539 Int iIF;
540 while (True) {
541 ibeam = cBeamNoCol(cIdx);
542 iIF = cDataDescIdCol(cIdx);
543 if (cBeams(ibeam) && cIFs(iIF)) {
544 break;
545 }
546
547 // Check for EOF.
548 if (++cIdx >= cNRow) {
549 return -1;
550 }
551 }
552
553 // Renumerate scan no. Here still is 1-based
554 scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
555
556 if (scanNo != cScanNo) {
557 // Start of new scan.
558 cScanNo = scanNo;
559 cCycleNo = 1;
560 cTime = cTimeCol(cIdx);
561 }
562
563 Double time = cTimeCol(cIdx);
564 mjd = time/86400.0;
565 interval = cIntervalCol(cIdx);
566
567 // Reconstruct the integration cycle number; due to small latencies the
568 // integration time is usually slightly less than the time between cycles,
569 // resetting cTime will prevent the difference from accumulating.
570 cCycleNo += nint((time - cTime)/interval);
571 cycleNo = cCycleNo;
572 cTime = time;
573
574 Int fieldId = cFieldIdCol(cIdx);
575 fieldName = cFieldNameCol(fieldId);
576
577 Int srcId = cSrcIdCol(fieldId);
578 srcName = cSrcNameCol(srcId);
579 srcDir = cSrcDirCol(srcId);
580 srcPM = cSrcPMCol(srcId);
581
582 // Systemic velocity.
583 if (!cHaveSrcVel) {
584 srcVel = 0.0f;
585 } else {
586 srcVel = cSrcVelCol(srcId)(IPosition(1,0));
587 }
588
589 // Observation type.
590 Int stateId = cStateIdCol(cIdx);
591 obsMode = cObsModeCol(stateId);
592
593 IFno = iIF + 1;
594 Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
595
596 // Minimal handling on continuum data.
597 Vector<Double> chanFreq = cChanFreqCol(iIF);
598 if (nChan == 1) {
599 cout << "The input is continuum data. "<< endl;
600 freqInc = chanFreq(0);
601 refFreq = chanFreq(0);
602 restFreq = 0.0f;
603 } else {
604 if (cStartChan(iIF) <= cEndChan(iIF)) {
605 freqInc = chanFreq(1) - chanFreq(0);
606 } else {
607 freqInc = chanFreq(0) - chanFreq(1);
608 }
609
610 refFreq = chanFreq(cRefChan(iIF)-1);
611 restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
612 }
613 bandwidth = abs(freqInc * nChan);
614
615 tcal.resize(cNPol(iIF));
616 tcal = 0.0f;
617 tcalTime = "";
618 azimuth = 0.0f;
619 elevation = 0.0f;
620 parAngle = 0.0f;
621 focusAxi = 0.0f;
622 focusTan = 0.0f;
623 focusRot = 0.0f;
624
625 // Find the appropriate entry in the WEATHER subtable.
626 Vector<Double> wTimes = cWeatherTimeCol.getColumn();
627 Int weatherIdx;
628 for (weatherIdx = wTimes.nelements()-1; weatherIdx >= 0; weatherIdx--) {
629 if (cWeatherTimeCol(weatherIdx) <= time) {
630 break;
631 }
632 }
633
634 if (weatherIdx < 0) {
635 // No appropriate WEATHER entry.
636 pressure = 0.0f;
637 humidity = 0.0f;
638 temperature = 0.0f;
639 } else {
640 pressure = cPressureCol(weatherIdx);
641 humidity = cHumidityCol(weatherIdx);
642 temperature = cTemperatureCol(weatherIdx);
643 }
644
645 windSpeed = 0.0f;
646 windAz = 0.0f;
647
648 refBeam = 0;
649 beamNo = ibeam + 1;
650
651 Matrix<Double> pointingDir = cPointingCol(fieldId);
652 direction = pointingDir.column(0);
653 uInt ncols = pointingDir.ncolumn();
654 if (ncols == 1) {
655 scanRate = 0.0f;
656 } else {
657 scanRate = pointingDir.column(1);
658 }
659
660 // Get Tsys assuming that entries in the SYSCAL table match the main table.
661 if (cHaveTsys) {
662 Int nTsysColRow = cTsysCol.nrow();
663 if (nTsysColRow != cNRow) {
664 cHaveTsys=0;
665 }
666 }
667 if (cHaveTsys) {
668 cTsysCol.get(cIdx, tsys, True);
669 } else {
670 Int numReceptor;
671 cNumReceptorCol.get(0, numReceptor);
672 tsys.resize(numReceptor);
673 tsys = 1.0f;
674 }
675 cSigmaCol.get(cIdx, sigma, True);
676
677 // Calibration factors (if available).
678 calFctr.resize(cNPol(iIF));
679 if (cHaveCalFctr) {
680 cCalFctrCol.get(cIdx, calFctr);
681 } else {
682 calFctr = 0.0f;
683 }
684
685 // Baseline parameters (if available).
686 if (cHaveBaseLin) {
687 baseLin.resize(2,cNPol(iIF));
688 cBaseLinCol.get(cIdx, baseLin);
689
690 baseSub.resize(9,cNPol(iIF));
691 cBaseSubCol.get(cIdx, baseSub);
692
693 } else {
694 baseLin.resize(0,0);
695 baseSub.resize(0,0);
696 }
697
698
699 // Get spectral data.
700 if (cGetSpectra) {
701 Matrix<Float> tmpData;
702 Matrix<Bool> tmpFlag;
703 cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
704 cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
705
706 // Transpose spectra.
707 Int nPol = tmpData.nrow();
708 spectra.resize(nChan, nPol);
709 flagged.resize(nChan, nPol);
710 if (cEndChan(iIF) >= cStartChan(iIF)) {
711 // Simple transposition.
712 for (Int ipol = 0; ipol < nPol; ipol++) {
713 for (Int ichan = 0; ichan < nChan; ichan++) {
714 spectra(ichan,ipol) = tmpData(ipol,ichan);
715 flagged(ichan,ipol) = tmpFlag(ipol,ichan);
716 }
717 }
718
719 } else {
720 // Transpose with inversion.
721 Int jchan = nChan - 1;
722 for (Int ipol = 0; ipol < nPol; ipol++) {
723 for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
724 spectra(ichan,ipol) = tmpData(ipol,jchan);
725 flagged(ichan,ipol) = tmpFlag(ipol,jchan);
726 }
727 }
728 }
729 }
730
731 // Get cross-polarization data.
732 if (cGetXPol) {
733 if (cHaveXCalFctr) {
734 cXCalFctrCol.get(cIdx, xCalFctr);
735 } else {
736 xCalFctr = Complex(0.0f, 0.0f);
737 }
738
739 cDataCol.get(cIdx, xPol, True);
740
741 if (cEndChan(iIF) < cStartChan(iIF)) {
742 Complex ctmp;
743 Int jchan = nChan - 1;
744 for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
745 ctmp = xPol(ichan);
746 xPol(ichan) = xPol(jchan);
747 xPol(jchan) = ctmp;
748 }
749 }
750 }
751
752 cIdx++;
753
754 return 0;
755}
756
757//--------------------------------------------------------- PKSMS2reader::read
758
759// Read the next data record, just the basics.
760
761Int PKSMS2reader::read(
762 Int &IFno,
763 Vector<Float> &tsys,
764 Vector<Float> &calFctr,
765 Matrix<Float> &baseLin,
766 Matrix<Float> &baseSub,
767 Matrix<Float> &spectra,
768 Matrix<uChar> &flagged)
769{
770 if (!cMSopen) {
771 return 1;
772 }
773
774 // Check for EOF.
775 if (cIdx >= cNRow) {
776 return -1;
777 }
778
779 // Find the next selected beam and IF.
780 Int ibeam;
781 Int iIF;
782 while (True) {
783 ibeam = cBeamNoCol(cIdx);
784 iIF = cDataDescIdCol(cIdx);
785 if (cBeams(ibeam) && cIFs(iIF)) {
786 break;
787 }
788
789 // Check for EOF.
790 if (++cIdx >= cNRow) {
791 return -1;
792 }
793 }
794
795 IFno = iIF + 1;
796
797 // Get Tsys assuming that entries in the SYSCAL table match the main table.
798 cTsysCol.get(cIdx, tsys, True);
799
800 // Calibration factors (if available).
801 if (cHaveCalFctr) {
802 cCalFctrCol.get(cIdx, calFctr, True);
803 } else {
804 calFctr.resize(cNPol(iIF));
805 calFctr = 0.0f;
806 }
807
808 // Baseline parameters (if available).
809 if (cHaveBaseLin) {
810 baseLin.resize(2,cNPol(iIF));
811 cBaseLinCol.get(cIdx, baseLin);
812
813 baseSub.resize(9,cNPol(iIF));
814 cBaseSubCol.get(cIdx, baseSub);
815
816 } else {
817 baseLin.resize(0,0);
818 baseSub.resize(0,0);
819 }
820
821 if (cGetSpectra) {
822 // Get spectral data.
823 Matrix<Float> tmpData;
824 Matrix<Bool> tmpFlag;
825 cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
826 cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
827
828 // Transpose spectra.
829 Int nChan = tmpData.ncolumn();
830 Int nPol = tmpData.nrow();
831 spectra.resize(nChan, nPol);
832 flagged.resize(nChan, nPol);
833 if (cEndChan(iIF) >= cStartChan(iIF)) {
834 // Simple transposition.
835 for (Int ipol = 0; ipol < nPol; ipol++) {
836 for (Int ichan = 0; ichan < nChan; ichan++) {
837 spectra(ichan,ipol) = tmpData(ipol,ichan);
838 flagged(ichan,ipol) = tmpFlag(ipol,ichan);
839 }
840 }
841
842 } else {
843 // Transpose with inversion.
844 Int jchan = nChan - 1;
845 for (Int ipol = 0; ipol < nPol; ipol++) {
846 for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
847 spectra(ichan,ipol) = tmpData(ipol,jchan);
848 flagged(ichan,ipol) = tmpFlag(ipol,jchan);
849 }
850 }
851 }
852 }
853
854 cIdx++;
855
856 return 0;
857}
858
859//-------------------------------------------------------- PKSMS2reader::close
860
861// Close the MS.
862
863void PKSMS2reader::close()
864{
865 cPKSMS = MeasurementSet();
866 cMSopen = False;
867}
Note: See TracBrowser for help on using the repository browser.