source: branches/alma/external/atnf/PKSIO/PKSMS2reader.cc@ 1398

Last change on this file since 1398 was 1393, checked in by TakTsutsumi, 17 years ago

Changes to handle GBT MS data

File size: 28.0 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$
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#include <casa/Quanta/MVTime.h>
41#include <casa/Quanta/MVAngle.h>
42#include <casa/BasicMath/Math.h>
43#include <measures/Measures/MeasConvert.h>
44#include <measures/Measures/MEpoch.h>
45#include <measures/Measures/MeasRef.h>
46
47
48// Parkes includes.
49#include <atnf/pks/pks_maths.h>
50#include <atnf/PKSIO/PKSMS2reader.h>
51
52
53//------------------------------------------------- PKSMS2reader::PKSMS2reader
54
55// Default constructor.
56
57PKSMS2reader::PKSMS2reader()
58{
59 cMSopen = False;
60}
61
62//------------------------------------------------ PKSMS2reader::~PKSMS2reader
63
64PKSMS2reader::~PKSMS2reader()
65{
66 close();
67}
68
69//--------------------------------------------------------- PKSMS2reader::open
70
71// Open the MS for reading.
72
73Int PKSMS2reader::open(
74 const String msName,
75 Vector<Bool> &beams,
76 Vector<Bool> &IFs,
77 Vector<uInt> &nChan,
78 Vector<uInt> &nPol,
79 Vector<Bool> &haveXPol,
80 Bool &haveBase,
81 Bool &haveSpectra)
82{
83 // Check that MS is readable.
84 if (!MS::isReadable(msName)) {
85 return 1;
86 }
87
88 if (cMSopen) {
89 close();
90 }
91
92 cPKSMS = MeasurementSet(msName);
93 // taql access to the syscal table
94 String tmpcalName = msName;
95 tmpcalName.append("/SYSCAL");
96 cSysCalTab = Table(tmpcalName);
97
98 cIdx = 0;
99 lastmjd = 0.0;
100 cNRow = cPKSMS.nrow();
101 cMSopen = True;
102
103 // Lock the table for read access.
104 cPKSMS.lock(False);
105
106 // Main MS table and subtable column access.
107 ROMSMainColumns msCols(cPKSMS);
108 ROMSDataDescColumns dataDescCols(cPKSMS.dataDescription());
109 ROMSFeedColumns feedCols(cPKSMS.feed());
110 ROMSFieldColumns fieldCols(cPKSMS.field());
111 ROMSPointingColumns pointingCols(cPKSMS.pointing());
112 ROMSPolarizationColumns polarizationCols(cPKSMS.polarization());
113 ROMSSourceColumns sourceCols(cPKSMS.source());
114 ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
115 ROMSStateColumns stateCols(cPKSMS.state());
116 ROMSSysCalColumns sysCalCols(cPKSMS.sysCal());
117 ROMSWeatherColumns weatherCols(cPKSMS.weather());
118
119 // Column accessors for required columns.
120 cScanNoCol.reference(msCols.scanNumber());
121 cTimeCol.reference(msCols.time());
122 cIntervalCol.reference(msCols.interval());
123
124 cFieldIdCol.reference(msCols.fieldId());
125 cFieldNameCol.reference(fieldCols.name());
126 cFieldDelayDirCol.reference(fieldCols.delayDir());
127
128 cSrcIdCol.reference(fieldCols.sourceId());
129 cSrcId2Col.reference(sourceCols.sourceId());
130 cSrcNameCol.reference(sourceCols.name());
131 cSrcDirCol.reference(sourceCols.direction());
132 cSrcPMCol.reference(sourceCols.properMotion());
133 cSrcRestFrqCol.reference(sourceCols.restFrequency());
134
135 cStateIdCol.reference(msCols.stateId());
136 cObsModeCol.reference(stateCols.obsMode());
137 cCalCol.reference(stateCols.cal());
138 cSigStateCol.reference(stateCols.sig());
139 cRefStateCol.reference(stateCols.ref());
140 cDataDescIdCol.reference(msCols.dataDescId());
141 cSpWinIdCol.reference(dataDescCols.spectralWindowId());
142 cChanFreqCol.reference(spWinCols.chanFreq());
143
144 cWeatherTimeCol.reference(weatherCols.time());
145 cTemperatureCol.reference(weatherCols.temperature());
146 cPressureCol.reference(weatherCols.pressure());
147 cHumidityCol.reference(weatherCols.relHumidity());
148
149 cBeamNoCol.reference(msCols.feed1());
150 cPointingCol.reference(pointingCols.direction());
151 cSigmaCol.reference(msCols.sigma());
152 cNumReceptorCol.reference(feedCols.numReceptors());
153
154 // Optional columns.
155 if ((cHaveSrcVel = cPKSMS.source().tableDesc().isColumn("SYSVEL"))) {
156 cSrcVelCol.attach(cPKSMS.source(), "SYSVEL");
157 }
158
159 if ((cHaveTsys = cPKSMS.sysCal().tableDesc().isColumn("TSYS"))) {
160 cTsysCol.attach(cPKSMS.sysCal(), "TSYS");
161 }
162
163 if ((cHaveTcal = cPKSMS.sysCal().tableDesc().isColumn("TCAL"))) {
164 cTcalCol.attach(cPKSMS.sysCal(), "TCAL");
165 }
166
167 if ((cHaveCalFctr = cPKSMS.tableDesc().isColumn("CALFCTR"))) {
168 cCalFctrCol.attach(cPKSMS, "CALFCTR");
169 }
170
171 if ((cHaveBaseLin = cPKSMS.tableDesc().isColumn("BASELIN"))) {
172 cBaseLinCol.attach(cPKSMS, "BASELIN");
173 cBaseSubCol.attach(cPKSMS, "BASESUB");
174 }
175
176 // Spectral data should always be present.
177 haveSpectra = True;
178 cFloatDataCol.reference(msCols.floatData());
179 cFlagCol.reference(msCols.flag());
180
181
182 if ((cGetXPol = cPKSMS.isColumn(MSMainEnums::DATA))) {
183 if ((cHaveXCalFctr = cPKSMS.tableDesc().isColumn("XCALFCTR"))) {
184 cXCalFctrCol.attach(cPKSMS, "XCALFCTR");
185 }
186
187 cDataCol.reference(msCols.data());
188 }
189
190 // Find which beams are present in the data.
191 Vector<Int> beamNos = cBeamNoCol.getColumn();
192 Int maxBeamNo = max(beamNos) + 1;
193 beams.resize(maxBeamNo);
194
195 beams = False;
196 for (uInt irow = 0; irow < beamNos.nelements(); irow++) {
197 beams(beamNos(irow)) = True;
198 }
199
200
201 // Number of IFs.
202 //uInt nIF = dataDescCols.nrow();
203 uInt nIF =spWinCols.nrow();
204 IFs.resize(nIF);
205 IFs = True;
206
207 // Number of polarizations and channels in each IF.
208 ROScalarColumn<Int> spWinIdCol(dataDescCols.spectralWindowId());
209 ROScalarColumn<Int> numChanCol(spWinCols.numChan());
210
211 ROScalarColumn<Int> polIdCol(dataDescCols.polarizationId());
212 ROScalarColumn<Int> numPolCol(polarizationCols.numCorr());
213
214 nChan.resize(nIF);
215 nPol.resize(nIF);
216 for (uInt iIF = 0; iIF < nIF; iIF++) {
217 nChan(iIF) = numChanCol(spWinIdCol(iIF));
218 nPol(iIF) = numPolCol(polIdCol(iIF));
219 }
220
221 // Cross-polarization data present?
222 haveXPol.resize(nIF);
223 haveXPol = False;
224
225 if (cGetXPol) {
226 for (Int irow = 0; irow < cNRow; irow++) {
227 if (cDataCol.isDefined(irow)) {
228 Int iIF = cDataDescIdCol(irow);
229 haveXPol(iIF) = True;
230 }
231 }
232 }
233
234
235 // Initialize member data.
236 cBeams.assign(beams);
237 cIFs.assign(IFs);
238 cNChan.assign(nChan);
239 cNPol.assign(nPol);
240 cHaveXPol.assign(haveXPol);
241
242
243 // Default channel range selection.
244 cStartChan.resize(nIF);
245 cEndChan.resize(nIF);
246 cRefChan.resize(nIF);
247
248 for (uInt iIF = 0; iIF < nIF; iIF++) {
249 cStartChan(iIF) = 1;
250 cEndChan(iIF) = cNChan(iIF);
251 cRefChan(iIF) = cNChan(iIF)/2 + 1;
252 }
253
254 Slice all;
255 cDataSel.resize(nIF);
256 cDataSel = Slicer(all, all);
257
258 cScanNo = 0;
259 cCycleNo = 1;
260 cTime = cTimeCol(0);
261
262 return 0;
263}
264
265//---------------------------------------------------- PKSMS2reader::getHeader
266
267// Get parameters describing the data.
268
269Int PKSMS2reader::getHeader(
270 String &observer,
271 String &project,
272 String &antName,
273 Vector<Double> &antPosition,
274 String &obsMode,
275 Float &equinox,
276 String &dopplerFrame,
277 Double &mjd,
278 Double &refFreq,
279 Double &bandwidth,
280 String &fluxunit)
281{
282 if (!cMSopen) {
283 return 1;
284 }
285
286 // Observer and project.
287 ROMSObservationColumns observationCols(cPKSMS.observation());
288 observer = observationCols.observer()(0);
289 project = observationCols.project()(0);
290
291 // Antenna name and ITRF coordinates.
292 ROMSAntennaColumns antennaCols(cPKSMS.antenna());
293 antName = antennaCols.name()(0);
294 antPosition = antennaCols.position()(0);
295
296 // Observation type.
297 if (cObsModeCol.nrow()) {
298 obsMode = cObsModeCol(0);
299 if (obsMode == "\0") obsMode = "RF";
300 } else {
301 obsMode = "RF";
302 }
303
304 fluxunit = "";
305 const TableRecord& keywordSet
306 = cFloatDataCol.columnDesc().keywordSet();
307 if(keywordSet.isDefined("UNIT")) {
308 fluxunit = keywordSet.asString("UNIT");
309 }
310
311 // Coordinate equinox.
312 ROMSPointingColumns pointingCols(cPKSMS.pointing());
313 String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
314 asString("Ref");
315 sscanf(dirref.chars()+1, "%f", &equinox);
316
317 // Frequency/velocity reference frame.
318 ROMSSpWindowColumns spWinCols(cPKSMS.spectralWindow());
319 dopplerFrame = MFrequency::showType(spWinCols.measFreqRef()(0));
320
321 // Translate to FITS standard names.
322 if (dopplerFrame == "TOPO") {
323 dopplerFrame = "TOPOCENT";
324 } else if (dopplerFrame == "GEO") {
325 dopplerFrame = "GEOCENTR";
326 } else if (dopplerFrame == "BARY") {
327 dopplerFrame = "BARYCENT";
328 } else if (dopplerFrame == "GALACTO") {
329 dopplerFrame = "GALACTOC";
330 } else if (dopplerFrame == "LGROUP") {
331 dopplerFrame = "LOCALGRP";
332 } else if (dopplerFrame == "CMB") {
333 dopplerFrame = "CMBDIPOL";
334 } else if (dopplerFrame == "REST") {
335 dopplerFrame = "SOURCE";
336 }
337
338 // MJD at start of observation.
339 mjd = cTimeCol(0)/86400.0;
340
341 // Reference frequency and bandwidth.
342 refFreq = spWinCols.refFrequency()(0);
343 bandwidth = spWinCols.totalBandwidth()(0);
344
345 return 0;
346}
347
348//-------------------------------------------------- PKSMS2reader::getFreqInfo
349
350// Get frequency parameters for each IF.
351
352Int PKSMS2reader::getFreqInfo(
353 Vector<Double> &startFreq,
354 Vector<Double> &endFreq)
355{
356 uInt nIF = cIFs.nelements();
357 startFreq.resize(nIF);
358 endFreq.resize(nIF);
359
360 for (uInt iIF = 0; iIF < nIF; iIF++) {
361 Vector<Double> chanFreq = cChanFreqCol(iIF);
362
363 Int nChan = chanFreq.nelements();
364 startFreq(iIF) = chanFreq(0);
365 endFreq(iIF) = chanFreq(nChan-1);
366 }
367
368 return 0;
369}
370
371//------------------------------------------------------- PKSMS2reader::select
372
373// Set data selection by beam number and channel.
374
375uInt PKSMS2reader::select(
376 const Vector<Bool> beamSel,
377 const Vector<Bool> IFsel,
378 const Vector<Int> startChan,
379 const Vector<Int> endChan,
380 const Vector<Int> refChan,
381 const Bool getSpectra,
382 const Bool getXPol,
383 const Bool getFeedPos)
384{
385 if (!cMSopen) {
386 return 1;
387 }
388
389 // Beam selection.
390 uInt nBeam = cBeams.nelements();
391 uInt nBeamSel = beamSel.nelements();
392 for (uInt ibeam = 0; ibeam < nBeam; ibeam++) {
393 if (ibeam < nBeamSel) {
394 cBeams(ibeam) = beamSel(ibeam);
395 } else {
396 cBeams(ibeam) = False;
397 }
398 }
399
400 uInt nIF = cIFs.nelements();
401 uInt maxNChan = 0;
402 for (uInt iIF = 0; iIF < nIF; iIF++) {
403 // IF selection.
404 if (iIF < IFsel.nelements()) {
405 cIFs(iIF) = IFsel(iIF);
406 } else {
407 cIFs(iIF) = False;
408 }
409
410 if (!cIFs(iIF)) continue;
411
412
413 // Channel selection.
414 if (iIF < startChan.nelements()) {
415 cStartChan(iIF) = startChan(iIF);
416
417 if (cStartChan(iIF) <= 0) {
418 cStartChan(iIF) += cNChan(iIF);
419 } else if (cStartChan(iIF) > Int(cNChan(iIF))) {
420 cStartChan(iIF) = cNChan(iIF);
421 }
422 }
423
424 if (iIF < endChan.nelements()) {
425 cEndChan(iIF) = endChan(iIF);
426
427 if (cEndChan(iIF) <= 0) {
428 cEndChan(iIF) += cNChan(iIF);
429 } else if (cEndChan(iIF) > Int(cNChan(iIF))) {
430 cEndChan(iIF) = cNChan(iIF);
431 }
432 }
433
434 if (iIF < refChan.nelements()) {
435 cRefChan(iIF) = refChan(iIF);
436 } else {
437 cRefChan(iIF) = cStartChan(iIF);
438 if (cStartChan(iIF) <= cEndChan(iIF)) {
439 cRefChan(iIF) += (cEndChan(iIF) - cStartChan(iIF) + 1)/2;
440 } else {
441 cRefChan(iIF) -= (cStartChan(iIF) - cEndChan(iIF) + 1)/2;
442 }
443 }
444
445 uInt nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
446 if (maxNChan < nChan) {
447 maxNChan = nChan;
448 }
449
450 // Inverted Slices are not allowed.
451 Slice outPols;
452 Slice outChans(min(cStartChan(iIF),cEndChan(iIF))-1, nChan);
453 cDataSel(iIF) = Slicer(outPols, outChans);
454 }
455
456 // Get spectral data?
457 cGetSpectra = getSpectra;
458
459 // Get cross-polarization data?
460 cGetXPol = cGetXPol && getXPol;
461
462 // Get feed positions? (Not available.)
463 cGetFeedPos = False;
464
465 return maxNChan;
466}
467
468//---------------------------------------------------- PKSMS2reader::findRange
469
470// Find the range of the data in time and position.
471
472Int PKSMS2reader::findRange(
473 Int &nRow,
474 Int &nSel,
475 Vector<Double> &timeSpan,
476 Matrix<Double> &positions)
477{
478 if (!cMSopen) {
479 return 1;
480 }
481
482 nRow = cNRow;
483
484 // Find the number of rows selected.
485 nSel = 0;
486 Vector<Bool> sel(nRow);
487 for (Int irow = 0; irow < nRow; irow++) {
488 if ((sel(irow) = cBeams(cBeamNoCol(irow)) &&
489 cIFs(cDataDescIdCol(irow)))) {
490 nSel++;
491 }
492 }
493
494 // Find the time range (s).
495 timeSpan.resize(2);
496 timeSpan(0) = cTimeCol(0);
497 timeSpan(1) = cTimeCol(nRow-1);
498
499 // Retrieve positions for selected data.
500 Int isel = 0;
501 positions.resize(2,nSel);
502 for (Int irow = 0; irow < nRow; irow++) {
503 if (sel(irow)) {
504 Matrix<Double> pointingDir = cPointingCol(cFieldIdCol(irow));
505 positions.column(isel++) = pointingDir.column(0);
506 }
507 }
508
509 return 0;
510}
511
512//--------------------------------------------------------- PKSMS2reader::read
513
514// Read the next data record.
515
516Int PKSMS2reader::read(
517 Int &scanNo,
518 Int &cycleNo,
519 Double &mjd,
520 Double &interval,
521 String &fieldName,
522 String &srcName,
523 Vector<Double> &srcDir,
524 Vector<Double> &srcPM,
525 Double &srcVel,
526 String &obsMode,
527 Int &IFno,
528 Double &refFreq,
529 Double &bandwidth,
530 Double &freqInc,
531 Double &restFreq,
532 Vector<Float> &tcal,
533 String &tcalTime,
534 Float &azimuth,
535 Float &elevation,
536 Float &parAngle,
537 Float &focusAxi,
538 Float &focusTan,
539 Float &focusRot,
540 Float &temperature,
541 Float &pressure,
542 Float &humidity,
543 Float &windSpeed,
544 Float &windAz,
545 Int &refBeam,
546 Int &beamNo,
547 Vector<Double> &direction,
548 Vector<Double> &scanRate,
549 Vector<Float> &tsys,
550 Vector<Float> &sigma,
551 Vector<Float> &calFctr,
552 Matrix<Float> &baseLin,
553 Matrix<Float> &baseSub,
554 Matrix<Float> &spectra,
555 Matrix<uChar> &flagged,
556 Complex &xCalFctr,
557 Vector<Complex> &xPol)
558{
559 if (!cMSopen) {
560 return 1;
561 }
562
563 // Check for EOF.
564 if (cIdx >= cNRow) {
565 return -1;
566 }
567
568 // Find the next selected beam and IF.
569 Int ibeam;
570 Int iIF;
571 Int iDataDesc;
572
573 while (True) {
574 ibeam = cBeamNoCol(cIdx);
575 iDataDesc = cDataDescIdCol(cIdx);
576 iIF =cSpWinIdCol(iDataDesc);
577 if (cBeams(ibeam) && cIFs(iIF)) {
578 break;
579 }
580
581 // Check for EOF.
582 if (++cIdx >= cNRow) {
583 return -1;
584 }
585 }
586
587 // Renumerate scan no. Here still is 1-based
588 //scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
589 scanNo = cScanNoCol(cIdx);
590
591 if (scanNo != cScanNo) {
592 // Start of new scan.
593 cScanNo = scanNo;
594 cCycleNo = 1;
595 cTime = cTimeCol(cIdx);
596 }
597
598 Double time = cTimeCol(cIdx);
599 mjd = time/86400.0;
600 interval = cIntervalCol(cIdx);
601
602 // Reconstruct the integration cycle number; due to small latencies the
603 // integration time is usually slightly less than the time between cycles,
604 // resetting cTime will prevent the difference from accumulating.
605 cCycleNo += nint((time - cTime)/interval);
606 cycleNo = cCycleNo;
607 cTime = time;
608
609 Int fieldId = cFieldIdCol(cIdx);
610 fieldName = cFieldNameCol(fieldId);
611
612 Int srcId = cSrcIdCol(fieldId);
613 //For source with multiple spectral window setting, this is not
614 // correct. Source name of srcId may not be at 'srcId'th row of SrcNameCol
615 //srcName = cSrcNameCol(srcId);
616 for (uInt irow = 0; irow < cSrcId2Col.nrow(); irow++) {
617 if (cSrcId2Col(irow) == srcId) {
618 srcName = cSrcNameCol(irow);
619 }
620 }
621
622 srcDir = cSrcDirCol(srcId);
623 srcPM = cSrcPMCol(srcId);
624
625 // Systemic velocity.
626 if (!cHaveSrcVel) {
627 srcVel = 0.0f;
628 } else {
629 srcVel = cSrcVelCol(srcId)(IPosition(1,0));
630 }
631
632 ROMSAntennaColumns antennaCols(cPKSMS.antenna());
633 String telescope = antennaCols.name()(0);
634 Bool cGBT = telescope.contains("GBT");
635 // Observation type.
636 Int stateId = cStateIdCol(cIdx);
637 if (stateId == -1) {
638 //obsMode = " ";
639 } else {
640 obsMode = cObsModeCol(stateId);
641 Bool sigState =cSigStateCol(stateId);
642 Bool refState =cRefStateCol(stateId);
643 //DEBUG
644 //cerr <<"stateid="<<stateId<<" obsmode="<<obsMode<<endl;
645 if (cGBT) {
646 // split the obsMode string and append a proper label
647 // (these are GBT specific)
648 int epos = obsMode.find_first_of(':');
649 int nextpos = obsMode.find_first_of(':',epos+1);
650 string obsMode1 = obsMode.substr(0,epos);
651 string obsMode2 = obsMode.substr(epos+1,nextpos-epos-1);
652
653 //cerr <<"obsMode2= "<<obsMode2<<endl;
654 if (!srcName.contains("_ps")
655 &&!srcName.contains("_psr")
656 &&!srcName.contains("_nod")
657 &&!srcName.contains("_fs")
658 &&!srcName.contains("_fsr")) {
659 // if Nod mode observation , append '_nod'
660 if (obsMode1 == "Nod") {
661 srcName.append("_nod");
662 } else if (obsMode1 == "OffOn") {
663 // for GBT position switch observations (OffOn or OnOff)
664 if (obsMode2 == "PSWITCHON") srcName.append("_ps");
665 if (obsMode2 == "PSWITCHOFF") srcName.append("_psr");
666 } else {
667 if (obsMode2 == "FSWITCH") {
668 // for GBT frequency switch mode
669 if (sigState) srcName.append("_fs");
670 if (refState) srcName.append("_fsr");
671 }
672 }
673 }
674 }
675 }
676 // CAL state
677 // this should be apply just for GBT data?
678 Double Cal;
679 if (stateId==-1) {
680 Cal = 0;
681 } else {
682 Cal = cCalCol(stateId);
683 }
684 if (cGBT) {
685 if (Cal > 0 && !srcName.contains("_calon")) {
686 srcName.append("_calon");
687 }
688 }
689
690 IFno = iIF + 1;
691 Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
692
693 // Minimal handling on continuum data.
694 Vector<Double> chanFreq = cChanFreqCol(iIF);
695 if (nChan == 1) {
696 cout << "The input is continuum data. "<< endl;
697 freqInc = chanFreq(0);
698 refFreq = chanFreq(0);
699 restFreq = 0.0f;
700 } else {
701 if (cStartChan(iIF) <= cEndChan(iIF)) {
702 freqInc = chanFreq(1) - chanFreq(0);
703 } else {
704 freqInc = chanFreq(0) - chanFreq(1);
705 }
706 refFreq = chanFreq(cRefChan(iIF)-1);
707 restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
708 }
709 bandwidth = abs(freqInc * nChan);
710
711 tcal.resize(cNPol(iIF));
712 tcal = 0.0f;
713 tcalTime = "";
714 //azimuth = 0.0f;
715 //elevation = 0.0f;
716 parAngle = 0.0f;
717 focusAxi = 0.0f;
718 focusTan = 0.0f;
719 focusRot = 0.0f;
720
721 // Find the appropriate entry in the WEATHER subtable.
722 Vector<Double> wTimes = cWeatherTimeCol.getColumn();
723 Int weatherIdx;
724 for (weatherIdx = wTimes.nelements()-1; weatherIdx >= 0; weatherIdx--) {
725 if (cWeatherTimeCol(weatherIdx) <= time) {
726 break;
727 }
728 }
729
730 if (weatherIdx < 0) {
731 // No appropriate WEATHER entry.
732 pressure = 0.0f;
733 humidity = 0.0f;
734 temperature = 0.0f;
735 } else {
736 pressure = cPressureCol(weatherIdx);
737 humidity = cHumidityCol(weatherIdx);
738 temperature = cTemperatureCol(weatherIdx);
739 }
740
741 windSpeed = 0.0f;
742 windAz = 0.0f;
743
744 refBeam = 0;
745 beamNo = ibeam + 1;
746
747 //Matrix<Double> pointingDir = cPointingCol(fieldId);
748 //pointingDir = cPointingCol(fieldId);
749 //direction = pointingDir.column(0);
750 //uInt ncols = pointingDir.ncolumn();
751 //if (ncols == 1) {
752 // scanRate = 0.0f;
753 //} else {
754 // scanRate = pointingDir.column(1);
755 //}
756
757 // Get direction from FIELD table
758 // here, assume direction to be the field direction not pointing
759 Matrix<Double> delayDir = cFieldDelayDirCol(fieldId);
760 direction = delayDir.column(0);
761 uInt ncols = delayDir.ncolumn();
762 if (ncols == 1) {
763 scanRate = 0.0f;
764 } else {
765 scanRate = delayDir.column(1);
766 }
767
768 // caluculate azimuth and elevation
769 // first, get the reference frame
770 MVPosition mvpos(antennaCols.position()(0));
771 MPosition mp(mvpos);
772 Quantum<Double> qt(time,"s");
773 MVEpoch mvt(qt);
774 MEpoch me(mvt);
775 MeasFrame frame(mp, me);
776 //
777 ROMSFieldColumns fldCols(cPKSMS.field());
778 Vector<MDirection> vmd(1);
779 MDirection md;
780 fldCols.delayDirMeasCol().get(fieldId,vmd);
781 md = vmd[0];
782 //Vector<Double> dircheck = md.getAngle("rad").getValue();
783 //cerr<<"dircheck="<<dircheck<<endl;
784
785 Vector<Double> azel =
786 MDirection::Convert(md, MDirection::Ref(MDirection::AZEL,
787 frame)
788 )().getAngle("rad").getValue();
789 //cerr<<"azel="<<azel<<endl;
790 azimuth = azel[0];
791 elevation = azel[1];
792
793 // Get Tsys assuming that entries in the SYSCAL table match the main table.
794 if (cHaveTsys) {
795 Int nTsysColRow = cTsysCol.nrow();
796 if (nTsysColRow != cNRow) {
797 cHaveTsys=0;
798 }
799 }
800 if (cHaveTsys) {
801 cTsysCol.get(cIdx, tsys, True);
802 } else {
803 Int numReceptor;
804 cNumReceptorCol.get(0, numReceptor);
805 tsys.resize(numReceptor);
806 tsys = 1.0f;
807 }
808 cSigmaCol.get(cIdx, sigma, True);
809
810 //get Tcal if available
811 if (cHaveTcal) {
812 Int nTcalColRow = cTcalCol.nrow();
813 uInt nBeam = cBeams.nelements();
814 uInt nIF = cIFs.nelements();
815 uInt nrws = nBeam * nIF;
816 if (nTcalColRow > 0) {
817 // find tcal match with the data with the data time stamp
818 Double mjds = mjd*(24*3600);
819 Double dtcalTime;
820 if ( mjd > lastmjd || cIdx==0 ) {
821 //Table tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds));
822 tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds), nrws);
823 //DEBUG
824 //if (cIdx == 0) {
825 // cerr<<"inital table retrieved"<<endl;
826 //}
827
828 }
829
830 if (nBeam == 1) {
831 tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF, 1);
832 } else {
833 tmptab2 = tmptab( tmptab.col("SPECTRAL_WINDOW_ID") == iIF &&
834 tmptab.col("FEED_ID") == ibeam , 1);
835 }
836 //cerr<<"first subtab rows="<<tmptab.nrow()<<endl;
837 int syscalrow = tmptab2.nrow();
838 ROArrayColumn<Float> tcalCol(tmptab2, "TCAL");
839 ROScalarColumn<Double> tcalTimeCol(tmptab2, "TIME");
840 if (syscalrow==0) {
841 cerr<<"Cannot find any matching Tcal at/near the data timestamp."
842 << " Set Tcal=0.0"<<endl;
843 } else {
844 tcalCol.get(0, tcal);
845 tcalTimeCol.get(0,dtcalTime);
846 tcalTime = MVTime(dtcalTime/(24*3600)).string(MVTime::YMD);
847 //DEBUG
848 //cerr<<"cIdx:"<<cIdx<<" tcal="<<tcal<<" tcalTime="<<tcalTime<<endl;
849 tmptab.markForDelete();
850 tmptab2.markForDelete();
851 }
852 }
853 lastmjd = mjd;
854 }
855
856 // Calibration factors (if available).
857 calFctr.resize(cNPol(iIF));
858 if (cHaveCalFctr) {
859 cCalFctrCol.get(cIdx, calFctr);
860 } else {
861 calFctr = 0.0f;
862 }
863
864 // Baseline parameters (if available).
865 if (cHaveBaseLin) {
866 baseLin.resize(2,cNPol(iIF));
867 cBaseLinCol.get(cIdx, baseLin);
868
869 baseSub.resize(9,cNPol(iIF));
870 cBaseSubCol.get(cIdx, baseSub);
871
872 } else {
873 baseLin.resize(0,0);
874 baseSub.resize(0,0);
875 }
876
877 // Get spectral data.
878 if (cGetSpectra) {
879 Matrix<Float> tmpData;
880 Matrix<Bool> tmpFlag;
881 cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
882 cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
883
884 // Transpose spectra.
885 Int nPol = tmpData.nrow();
886 spectra.resize(nChan, nPol);
887 flagged.resize(nChan, nPol);
888 if (cEndChan(iIF) >= cStartChan(iIF)) {
889 // Simple transposition.
890 for (Int ipol = 0; ipol < nPol; ipol++) {
891 for (Int ichan = 0; ichan < nChan; ichan++) {
892 spectra(ichan,ipol) = tmpData(ipol,ichan);
893 flagged(ichan,ipol) = tmpFlag(ipol,ichan);
894 }
895 }
896
897 } else {
898 // Transpose with inversion.
899 Int jchan = nChan - 1;
900 for (Int ipol = 0; ipol < nPol; ipol++) {
901 for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
902 spectra(ichan,ipol) = tmpData(ipol,jchan);
903 flagged(ichan,ipol) = tmpFlag(ipol,jchan);
904 }
905 }
906 }
907 }
908
909 // Get cross-polarization data.
910 if (cGetXPol) {
911 if (cHaveXCalFctr) {
912 cXCalFctrCol.get(cIdx, xCalFctr);
913 } else {
914 xCalFctr = Complex(0.0f, 0.0f);
915 }
916
917 cDataCol.get(cIdx, xPol, True);
918
919 if (cEndChan(iIF) < cStartChan(iIF)) {
920 Complex ctmp;
921 Int jchan = nChan - 1;
922 for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
923 ctmp = xPol(ichan);
924 xPol(ichan) = xPol(jchan);
925 xPol(jchan) = ctmp;
926 }
927 }
928 }
929
930 cIdx++;
931
932 return 0;
933}
934
935//--------------------------------------------------------- PKSMS2reader::read
936
937// Read the next data record, just the basics.
938
939Int PKSMS2reader::read(
940 Int &IFno,
941 Vector<Float> &tsys,
942 Vector<Float> &calFctr,
943 Matrix<Float> &baseLin,
944 Matrix<Float> &baseSub,
945 Matrix<Float> &spectra,
946 Matrix<uChar> &flagged)
947{
948 if (!cMSopen) {
949 return 1;
950 }
951
952 // Check for EOF.
953 if (cIdx >= cNRow) {
954 return -1;
955 }
956
957 // Find the next selected beam and IF.
958 Int ibeam;
959 Int iIF;
960 Int iDataDesc;
961 while (True) {
962 ibeam = cBeamNoCol(cIdx);
963 //iIF = cDataDescIdCol(cIdx);
964 iDataDesc = cDataDescIdCol(cIdx);
965 iIF = cSpWinIdCol(iDataDesc);
966 if (cBeams(ibeam) && cIFs(iIF)) {
967 break;
968 }
969
970 // Check for EOF.
971 if (++cIdx >= cNRow) {
972 return -1;
973 }
974 }
975
976 IFno = iIF + 1;
977 // Get Tsys assuming that entries in the SYSCAL table match the main table.
978 cTsysCol.get(cIdx, tsys, True);
979
980 // Calibration factors (if available).
981 if (cHaveCalFctr) {
982 cCalFctrCol.get(cIdx, calFctr, True);
983 } else {
984 calFctr.resize(cNPol(iIF));
985 calFctr = 0.0f;
986 }
987
988 // Baseline parameters (if available).
989 if (cHaveBaseLin) {
990 baseLin.resize(2,cNPol(iIF));
991 cBaseLinCol.get(cIdx, baseLin);
992
993 baseSub.resize(9,cNPol(iIF));
994 cBaseSubCol.get(cIdx, baseSub);
995
996 } else {
997 baseLin.resize(0,0);
998 baseSub.resize(0,0);
999 }
1000
1001 if (cGetSpectra) {
1002 // Get spectral data.
1003 Matrix<Float> tmpData;
1004 Matrix<Bool> tmpFlag;
1005 cFloatDataCol.getSlice(cIdx, cDataSel(iIF), tmpData, True);
1006 cFlagCol.getSlice(cIdx, cDataSel(iIF), tmpFlag, True);
1007
1008 // Transpose spectra.
1009 Int nChan = tmpData.ncolumn();
1010 Int nPol = tmpData.nrow();
1011 spectra.resize(nChan, nPol);
1012 flagged.resize(nChan, nPol);
1013 if (cEndChan(iIF) >= cStartChan(iIF)) {
1014 // Simple transposition.
1015 for (Int ipol = 0; ipol < nPol; ipol++) {
1016 for (Int ichan = 0; ichan < nChan; ichan++) {
1017 spectra(ichan,ipol) = tmpData(ipol,ichan);
1018 flagged(ichan,ipol) = tmpFlag(ipol,ichan);
1019 }
1020 }
1021
1022 } else {
1023 // Transpose with inversion.
1024 Int jchan = nChan - 1;
1025 for (Int ipol = 0; ipol < nPol; ipol++) {
1026 for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
1027 spectra(ichan,ipol) = tmpData(ipol,jchan);
1028 flagged(ichan,ipol) = tmpFlag(ipol,jchan);
1029 }
1030 }
1031 }
1032 }
1033
1034 cIdx++;
1035
1036 return 0;
1037}
1038
1039//-------------------------------------------------------- PKSMS2reader::close
1040
1041// Close the MS.
1042
1043void PKSMS2reader::close()
1044{
1045 cPKSMS = MeasurementSet();
1046 cMSopen = False;
1047}
Note: See TracBrowser for help on using the repository browser.