source: trunk/src/MSFiller.cpp@ 2293

Last change on this file since 2293 was 2292, checked in by Takeshi Nakazato, 13 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Support MS without SYSCAL table.


File size: 65.4 KB
Line 
1
2//
3// C++ Interface: MSFiller
4//
5// Description:
6//
7// This class is specific filler for MS format
8// New version that is implemented using TableVisitor instead of TableIterator
9//
10// Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2011
11//
12// Copyright: See COPYING file that comes with this distribution
13//
14//
15
16#include <assert.h>
17#include <iostream>
18#include <map>
19
20#include <tables/Tables/ExprNode.h>
21#include <tables/Tables/TableIter.h>
22#include <tables/Tables/TableColumn.h>
23#include <tables/Tables/ScalarColumn.h>
24#include <tables/Tables/ArrayColumn.h>
25#include <tables/Tables/TableParse.h>
26#include <tables/Tables/TableRow.h>
27
28#include <casa/Containers/RecordField.h>
29#include <casa/Logging/LogIO.h>
30#include <casa/Arrays/Slicer.h>
31#include <casa/Quanta/MVTime.h>
32#include <casa/OS/Path.h>
33
34#include <measures/Measures/Stokes.h>
35#include <measures/Measures/MEpoch.h>
36#include <measures/Measures/MCEpoch.h>
37#include <measures/Measures/MFrequency.h>
38#include <measures/Measures/MCFrequency.h>
39#include <measures/Measures/MPosition.h>
40#include <measures/Measures/MCPosition.h>
41#include <measures/Measures/MDirection.h>
42#include <measures/Measures/MCDirection.h>
43#include <measures/Measures/MeasConvert.h>
44#include <measures/TableMeasures/ScalarMeasColumn.h>
45#include <measures/TableMeasures/ArrayMeasColumn.h>
46#include <measures/TableMeasures/ScalarQuantColumn.h>
47#include <measures/TableMeasures/ArrayQuantColumn.h>
48
49#include <ms/MeasurementSets/MSAntennaIndex.h>
50
51#include <atnf/PKSIO/SrcType.h>
52
53#include "MSFiller.h"
54#include "STHeader.h"
55
56#include "MathUtils.h"
57
58using namespace casa ;
59using namespace std ;
60
61namespace asap {
62
63class BaseMSFillerVisitor: public TableVisitor {
64 uInt lastRecordNo ;
65 Int lastObservationId ;
66 Int lastFeedId ;
67 Int lastFieldId ;
68 Int lastDataDescId ;
69 Int lastScanNo ;
70 Int lastStateId ;
71 Double lastTime ;
72protected:
73 const Table &table;
74 uInt count;
75public:
76 BaseMSFillerVisitor(const Table &table)
77 : table(table)
78 {
79 count = 0;
80 }
81
82 virtual void enterObservationId(const uInt recordNo, Int columnValue) { }
83 virtual void leaveObservationId(const uInt recordNo, Int columnValue) { }
84 virtual void enterFeedId(const uInt recordNo, Int columnValue) { }
85 virtual void leaveFeedId(const uInt recordNo, Int columnValue) { }
86 virtual void enterFieldId(const uInt recordNo, Int columnValue) { }
87 virtual void leaveFieldId(const uInt recordNo, Int columnValue) { }
88 virtual void enterDataDescId(const uInt recordNo, Int columnValue) { }
89 virtual void leaveDataDescId(const uInt recordNo, Int columnValue) { }
90 virtual void enterScanNo(const uInt recordNo, Int columnValue) { }
91 virtual void leaveScanNo(const uInt recordNo, Int columnValue) { }
92 virtual void enterStateId(const uInt recordNo, Int columnValue) { }
93 virtual void leaveStateId(const uInt recordNo, Int columnValue) { }
94 virtual void enterTime(const uInt recordNo, Double columnValue) { }
95 virtual void leaveTime(const uInt recordNo, Double columnValue) { }
96
97 virtual Bool visitRecord(const uInt recordNo,
98 const Int ObservationId,
99 const Int feedId,
100 const Int fieldId,
101 const Int dataDescId,
102 const Int scanNo,
103 const Int stateId,
104 const Double time) { return True ; }
105
106 virtual Bool visit(Bool isFirst, const uInt recordNo,
107 const uInt nCols, void const *const colValues[]) {
108 Int observationId, feedId, fieldId, dataDescId, scanNo, stateId;
109 Double time;
110 { // prologue
111 uInt i = 0;
112 {
113 const Int *col = (const Int *)colValues[i++];
114 observationId = col[recordNo];
115 }
116 {
117 const Int *col = (const Int *)colValues[i++];
118 feedId = col[recordNo];
119 }
120 {
121 const Int *col = (const Int *)colValues[i++];
122 fieldId = col[recordNo];
123 }
124 {
125 const Int *col = (const Int *)colValues[i++];
126 dataDescId = col[recordNo];
127 }
128 {
129 const Int *col = (const Int *)colValues[i++];
130 scanNo = col[recordNo];
131 }
132 {
133 const Int *col = (const Int *)colValues[i++];
134 stateId = col[recordNo];
135 }
136 {
137 const Double *col = (const Double *)colValues[i++];
138 time = col[recordNo];
139 }
140 assert(nCols == i);
141 }
142
143 if (isFirst) {
144 enterObservationId(recordNo, observationId);
145 enterFeedId(recordNo, feedId);
146 enterFieldId(recordNo, fieldId);
147 enterDataDescId(recordNo, dataDescId);
148 enterScanNo(recordNo, scanNo);
149 enterStateId(recordNo, stateId);
150 enterTime(recordNo, time);
151 } else {
152 if (lastObservationId != observationId) {
153 leaveTime(lastRecordNo, lastTime);
154 leaveStateId(lastRecordNo, lastStateId);
155 leaveScanNo(lastRecordNo, lastScanNo);
156 leaveDataDescId(lastRecordNo, lastDataDescId);
157 leaveFieldId(lastRecordNo, lastFieldId);
158 leaveFeedId(lastRecordNo, lastFeedId);
159 leaveObservationId(lastRecordNo, lastObservationId);
160
161 enterObservationId(recordNo, observationId);
162 enterFeedId(recordNo, feedId);
163 enterFieldId(recordNo, fieldId);
164 enterDataDescId(recordNo, dataDescId);
165 enterScanNo(recordNo, scanNo);
166 enterStateId(recordNo, stateId);
167 enterTime(recordNo, time);
168 } else if (lastFeedId != feedId) {
169 leaveTime(lastRecordNo, lastTime);
170 leaveStateId(lastRecordNo, lastStateId);
171 leaveScanNo(lastRecordNo, lastScanNo);
172 leaveDataDescId(lastRecordNo, lastDataDescId);
173 leaveFieldId(lastRecordNo, lastFieldId);
174 leaveFeedId(lastRecordNo, lastFeedId);
175
176 enterFeedId(recordNo, feedId);
177 enterFieldId(recordNo, fieldId);
178 enterDataDescId(recordNo, dataDescId);
179 enterScanNo(recordNo, scanNo);
180 enterStateId(recordNo, stateId);
181 enterTime(recordNo, time);
182 } else if (lastFieldId != fieldId) {
183 leaveTime(lastRecordNo, lastTime);
184 leaveStateId(lastRecordNo, lastStateId);
185 leaveScanNo(lastRecordNo, lastScanNo);
186 leaveDataDescId(lastRecordNo, lastDataDescId);
187 leaveFieldId(lastRecordNo, lastFieldId);
188
189 enterFieldId(recordNo, fieldId);
190 enterDataDescId(recordNo, dataDescId);
191 enterScanNo(recordNo, scanNo);
192 enterStateId(recordNo, stateId);
193 enterTime(recordNo, time);
194 } else if (lastDataDescId != dataDescId) {
195 leaveTime(lastRecordNo, lastTime);
196 leaveStateId(lastRecordNo, lastStateId);
197 leaveScanNo(lastRecordNo, lastScanNo);
198 leaveDataDescId(lastRecordNo, lastDataDescId);
199
200 enterDataDescId(recordNo, dataDescId);
201 enterScanNo(recordNo, scanNo);
202 enterStateId(recordNo, stateId);
203 enterTime(recordNo, time);
204 } else if (lastScanNo != scanNo) {
205 leaveTime(lastRecordNo, lastTime);
206 leaveStateId(lastRecordNo, lastStateId);
207 leaveScanNo(lastRecordNo, lastScanNo);
208
209 enterScanNo(recordNo, scanNo);
210 enterStateId(recordNo, stateId);
211 enterTime(recordNo, time);
212 } else if (lastStateId != stateId) {
213 leaveTime(lastRecordNo, lastTime);
214 leaveStateId(lastRecordNo, lastStateId);
215
216 enterStateId(recordNo, stateId);
217 enterTime(recordNo, time);
218 } else if (lastTime != time) {
219 leaveTime(lastRecordNo, lastTime);
220 enterTime(recordNo, time);
221 }
222 }
223 count++;
224 Bool result = visitRecord(recordNo, observationId, feedId, fieldId, dataDescId,
225 scanNo, stateId, time);
226
227 { // epilogue
228 lastRecordNo = recordNo;
229
230 lastObservationId = observationId;
231 lastFeedId = feedId;
232 lastFieldId = fieldId;
233 lastDataDescId = dataDescId;
234 lastScanNo = scanNo;
235 lastStateId = stateId;
236 lastTime = time;
237 }
238 return result ;
239 }
240
241 virtual void finish() {
242 if (count > 0) {
243 leaveTime(lastRecordNo, lastTime);
244 leaveStateId(lastRecordNo, lastStateId);
245 leaveScanNo(lastRecordNo, lastScanNo);
246 leaveDataDescId(lastRecordNo, lastDataDescId);
247 leaveFieldId(lastRecordNo, lastFieldId);
248 leaveFeedId(lastRecordNo, lastFeedId);
249 leaveObservationId(lastRecordNo, lastObservationId);
250 }
251 }
252};
253
254class MSFillerVisitor: public BaseMSFillerVisitor, public MSFillerUtils {
255public:
256 MSFillerVisitor(const Table &from, Scantable &to)
257 : BaseMSFillerVisitor(from),
258 scantable( to )
259 {
260 antennaId = 0 ;
261 rowidx = 0 ;
262 tablerow = TableRow( scantable.table() ) ;
263 feedEntry = Vector<Int>( 64, -1 ) ;
264 nbeam = 0 ;
265 ifmap.clear() ;
266 const TableDesc &desc = table.tableDesc() ;
267 if ( desc.isColumn( "DATA" ) )
268 dataColumnName = "DATA" ;
269 else if ( desc.isColumn( "FLOAT_DATA" ) )
270 dataColumnName = "FLOAT_DATA" ;
271 getpt = False ;
272 isWeather = False ;
273 isSysCal = False ;
274 cycleNo = 0 ;
275 numSysCalRow = 0 ;
276 header = scantable.getHeader() ;
277 fluxUnit( header.fluxunit ) ;
278
279 // MS subtables
280 const TableRecord &hdr = table.keywordSet();
281 obstab = hdr.asTable( "OBSERVATION" ) ;
282 spwtab = hdr.asTable( "SPECTRAL_WINDOW" ) ;
283 statetab = hdr.asTable( "STATE" ) ;
284 ddtab = hdr.asTable( "DATA_DESCRIPTION" ) ;
285 poltab = hdr.asTable( "POLARIZATION" ) ;
286 fieldtab = hdr.asTable( "FIELD" ) ;
287 anttab = hdr.asTable( "ANTENNA" ) ;
288 if ( hdr.isDefined( "SYSCAL" ) )
289 sctab = hdr.asTable( "SYSCAL" ) ;
290 if ( hdr.isDefined( "SOURCE" ) )
291 srctab = hdr.asTable( "SOURCE" ) ;
292
293 // attach to columns
294 // MS MAIN
295 intervalCol.attach( table, "INTERVAL" ) ;
296 flagRowCol.attach( table, "FLAG_ROW" ) ;
297 flagCol.attach( table, "FLAG" ) ;
298 if ( dataColumnName.compare( "DATA" ) == 0 )
299 dataCol.attach( table, dataColumnName ) ;
300 else
301 floatDataCol.attach( table, dataColumnName ) ;
302
303 // set dummy epoch
304 mf.set( currentTime ) ;
305
306 // initialize dirType
307 dirType = MDirection::N_Types ;
308
309 //
310 // add rows to scantable
311 //
312 // number of polarization is up to 4
313 uInt addrow = table.nrow() * maxNumPol() ;
314 scantable.table().addRow( addrow ) ;
315
316 // attach to columns
317 // Scantable MAIN
318 TableRecord &r = tablerow.record() ;
319 timeRF.attachToRecord( r, "TIME" ) ;
320 intervalRF.attachToRecord( r, "INTERVAL" ) ;
321 directionRF.attachToRecord( r, "DIRECTION" ) ;
322 azimuthRF.attachToRecord( r, "AZIMUTH" ) ;
323 elevationRF.attachToRecord( r, "ELEVATION" ) ;
324 scanRateRF.attachToRecord( r, "SCANRATE" ) ;
325 weatherIdRF.attachToRecord( r, "WEATHER_ID" ) ;
326 cycleNoRF.attachToRecord( r, "CYCLENO" ) ;
327 flagRowRF.attachToRecord( r, "FLAGROW" ) ;
328 polNoRF.attachToRecord( r, "POLNO" ) ;
329 tcalIdRF.attachToRecord( r, "TCAL_ID" ) ;
330 spectraRF.attachToRecord( r, "SPECTRA" ) ;
331 flagtraRF.attachToRecord( r, "FLAGTRA" ) ;
332 tsysRF.attachToRecord( r, "TSYS" ) ;
333 beamNoRF.attachToRecord( r, "BEAMNO" ) ;
334 ifNoRF.attachToRecord( r, "IFNO" ) ;
335 freqIdRF.attachToRecord( r, "FREQ_ID" ) ;
336 moleculeIdRF.attachToRecord( r, "MOLECULE_ID" ) ;
337 sourceNameRF.attachToRecord( r, "SRCNAME" ) ;
338 sourceProperMotionRF.attachToRecord( r, "SRCPROPERMOTION" ) ;
339 sourceDirectionRF.attachToRecord( r, "SRCDIRECTION" ) ;
340 sourceVelocityRF.attachToRecord( r, "SRCVELOCITY" ) ;
341 focusIdRF.attachToRecord( r, "FOCUS_ID" ) ;
342 fieldNameRF.attachToRecord( r, "FIELDNAME" ) ;
343 sourceTypeRF.attachToRecord( r, "SRCTYPE" ) ;
344 scanNoRF.attachToRecord( r, "SCANNO" ) ;
345
346 // put values
347 RecordFieldPtr<Int> refBeamNoRF( r, "REFBEAMNO" ) ;
348 *refBeamNoRF = -1 ;
349 RecordFieldPtr<Int> fitIdRF( r, "FIT_ID" ) ;
350 *fitIdRF = -1 ;
351 RecordFieldPtr<Float> opacityRF( r, "OPACITY" ) ;
352 *opacityRF = 0.0 ;
353 }
354
355 virtual void enterObservationId(const uInt recordNo, Int columnValue) {
356 //printf("%u: ObservationId: %d\n", recordNo, columnValue);
357 // update header
358 if ( header.observer.empty() )
359 getScalar( String("OBSERVER"), (uInt)columnValue, obstab, header.observer ) ;
360 if ( header.project.empty() )
361 getScalar( "PROJECT", (uInt)columnValue, obstab, header.project ) ;
362 if ( header.utc == 0.0 ) {
363 Vector<MEpoch> amp ;
364 getArrayMeas( "TIME_RANGE", (uInt)columnValue, obstab, amp ) ;
365 header.utc = amp[0].get( "d" ).getValue() ;
366 }
367 if ( header.antennaname.empty() )
368 getScalar( "TELESCOPE_NAME", (uInt)columnValue, obstab, header.antennaname ) ;
369 }
370 virtual void leaveObservationId(const uInt recordNo, Int columnValue) {
371 // update header
372 header.nbeam = max( header.nbeam, (Int)nbeam ) ;
373
374 nbeam = 0 ;
375 feedEntry = -1 ;
376 }
377 virtual void enterFeedId(const uInt recordNo, Int columnValue) {
378 //printf("%u: FeedId: %d\n", recordNo, columnValue);
379
380 // update feed entry
381 if ( allNE( feedEntry, columnValue ) ) {
382 feedEntry[nbeam] = columnValue ;
383 nbeam++ ;
384 }
385
386 // put values
387 *beamNoRF = (uInt)columnValue ;
388 *focusIdRF = (uInt)0 ;
389 }
390 virtual void leaveFeedId(const uInt recordNo, Int columnValue) {
391 Int nelem = (Int)feedEntry.nelements() ;
392 if ( nbeam > nelem ) {
393 feedEntry.resize( nelem+64, True ) ;
394 Slicer slice( IPosition( 1, nelem ), IPosition( 1, feedEntry.nelements()-1 ) ) ;
395 feedEntry( slice ) = -1 ;
396 }
397 }
398 virtual void enterFieldId(const uInt recordNo, Int columnValue) {
399 //printf("%u: FieldId: %d\n", recordNo, columnValue);
400 // update sourceId and fieldName
401 getScalar( "SOURCE_ID", (uInt)columnValue, fieldtab, sourceId ) ;
402 String fieldName ;
403 getScalar( "NAME", (uInt)columnValue, fieldtab, fieldName ) ;
404 fieldName += "__" + String::toString( columnValue ) ;
405
406 // put values
407 *fieldNameRF = fieldName ;
408 }
409 virtual void leaveFieldId(const uInt recordNo, Int columnValue) {
410 sourceId = -1 ;
411 }
412 virtual void enterDataDescId(const uInt recordNo, Int columnValue) {
413 //printf("%u: DataDescId: %d\n", recordNo, columnValue);
414 // update polarization and spectral window ids
415 getScalar( "POLARIZATION_ID", (uInt)columnValue, ddtab, polId ) ;
416 getScalar( "SPECTRAL_WINDOW_ID", (uInt)columnValue, ddtab, spwId ) ;
417
418 // polarization setup
419 getScalar( "NUM_CORR", (uInt)polId, poltab, npol ) ;
420 Vector<Int> corrtype ;
421 getArray( "CORR_TYPE", (uInt)polId, poltab, corrtype ) ;
422 polnos = getPolNos( corrtype ) ;
423
424 // process SOURCE table
425 String sourceName ;
426 Vector<Double> sourcePM, restFreqs, sysVels ;
427 Vector<String> transition ;
428 processSource( sourceId, spwId, sourceName, sourceDir, sourcePM,
429 restFreqs, transition, sysVels ) ;
430
431 // spectral setup
432 uInt freqId ;
433 Double reffreq, bandwidth ;
434 String freqref ;
435 getScalar( "NUM_CHAN", (uInt)spwId, spwtab, nchan ) ;
436 Bool iswvr = (Bool)(nchan == 4) ;
437 map<Int,uInt>::iterator iter = ifmap.find( spwId ) ;
438 if ( iter == ifmap.end() ) {
439 MEpoch me ;
440 getScalarMeas( "TIME", recordNo, table, me ) ;
441 spectralSetup( spwId, me, antpos, sourceDir,
442 freqId, nchan,
443 freqref, reffreq, bandwidth ) ;
444 ifmap.insert( pair<Int,uInt>(spwId,freqId) ) ;
445 }
446 else {
447 freqId = iter->second ;
448 }
449 sp.resize( npol, nchan ) ;
450 fl.resize( npol, nchan ) ;
451
452
453 // molecular setup
454 STMolecules mtab = scantable.molecules() ;
455 uInt molId = mtab.addEntry( restFreqs, transition, transition ) ;
456
457 // process SYSCAL table
458 if ( isSysCal )
459 processSysCal( spwId ) ;
460
461 // update header
462 if ( !iswvr ) {
463 header.nchan = max( header.nchan, nchan ) ;
464 header.bandwidth = max( header.bandwidth, bandwidth ) ;
465 if ( header.reffreq == -1.0 )
466 header.reffreq = reffreq ;
467 header.npol = max( header.npol, npol ) ;
468 if ( header.poltype.empty() )
469 header.poltype = getPolType( corrtype[0] ) ;
470 if ( header.freqref.empty() )
471 header.freqref = freqref ;
472 }
473
474 // put values
475 *ifNoRF = (uInt)spwId ;
476 *freqIdRF = freqId ;
477 *moleculeIdRF = molId ;
478 *sourceNameRF = sourceName ;
479 sourceProperMotionRF.define( sourcePM ) ;
480 Vector<Double> srcD = sourceDir.getAngle().getValue( "rad" ) ;
481 sourceDirectionRF.define( srcD ) ;
482 if ( !sysVels.empty() )
483 *sourceVelocityRF = sysVels[0] ;
484 else {
485 *sourceVelocityRF = (Double)0.0 ;
486 }
487 }
488 virtual void leaveDataDescId(const uInt recordNo, Int columnValue) {
489 npol = 0 ;
490 nchan = 0 ;
491 numSysCalRow = 0 ;
492 }
493 virtual void enterScanNo(const uInt recordNo, Int columnValue) {
494 //printf("%u: ScanNo: %d\n", recordNo, columnValue);
495 // put value
496 // scan number is 1-based in MS while 0-based in Scantable
497 *scanNoRF = (uInt)columnValue - 1 ;
498 }
499 virtual void leaveScanNo(const uInt recordNo, Int columnValue) {
500 cycleNo = 0 ;
501 }
502 virtual void enterStateId(const uInt recordNo, Int columnValue) {
503 //printf("%u: StateId: %d\n", recordNo, columnValue);
504 // SRCTYPE
505 Int srcType = getSrcType( columnValue ) ;
506
507 // update header
508 if ( header.obstype.empty() )
509 getScalar( "OBS_MODE", (uInt)columnValue, statetab, header.obstype ) ;
510
511 // put value
512 *sourceTypeRF = srcType ;
513 }
514 virtual void leaveStateId(const uInt recordNo, Int columnValue) { }
515 virtual void enterTime(const uInt recordNo, Double columnValue) {
516 //printf("%u: Time: %f\n", recordNo, columnValue);
517 currentTime = MEpoch( Quantity( columnValue, "s" ), MEpoch::UTC ) ;
518
519 // DIRECTION, AZEL, and SCANRATE
520 Vector<Double> direction, azel ;
521 Vector<Double> scanrate( 2, 0.0 ) ;
522 if ( getpt )
523 getDirection( direction, azel, scanrate ) ;
524 else
525 getSourceDirection( direction, azel, scanrate ) ;
526
527 // INTERVAL
528 Double interval = intervalCol.asdouble( recordNo ) ;
529
530 // WEATHER_ID
531 uInt wid = 0 ;
532 if ( isWeather )
533 wid = getWeatherId() ;
534
535 // put value
536 Double t = currentTime.get( "d" ).getValue() ;
537 *timeRF = t ;
538 *intervalRF = interval ;
539 directionRF.define( direction ) ;
540 *azimuthRF = (Float)azel[0] ;
541 *elevationRF = (Float)azel[1] ;
542 scanRateRF.define( scanrate ) ;
543 *weatherIdRF = wid ;
544 }
545 virtual void leaveTime(const uInt recordNo, Double columnValue) { }
546 virtual Bool visitRecord(const uInt recordNo,
547 const Int observationId,
548 const Int feedId,
549 const Int fieldId,
550 const Int dataDescId,
551 const Int scanNo,
552 const Int stateId,
553 const Double time)
554 {
555 //printf("%u: %d, %d, %d, %d, %d, %d, %f\n", recordNo,
556 //observationId, feedId, fieldId, dataDescId, scanNo, stateId, time);
557
558 // SPECTRA and FLAGTRA
559 //Matrix<Float> sp;
560 //Matrix<uChar> fl;
561 spectraAndFlagtra( recordNo, sp, fl ) ;
562
563 // FLAGROW
564 Bool flr = flagRowCol.asBool( recordNo ) ;
565
566 // TSYS
567 Matrix<Float> tsys ;
568 uInt scIdx = getSysCalIndex() ;
569 if ( numSysCalRow > 0 ) {
570 tsys = sysCalTsysCol( syscalRow[scIdx] ) ;
571 }
572 else {
573 tsys.resize( npol, 1 ) ;
574 tsys = 1.0 ;
575 }
576
577 // TCAL_ID
578 Block<uInt> tcalids( npol, 0 ) ;
579 if ( numSysCalRow > 0 ) {
580 tcalids = getTcalId( syscalTime[scIdx] ) ;
581 }
582
583 // put value
584 *cycleNoRF = cycleNo ;
585 *flagRowRF = (uInt)flr ;
586
587 // for each polarization component
588 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
589 // put value depending on polarization component
590 *polNoRF = polnos[ipol] ;
591 *tcalIdRF = tcalids[ipol] ;
592 spectraRF.define( sp.row( ipol ) ) ;
593 flagtraRF.define( fl.row( ipol ) ) ;
594 tsysRF.define( tsys.row( ipol ) ) ;
595
596 // commit row
597 tablerow.put( rowidx ) ;
598 rowidx++ ;
599 }
600
601 // increment CYCLENO
602 cycleNo++ ;
603
604 return True ;
605 }
606 virtual void finish()
607 {
608 BaseMSFillerVisitor::finish();
609 //printf("Total: %u\n", count);
610 // remove redundant rows
611 //cout << "filled " << rowidx << " rows out of " << scantable.nrow() << " rows" << endl ;
612 if ( scantable.nrow() > rowidx ) {
613 uInt numRemove = scantable.nrow() - rowidx ;
614 //cout << "numRemove = " << numRemove << endl ;
615 Vector<uInt> rows( numRemove ) ;
616 indgen( rows, rowidx ) ;
617 scantable.table().removeRow( rows ) ;
618 }
619
620 // antenna name and station name
621 String antennaName ;
622 getScalar( "NAME", (uInt)antennaId, anttab, antennaName ) ;
623 String stationName ;
624 getScalar( "STATION", (uInt)antennaId, anttab, stationName ) ;
625
626 // update header
627 header.nif = ifmap.size() ;
628 header.antennaposition = antpos.get( "m" ).getValue() ;
629 if ( header.antennaname.empty() || header.antennaname == antennaName )
630 header.antennaname = antennaName ;
631 else
632 header.antennaname += "//" + antennaName ;
633 if ( !stationName.empty() && stationName != antennaName )
634 header.antennaname += "@" + stationName ;
635 if ( header.fluxunit.empty() || header.fluxunit == "CNTS" )
636 header.fluxunit = "K" ;
637 header.epoch = "UTC" ;
638 header.equinox = 2000.0 ;
639 if (header.freqref == "TOPO") {
640 header.freqref = "TOPOCENT";
641 } else if (header.freqref == "GEO") {
642 header.freqref = "GEOCENTR";
643 } else if (header.freqref == "BARY") {
644 header.freqref = "BARYCENT";
645 } else if (header.freqref == "GALACTO") {
646 header.freqref = "GALACTOC";
647 } else if (header.freqref == "LGROUP") {
648 header.freqref = "LOCALGRP";
649 } else if (header.freqref == "CMB") {
650 header.freqref = "CMBDIPOL";
651 } else if (header.freqref == "REST") {
652 header.freqref = "SOURCE";
653 }
654 scantable.setHeader( header ) ;
655 }
656 void setAntenna( Int id )
657 {
658 antennaId = id ;
659
660 Vector< Quantum<Double> > pos ;
661 getArrayQuant( "POSITION", (uInt)antennaId, anttab, pos ) ;
662 antpos = MPosition( MVPosition( pos ), MPosition::ITRF ) ;
663 mf.set( antpos ) ;
664 }
665 void setPointingTable( const Table &tab, String columnToUse="DIRECTION" )
666 {
667 // input POINTING table must be
668 // 1) selected by antenna
669 // 2) sorted by TIME
670 ROScalarColumn<Double> tcol( tab, "TIME" ) ;
671 ROArrayColumn<Double> dcol( tab, columnToUse ) ;
672 tcol.getColumn( pointingTime ) ;
673 dcol.getColumn( pointingDirection ) ;
674 const TableRecord &rec = dcol.keywordSet() ;
675 String pointingRef = rec.asRecord( "MEASINFO" ).asString( "Ref" ) ;
676 MDirection::getType( dirType, pointingRef ) ;
677 getpt = True ;
678 }
679 void setWeatherTime( const Vector<Double> &t, const Vector<Double> &it )
680 {
681 isWeather = True ;
682 weatherTime = t ;
683 weatherInterval = it ;
684 }
685 void setSysCalRecord( const Record &r )
686 //void setSysCalRecord( const map< String,Vector<uInt> > &r )
687 {
688 isSysCal = True ;
689 syscalRecord = r ;
690
691 const TableDesc &desc = sctab.tableDesc() ;
692 uInt nrow = sctab.nrow() ;
693 syscalRow.resize( nrow ) ;
694 syscalTime.resize( nrow ) ;
695 syscalInterval.resize( nrow ) ;
696 String tsysCol = "NONE" ;
697 Vector<String> tsysCols = stringToVector( "TSYS_SPECTRUM,TSYS" ) ;
698 for ( uInt i = 0 ; i < tsysCols.nelements() ; i++ ) {
699 if ( tsysCol == "NONE" && desc.isColumn( tsysCols[i] ) )
700 tsysCol = tsysCols[i] ;
701 }
702 sysCalTsysCol.attach( sctab, tsysCol ) ;
703 }
704 STHeader getHeader() { return header ; }
705 uInt getNumBeam() { return nbeam ; }
706 uInt getFilledRowNum() { return rowidx ; }
707private:
708 void fluxUnit( String &u )
709 {
710 ROTableColumn col( table, dataColumnName ) ;
711 const TableRecord &rec = col.keywordSet() ;
712 if ( rec.isDefined( "UNIT" ) )
713 u = rec.asString( "UNIT" ) ;
714 else if ( rec.isDefined( "QuantumUnits" ) )
715 u = rec.asString( "QuantumUnits" ) ;
716 if ( u.empty() )
717 u = "K" ;
718 }
719 void processSource( Int sourceId, Int spwId,
720 String &name, MDirection &dir, Vector<Double> &pm,
721 Vector<Double> &rf, Vector<String> &trans, Vector<Double> &vel )
722 {
723 // find row
724 uInt nrow = srctab.nrow() ;
725 Int idx = -1 ;
726 ROTableRow row( srctab ) ;
727 for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
728 const TableRecord &r = row.get( irow ) ;
729 if ( r.asInt( "SOURCE_ID" ) == sourceId ) {
730 Int tmpSpwId = r.asInt( "SPECTRAL_WINDOW_ID" ) ;
731 if ( tmpSpwId == spwId || tmpSpwId == -1 ) {
732 idx = (Int)irow ;
733 break ;
734 }
735 }
736 }
737
738 // fill
739 Int numLines = 0 ;
740 if ( idx != -1 ) {
741 const TableRecord &r = row.get( idx ) ;
742 name = r.asString( "NAME" ) ;
743 getScalarMeas( "DIRECTION", idx, srctab, dir ) ;
744 pm = r.toArrayDouble( "PROPER_MOTION" ) ;
745 numLines = r.asInt( "NUM_LINES" ) ;
746 }
747 else {
748 name = "" ;
749 pm = Vector<Double>( 2, 0.0 ) ;
750 dir = MDirection( Quantum<Double>(0.0,Unit("rad")), Quantum<Double>(0.0,Unit("rad")) ) ;
751 }
752 if ( !getpt ) {
753 String ref = dir.getRefString() ;
754 MDirection::getType( dirType, ref ) ;
755 }
756
757 rf.resize( numLines ) ;
758 trans.resize( numLines ) ;
759 vel.resize( numLines ) ;
760 if ( numLines > 0 ) {
761 Block<Bool> isDefined = row.getDefined() ;
762 Vector<String> colNames = row.columnNames() ;
763 Vector<Int> indexes( 3, -1 ) ;
764 Vector<String> cols = stringToVector( "REST_FREQUENCY,TRANSITION,SYSVEL" ) ;
765 for ( uInt icol = 0 ; icol < colNames.nelements() ; icol++ ) {
766 if ( anyEQ( indexes, -1 ) ) {
767 for ( uInt jcol = 0 ; jcol < cols.nelements() ; jcol++ ) {
768 if ( colNames[icol] == cols[jcol] )
769 indexes[jcol] = icol ;
770 }
771 }
772 }
773 if ( indexes[0] != -1 && isDefined[indexes[0]] == True ) {
774 Vector< Quantum<Double> > qrf ;
775 getArrayQuant( "REST_FREQUENCY", idx, srctab, qrf ) ;
776 for ( int i = 0 ; i < numLines ; i++ )
777 rf[i] = qrf[i].getValue( "Hz" ) ;
778 }
779 if ( indexes[1] != -1 && isDefined[indexes[1]] == True ) {
780 getArray( "TRANSITION", idx, srctab, trans ) ;
781 }
782 if ( indexes[2] != -1 && isDefined[indexes[2]] == True ) {
783 Vector< Quantum<Double> > qsv ;
784 getArrayQuant( "SYSVEL", idx, srctab, qsv ) ;
785 for ( int i = 0 ; i < numLines ; i++ )
786 vel[i] = qsv[i].getValue( "m/s" ) ;
787 }
788 }
789 }
790 void spectralSetup( Int &spwId, MEpoch &me, MPosition &mp, MDirection &md,
791 uInt &freqId, Int &nchan,
792 String &freqref, Double &reffreq, Double &bandwidth )
793 {
794 // fill
795 Int measFreqRef ;
796 getScalar( "MEAS_FREQ_REF", spwId, spwtab, measFreqRef ) ;
797 MFrequency::Types freqRef = MFrequency::castType( measFreqRef ) ;
798 //freqref = MFrequency::showType( freqRef ) ;
799 freqref = "LSRK" ;
800 Quantum<Double> q ;
801 getScalarQuant( "TOTAL_BANDWIDTH", spwId, spwtab, q ) ;
802 bandwidth = q.getValue( "Hz" ) ;
803 getScalarQuant( "REF_FREQUENCY", spwId, spwtab, q ) ;
804 reffreq = q.getValue( "Hz" ) ;
805 Double refpix = 0.5 * ( (Double)nchan-1.0 ) ;
806 Int refchan = ( nchan - 1 ) / 2 ;
807 Bool even = (Bool)( nchan % 2 == 0 ) ;
808 Vector< Quantum<Double> > qa ;
809 getArrayQuant( "CHAN_WIDTH", spwId, spwtab, qa ) ;
810 Double increment = qa[refchan].getValue( "Hz" ) ;
811 getArrayQuant( "CHAN_FREQ", spwId, spwtab, qa ) ;
812 if ( nchan == 1 ) {
813 Int netSideband ;
814 getScalar( "NET_SIDEBAND", spwId, spwtab, netSideband ) ;
815 if ( netSideband == 1 ) increment *= -1.0 ;
816 }
817 else {
818 if ( qa[0].getValue( "Hz" ) > qa[1].getValue( "Hz" ) )
819 increment *= -1.0 ;
820 }
821 Double refval = qa[refchan].getValue( "Hz" ) ;
822 if ( even )
823 refval = 0.5 * ( refval + qa[refchan+1].getValue( "Hz" ) ) ;
824 if ( freqRef != MFrequency::LSRK ) {
825 MeasFrame mframe( me, mp, md ) ;
826 MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mframe ) ) ;
827 refval = tolsr( Quantum<Double>( refval, "Hz" ) ).get( "Hz" ).getValue() ;
828 }
829
830 // add new row to FREQUENCIES
831 Table ftab = scantable.frequencies().table() ;
832 freqId = ftab.nrow() ;
833 ftab.addRow() ;
834 TableRow row( ftab ) ;
835 TableRecord &r = row.record() ;
836 RecordFieldPtr<uInt> idRF( r, "ID" ) ;
837 *idRF = freqId ;
838 RecordFieldPtr<Double> refpixRF( r, "REFPIX" ) ;
839 RecordFieldPtr<Double> refvalRF( r, "REFVAL" ) ;
840 RecordFieldPtr<Double> incrRF( r, "INCREMENT" ) ;
841 *refpixRF = refpix ;
842 *refvalRF = refval ;
843 *incrRF = increment ;
844 row.put( freqId ) ;
845 }
846 void spectraAndFlagtra( uInt recordNo, Matrix<Float> &sp, Matrix<uChar> &fl )
847 {
848 Matrix<Bool> b = flagCol( recordNo ) ;
849 if ( dataColumnName.compare( "FLOAT_DATA" ) == 0 ) {
850 sp = floatDataCol( recordNo ) ;
851 convertArray( fl, b ) ;
852 }
853 else {
854 Bool notyet = True ;
855 Matrix<Complex> c = dataCol( recordNo ) ;
856 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
857 if ( ( header.poltype == "linear" || header.poltype == "circular" )
858 && ( polnos[ipol] == 2 || polnos[ipol] == 3 ) ) {
859 if ( notyet ) {
860 Vector<Float> tmp = ComplexToReal( c.row( ipol ) ) ;
861 IPosition start( 1, 0 ) ;
862 IPosition end( 1, 2*nchan-1 ) ;
863 IPosition inc( 1, 2 ) ;
864 if ( polnos[ipol] == 2 ) {
865 sp.row( ipol ) = tmp( start, end, inc ) ;
866 Vector<Bool> br = b.row( ipol ) ;
867 Vector<uChar> flr = fl.row( ipol ) ;
868 convertArray( flr, br ) ;
869 start = IPosition( 1, 1 ) ;
870 Int jpol = ipol+1 ;
871 while( polnos[jpol] != 3 && jpol < npol )
872 jpol++ ;
873 sp.row( jpol ) = tmp( start, end, inc ) ;
874 flr.reference( fl.row( jpol ) ) ;
875 convertArray( flr, br ) ;
876 }
877 else if ( polnos[ipol] == 3 ) {
878 sp.row( ipol ) = sp.row( ipol ) * (Float)(-1.0) ;
879 Int jpol = ipol+1 ;
880 while( polnos[jpol] != 2 && jpol < npol )
881 jpol++ ;
882 Vector<Bool> br = b.row( ipol ) ;
883 Vector<uChar> flr = fl.row( jpol ) ;
884 sp.row( jpol ) = tmp( start, end, inc ) ;
885 convertArray( flr, br ) ;
886 start = IPosition( 1, 1 ) ;
887 sp.row( ipol ) = tmp( start, end, inc ) * (Float)(-1.0) ;
888 flr.reference( fl.row( ipol ) ) ;
889 convertArray( flr, br ) ;
890 }
891 notyet = False ;
892 }
893 }
894 else {
895 Vector<Float> tmp = ComplexToReal( c.row( ipol ) ) ;
896 IPosition start( 1, 0 ) ;
897 IPosition end( 1, 2*nchan-1 ) ;
898 IPosition inc( 1, 2 ) ;
899 sp.row( ipol ) = tmp( start, end, inc ) ;
900 Vector<Bool> br = b.row( ipol ) ;
901 Vector<uChar> flr = fl.row( ipol ) ;
902 convertArray( flr, br ) ;
903 }
904 }
905 }
906 }
907 uInt binarySearch( Vector<Double> &timeList, Double target )
908 {
909 Int low = 0 ;
910 Int high = timeList.nelements() ;
911 uInt idx = 0 ;
912
913 while ( low <= high ) {
914 idx = (Int)( 0.5 * ( low + high ) ) ;
915 Double t = timeList[idx] ;
916 if ( t < target )
917 low = idx + 1 ;
918 else if ( t > target )
919 high = idx - 1 ;
920 else {
921 return idx ;
922 }
923 }
924
925 idx = max( 0, min( low, high ) ) ;
926 return idx ;
927 }
928 void getDirection( Vector<Double> &dir, Vector<Double> &azel, Vector<Double> &srate )
929 {
930 // @todo At the moment, do binary search every time
931 // if this is bottleneck, frequency of binary search must be reduced
932 Double t = currentTime.get( "s" ).getValue() ;
933 uInt idx = min( binarySearch( pointingTime, t ), pointingTime.nelements()-1 ) ;
934 Matrix<Double> d ;
935 if ( pointingTime[idx] == t )
936 d = pointingDirection.xyPlane( idx ) ;
937 else if ( pointingTime[idx] < t ) {
938 if ( idx == pointingTime.nelements()-1 )
939 d = pointingDirection.xyPlane( idx ) ;
940 else
941 d = interp( pointingTime[idx], pointingTime[idx+1], t,
942 pointingDirection.xyPlane( idx ), pointingDirection.xyPlane( idx+1 ) ) ;
943 }
944 else {
945 if ( idx == 0 )
946 d = pointingDirection.xyPlane( idx ) ;
947 else
948 d = interp( pointingTime[idx-1], pointingTime[idx], t,
949 pointingDirection.xyPlane( idx-1 ), pointingDirection.xyPlane( idx ) ) ;
950 }
951 mf.resetEpoch( currentTime ) ;
952 Quantum< Vector<Double> > tmp( d.column( 0 ), Unit( "rad" ) ) ;
953 if ( dirType != MDirection::J2000 ) {
954 MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
955 dir = toj2000( tmp ).getAngle( "rad" ).getValue() ;
956 }
957 else {
958 dir = d.column( 0 ) ;
959 }
960 if ( dirType != MDirection::AZELGEO ) {
961 MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZELGEO, mf ) ) ;
962 //MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
963 azel = toazel( tmp ).getAngle( "rad" ).getValue() ;
964 }
965 else {
966 azel = d.column( 0 ) ;
967 }
968 if ( d.ncolumn() > 1 )
969 srate = d.column( 1 ) ;
970 }
971 void getSourceDirection( Vector<Double> &dir, Vector<Double> &azel, Vector<Double> &srate )
972 {
973 dir = sourceDir.getAngle( "rad" ).getValue() ;
974 mf.resetEpoch( currentTime ) ;
975 MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZELGEO, mf ) ) ;
976 azel = toazel( Quantum< Vector<Double> >( dir, Unit("rad") ) ).getAngle( "rad" ).getValue() ;
977 if ( dirType != MDirection::J2000 ) {
978 MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
979 dir = toj2000( Quantum< Vector<Double> >( dir, Unit("rad") ) ).getAngle( "rad" ).getValue() ;
980 }
981 }
982 String detectSeparator( String &s )
983 {
984 String tmp = s.substr( 0, s.find_first_of( "," ) ) ;
985 Char *separators[] = { ":", "#", ".", "_" } ;
986 uInt nsep = 4 ;
987 for ( uInt i = 0 ; i < nsep ; i++ ) {
988 if ( tmp.find( separators[i] ) != String::npos )
989 return separators[i] ;
990 }
991 return "" ;
992 }
993 Int getSrcType( Int stateId )
994 {
995 // get values
996 Bool sig ;
997 getScalar( "SIG", stateId, statetab, sig ) ;
998 Bool ref ;
999 getScalar( "REF", stateId, statetab, ref ) ;
1000 Double cal ;
1001 getScalar( "CAL", stateId, statetab, cal ) ;
1002 String obsmode ;
1003 getScalar( "OBS_MODE", stateId, statetab, obsmode ) ;
1004 String sep = detectSeparator( obsmode ) ;
1005
1006 Int srcType = SrcType::NOTYPE ;
1007 if ( sep == ":" )
1008 srcTypeGBT( srcType, sep, obsmode, sig, ref, cal ) ;
1009 else if ( sep == "." || sep == "#" )
1010 srcTypeALMA( srcType, sep, obsmode ) ;
1011 else if ( sep == "_" )
1012 srcTypeOldALMA( srcType, sep, obsmode, sig, ref ) ;
1013 else
1014 srcTypeDefault( srcType, sig, ref ) ;
1015
1016 return srcType ;
1017 }
1018 void srcTypeDefault( Int &st, Bool &sig, Bool &ref )
1019 {
1020 if ( sig ) st = SrcType::SIG ;
1021 else if ( ref ) st = SrcType::REF ;
1022 }
1023 void srcTypeGBT( Int &st, String &sep, String &mode, Bool &sig, Bool &ref, Double &cal )
1024 {
1025 Int epos = mode.find_first_of( sep ) ;
1026 Int nextpos = mode.find_first_of( sep, epos+1 ) ;
1027 String m1 = mode.substr( 0, epos ) ;
1028 String m2 = mode.substr( epos+1, nextpos-epos-1 ) ;
1029 if ( m1 == "Nod" ) {
1030 st = SrcType::NOD ;
1031 }
1032 else if ( m1 == "OffOn" ) {
1033 if ( m2 == "PSWITCHON" ) st = SrcType::PSON ;
1034 if ( m2 == "PSWITCHOFF" ) st = SrcType::PSOFF ;
1035 }
1036 else {
1037 if ( m2 == "FSWITCH" ) {
1038 if ( sig ) st = SrcType::FSON ;
1039 else if ( ref ) st = SrcType::FSOFF ;
1040 }
1041 }
1042 if ( cal > 0.0 ) {
1043 if ( st == SrcType::NOD )
1044 st = SrcType::NODCAL ;
1045 else if ( st == SrcType::PSON )
1046 st = SrcType::PONCAL ;
1047 else if ( st == SrcType::PSOFF )
1048 st = SrcType::POFFCAL ;
1049 else if ( st == SrcType::FSON )
1050 st = SrcType::FONCAL ;
1051 else if ( st == SrcType::FSOFF )
1052 st = SrcType::FOFFCAL ;
1053 else
1054 st = SrcType::CAL ;
1055 }
1056 }
1057 void srcTypeALMA( Int &st, String &sep, String &mode )
1058 {
1059 Int epos = mode.find_first_of( "," ) ;
1060 String first = mode.substr( 0, epos ) ;
1061 epos = first.find_first_of( sep ) ;
1062 Int nextpos = first.find_first_of( sep, epos+1 ) ;
1063 String m1 = first.substr( 0, epos ) ;
1064 String m2 = first.substr( epos+1, nextpos-epos-1 ) ;
1065 if ( m1.find( "CALIBRATE_" ) == 0 ) {
1066 if ( m2.find( "ON_SOURCE" ) == 0 )
1067 st = SrcType::PONCAL ;
1068 else if ( m2.find( "OFF_SOURCE" ) == 0 )
1069 st = SrcType::POFFCAL ;
1070 }
1071 else if ( m1.find( "OBSERVE_TARGET" ) == 0 ) {
1072 if ( m2.find( "ON_SOURCE" ) == 0 )
1073 st = SrcType::PSON ;
1074 else if ( m2.find( "OFF_SOURCE" ) == 0 )
1075 st = SrcType::PSOFF ;
1076 }
1077 }
1078 void srcTypeOldALMA( Int &st, String &sep, String &mode, Bool &sig, Bool &ref )
1079 {
1080 Int epos = mode.find_first_of( "," ) ;
1081 String first = mode.substr( 0, epos ) ;
1082 string substr[4] ;
1083 int numSubstr = split( first, substr, 4, sep ) ;
1084 String m1( substr[0] ) ;
1085 String m2( substr[2] ) ;
1086 if ( numSubstr == 4 ) {
1087 if ( m1.find( "CALIBRATE" ) == 0 ) {
1088 if ( m2.find( "ON" ) == 0 )
1089 st = SrcType::PONCAL ;
1090 else if ( m2.find( "OFF" ) == 0 )
1091 st = SrcType::POFFCAL ;
1092 }
1093 else if ( m1.find( "OBSERVE" ) == 0 ) {
1094 if ( m2.find( "ON" ) == 0 )
1095 st = SrcType::PSON ;
1096 else if ( m2.find( "OFF" ) == 0 )
1097 st = SrcType::PSOFF ;
1098 }
1099 }
1100 else {
1101 if ( sig ) st = SrcType::SIG ;
1102 else if ( ref ) st = SrcType::REF ;
1103 }
1104 }
1105 Block<uInt> getPolNos( Vector<Int> &corr )
1106 {
1107 Block<uInt> polnos( npol ) ;
1108 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
1109 if ( corr[ipol] == Stokes::I || corr[ipol] == Stokes::RR || corr[ipol] == Stokes::XX )
1110 polnos[ipol] = 0 ;
1111 else if ( corr[ipol] == Stokes::Q || corr[ipol] == Stokes::LL || corr[ipol] == Stokes::YY )
1112 polnos[ipol] = 1 ;
1113 else if ( corr[ipol] == Stokes::U || corr[ipol] == Stokes::RL || corr[ipol] == Stokes::XY )
1114 polnos[ipol] = 2 ;
1115 else if ( corr[ipol] == Stokes::V || corr[ipol] == Stokes::LR || corr[ipol] == Stokes::YX )
1116 polnos[ipol] = 3 ;
1117 }
1118 return polnos ;
1119 }
1120 String getPolType( Int &corr )
1121 {
1122 String poltype = "" ;
1123 if ( corr == Stokes::I || corr == Stokes::Q || corr == Stokes::U || corr == Stokes::V )
1124 poltype = "stokes" ;
1125 else if ( corr == Stokes::XX || corr == Stokes::YY || corr == Stokes::XY || corr == Stokes::YX )
1126 poltype = "linear" ;
1127 else if ( corr == Stokes::RR || corr == Stokes::LL || corr == Stokes::RL || corr == Stokes::LR )
1128 poltype = "circular" ;
1129 else if ( corr == Stokes::Plinear || corr == Stokes::Pangle )
1130 poltype = "linpol" ;
1131 return poltype ;
1132 }
1133 uInt getWeatherId()
1134 {
1135 // if only one row, return 0
1136 if ( weatherTime.nelements() == 1 )
1137 return 0 ;
1138
1139 // @todo At the moment, do binary search every time
1140 // if this is bottleneck, frequency of binary search must be reduced
1141 Double t = currentTime.get( "s" ).getValue() ;
1142 uInt idx = min( binarySearch( weatherTime, t ), weatherTime.nelements()-1 ) ;
1143 if ( weatherTime[idx] < t ) {
1144 if ( idx != weatherTime.nelements()-1 ) {
1145 if ( weatherTime[idx+1] - t < 0.5 * weatherInterval[idx+1] )
1146 idx++ ;
1147 }
1148 }
1149 else if ( weatherTime[idx] > t ) {
1150 if ( idx != 0 ) {
1151 if ( weatherTime[idx] - t > 0.5 * weatherInterval[idx] )
1152 idx-- ;
1153 }
1154 }
1155 return idx ;
1156 }
1157 void processSysCal( Int &spwId )
1158 {
1159 // get feedId from row
1160 Int feedId = (Int)tablerow.record().asuInt( "BEAMNO" ) ;
1161
1162 uInt nrow = sctab.nrow() ;
1163 ROScalarColumn<Int> col( sctab, "ANTENNA_ID" ) ;
1164 Vector<Int> aids = col.getColumn() ;
1165 col.attach( sctab, "FEED_ID" ) ;
1166 Vector<Int> fids = col.getColumn() ;
1167 col.attach( sctab, "SPECTRAL_WINDOW_ID" ) ;
1168 Vector<Int> sids = col.getColumn() ;
1169 ROScalarColumn<Double> timeCol( sctab, "TIME" ) ;
1170 ROScalarColumn<Double> intCol( sctab, "INTERVAL" ) ;
1171 for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1172 if ( aids[irow] == antennaId
1173 && fids[irow] == feedId
1174 && sids[irow] == spwId ) {
1175 syscalRow[numSysCalRow] = irow ;
1176 syscalTime[numSysCalRow] = timeCol( irow ) ;
1177 syscalInterval[numSysCalRow] = intCol( irow ) ;
1178 numSysCalRow++ ;
1179 }
1180 }
1181 }
1182 uInt getSysCalIndex()
1183 {
1184 // if only one row, return 0
1185 if ( numSysCalRow == 1 || !isSysCal )
1186 return 0 ;
1187
1188 // @todo At the moment, do binary search every time
1189 // if this is bottleneck, frequency of binary search must be reduced
1190 Double t = currentTime.get( "s" ).getValue() ;
1191 Vector<Double> tslice = syscalTime( Slice(0, numSysCalRow) ) ;
1192 uInt idx = min( binarySearch( tslice, t ), numSysCalRow-1 ) ;
1193 if ( syscalTime[idx] < t ) {
1194 if ( idx != numSysCalRow-1 ) {
1195 if ( syscalTime[idx+1] - t < 0.5 * syscalInterval[idx+1] )
1196 idx++ ;
1197 }
1198 }
1199 else if ( syscalTime[idx] > t ) {
1200 if ( idx != 0 ) {
1201 if ( syscalTime[idx] - t > 0.5 * syscalInterval[idx] )
1202 idx-- ;
1203 }
1204 }
1205 return idx ;
1206 }
1207 Block<uInt> getTcalId( Double &t )
1208 {
1209 // return 0 if no SysCal table
1210 if ( !isSysCal ) {
1211 return Block<uInt>( 4, 0 ) ;
1212 }
1213
1214 // get feedId from row
1215 Int feedId = (Int)tablerow.record().asuInt( "BEAMNO" ) ;
1216
1217 // key
1218 String key = keyTcal( feedId, spwId, t ) ;
1219
1220 // retrieve ids
1221 Vector<uInt> ids = syscalRecord.asArrayuInt( key ) ;
1222 //Vector<uInt> ids = syscalRecord[key] ;
1223 uInt np = ids[1] - ids[0] + 1 ;
1224 Block<uInt> tcalids( np ) ;
1225 if ( np > 0 ) {
1226 tcalids[0] = ids[0] ;
1227 if ( np > 1 ) {
1228 tcalids[1] = ids[1] ;
1229 for ( uInt ip = 2 ; ip < np ; ip++ )
1230 tcalids[ip] = ids[0] + ip - 1 ;
1231 }
1232 }
1233 return tcalids ;
1234 }
1235 uInt maxNumPol()
1236 {
1237 ROScalarColumn<Int> numCorrCol( poltab, "NUM_CORR" ) ;
1238 return max( numCorrCol.getColumn() ) ;
1239 }
1240
1241 Scantable &scantable;
1242 Int antennaId;
1243 uInt rowidx;
1244 String dataColumnName;
1245 TableRow tablerow;
1246 STHeader header;
1247 Vector<Int> feedEntry;
1248 uInt nbeam;
1249 Int npol;
1250 Int nchan;
1251 Int sourceId;
1252 Int polId;
1253 Int spwId;
1254 uInt cycleNo;
1255 MDirection sourceDir;
1256 MPosition antpos;
1257 MEpoch currentTime;
1258 map<Int,uInt> ifmap;
1259 Block<uInt> polnos;
1260 Bool getpt;
1261 Vector<Double> pointingTime;
1262 Cube<Double> pointingDirection;
1263 MDirection::Types dirType;
1264 Bool isWeather;
1265 Vector<Double> weatherTime;
1266 Vector<Double> weatherInterval;
1267 Bool isSysCal;
1268 Record syscalRecord;
1269 //map< String,Vector<uInt> > syscalRecord;
1270 uInt numSysCalRow ;
1271 Vector<uInt> syscalRow;
1272 Vector<Double> syscalTime;
1273 Vector<Double> syscalInterval;
1274 //String tsysCol;
1275 //String tcalCol;
1276
1277 // MS subtables
1278 Table obstab;
1279 Table sctab;
1280 Table spwtab;
1281 Table statetab;
1282 Table ddtab;
1283 Table poltab;
1284 Table fieldtab;
1285 Table anttab;
1286 Table srctab;
1287 Matrix<Float> sp;
1288 Matrix<uChar> fl;
1289 MeasFrame mf;
1290
1291 // MS MAIN columns
1292 ROTableColumn intervalCol;
1293 ROTableColumn flagRowCol;
1294 ROArrayColumn<Float> floatDataCol;
1295 ROArrayColumn<Complex> dataCol;
1296 ROArrayColumn<Bool> flagCol;
1297
1298 // MS SYSCAL columns
1299 ROArrayColumn<Float> sysCalTsysCol;
1300
1301 // Scantable MAIN columns
1302 RecordFieldPtr<Double> timeRF,intervalRF,sourceVelocityRF;
1303 RecordFieldPtr< Vector<Double> > directionRF,scanRateRF,
1304 sourceProperMotionRF,sourceDirectionRF;
1305 RecordFieldPtr<Float> azimuthRF,elevationRF;
1306 RecordFieldPtr<uInt> weatherIdRF,cycleNoRF,flagRowRF,polNoRF,tcalIdRF,
1307 ifNoRF,freqIdRF,moleculeIdRF,beamNoRF,focusIdRF,scanNoRF;
1308 RecordFieldPtr< Vector<Float> > spectraRF,tsysRF;
1309 RecordFieldPtr< Vector<uChar> > flagtraRF;
1310 RecordFieldPtr<String> sourceNameRF,fieldNameRF;
1311 RecordFieldPtr<Int> sourceTypeRF;
1312};
1313
1314class BaseTcalVisitor: public TableVisitor {
1315 uInt lastRecordNo ;
1316 Int lastAntennaId ;
1317 Int lastFeedId ;
1318 Int lastSpwId ;
1319 Double lastTime ;
1320protected:
1321 const Table &table;
1322 uInt count;
1323public:
1324 BaseTcalVisitor(const Table &table)
1325 : table(table)
1326 {
1327 count = 0;
1328 }
1329
1330 virtual void enterAntennaId(const uInt recordNo, Int columnValue) { }
1331 virtual void leaveAntennaId(const uInt recordNo, Int columnValue) { }
1332 virtual void enterFeedId(const uInt recordNo, Int columnValue) { }
1333 virtual void leaveFeedId(const uInt recordNo, Int columnValue) { }
1334 virtual void enterSpwId(const uInt recordNo, Int columnValue) { }
1335 virtual void leaveSpwId(const uInt recordNo, Int columnValue) { }
1336 virtual void enterTime(const uInt recordNo, Double columnValue) { }
1337 virtual void leaveTime(const uInt recordNo, Double columnValue) { }
1338
1339 virtual Bool visitRecord(const uInt recordNo,
1340 const Int antennaId,
1341 const Int feedId,
1342 const Int spwId,
1343 const Double time) { return True ; }
1344
1345 virtual Bool visit(Bool isFirst, const uInt recordNo,
1346 const uInt nCols, void const *const colValues[]) {
1347 Int antennaId, feedId, spwId;
1348 Double time;
1349 { // prologue
1350 uInt i = 0;
1351 {
1352 const Int *col = (const Int *)colValues[i++];
1353 antennaId = col[recordNo];
1354 }
1355 {
1356 const Int *col = (const Int *)colValues[i++];
1357 feedId = col[recordNo];
1358 }
1359 {
1360 const Int *col = (const Int *)colValues[i++];
1361 spwId = col[recordNo];
1362 }
1363 {
1364 const Double *col = (const Double *)colValues[i++];
1365 time = col[recordNo];
1366 }
1367 assert(nCols == i);
1368 }
1369
1370 if (isFirst) {
1371 enterAntennaId(recordNo, antennaId);
1372 enterFeedId(recordNo, feedId);
1373 enterSpwId(recordNo, spwId);
1374 enterTime(recordNo, time);
1375 } else {
1376 if ( lastAntennaId != antennaId ) {
1377 leaveTime(lastRecordNo, lastTime);
1378 leaveSpwId(lastRecordNo, lastSpwId);
1379 leaveFeedId(lastRecordNo, lastFeedId);
1380 leaveAntennaId(lastRecordNo, lastAntennaId);
1381
1382 enterAntennaId(recordNo, antennaId);
1383 enterFeedId(recordNo, feedId);
1384 enterSpwId(recordNo, spwId);
1385 enterTime(recordNo, time);
1386 }
1387 else if (lastFeedId != feedId) {
1388 leaveTime(lastRecordNo, lastTime);
1389 leaveSpwId(lastRecordNo, lastSpwId);
1390 leaveFeedId(lastRecordNo, lastFeedId);
1391
1392 enterFeedId(recordNo, feedId);
1393 enterSpwId(recordNo, spwId);
1394 enterTime(recordNo, time);
1395 } else if (lastSpwId != spwId) {
1396 leaveTime(lastRecordNo, lastTime);
1397 leaveSpwId(lastRecordNo, lastSpwId);
1398
1399 enterSpwId(recordNo, spwId);
1400 enterTime(recordNo, time);
1401 } else if (lastTime != time) {
1402 leaveTime(lastRecordNo, lastTime);
1403 enterTime(recordNo, time);
1404 }
1405 }
1406 count++;
1407 Bool result = visitRecord(recordNo, antennaId, feedId, spwId, time);
1408
1409 { // epilogue
1410 lastRecordNo = recordNo;
1411
1412 lastAntennaId = antennaId;
1413 lastFeedId = feedId;
1414 lastSpwId = spwId;
1415 lastTime = time;
1416 }
1417 return result ;
1418 }
1419
1420 virtual void finish() {
1421 if (count > 0) {
1422 leaveTime(lastRecordNo, lastTime);
1423 leaveSpwId(lastRecordNo, lastSpwId);
1424 leaveFeedId(lastRecordNo, lastFeedId);
1425 leaveAntennaId(lastRecordNo, lastAntennaId);
1426 }
1427 }
1428};
1429
1430class TcalVisitor: public BaseTcalVisitor, public MSFillerUtils {
1431public:
1432 TcalVisitor(const Table &table, Table &tcaltab, Record &r, Int aid )
1433 //TcalVisitor(const Table &table, Table &tcaltab, map< String,Vector<uInt> > &r, Int aid )
1434 : BaseTcalVisitor( table ),
1435 tcal(tcaltab),
1436 rec(r),
1437 antenna(aid)
1438 {
1439 process = False ;
1440 rowidx = 0 ;
1441
1442 // attach to SYSCAL columns
1443 timeCol.attach( table, "TIME" ) ;
1444
1445 // add rows
1446 uInt addrow = table.nrow() * 4 ;
1447 tcal.addRow( addrow ) ;
1448
1449 // attach to TCAL columns
1450 row = TableRow( tcal ) ;
1451 TableRecord &trec = row.record() ;
1452 idRF.attachToRecord( trec, "ID" ) ;
1453 timeRF.attachToRecord( trec, "TIME" ) ;
1454 tcalRF.attachToRecord( trec, "TCAL" ) ;
1455 }
1456
1457 virtual void enterAntennaId(const uInt recordNo, Int columnValue) {
1458 if ( columnValue == antenna )
1459 process = True ;
1460 }
1461 virtual void leaveAntennaId(const uInt recordNo, Int columnValue) {
1462 process = False ;
1463 }
1464 virtual void enterFeedId(const uInt recordNo, Int columnValue) { }
1465 virtual void leaveFeedId(const uInt recordNo, Int columnValue) { }
1466 virtual void enterSpwId(const uInt recordNo, Int columnValue) { }
1467 virtual void leaveSpwId(const uInt recordNo, Int columnValue) { }
1468 virtual void enterTime(const uInt recordNo, Double columnValue) {
1469 qtime = timeCol( recordNo ) ;
1470 }
1471 virtual void leaveTime(const uInt recordNo, Double columnValue) { }
1472 virtual Bool visitRecord(const uInt recordNo,
1473 const Int antennaId,
1474 const Int feedId,
1475 const Int spwId,
1476 const Double time)
1477 {
1478 //cout << "(" << recordNo << "," << antennaId << "," << feedId << "," << spwId << ")" << endl ;
1479 if ( process ) {
1480 String sTime = MVTime( qtime ).string( MVTime::YMD ) ;
1481 *timeRF = sTime ;
1482 uInt oldidx = rowidx ;
1483 Matrix<Float> subtcal = tcalCol( recordNo ) ;
1484 Vector<uInt> idminmax( 2 ) ;
1485 for ( uInt ipol = 0 ; ipol < subtcal.nrow() ; ipol++ ) {
1486 *idRF = rowidx ;
1487 tcalRF.define( subtcal.row( ipol ) ) ;
1488
1489 // commit row
1490 row.put( rowidx ) ;
1491 rowidx++ ;
1492 }
1493
1494 idminmax[0] = oldidx ;
1495 idminmax[1] = rowidx - 1 ;
1496
1497 String key = keyTcal( feedId, spwId, sTime ) ;
1498 rec.define( key, idminmax ) ;
1499 //rec[key] = idminmax ;
1500 }
1501 return True ;
1502 }
1503 virtual void finish()
1504 {
1505 BaseTcalVisitor::finish() ;
1506
1507 if ( tcal.nrow() > rowidx ) {
1508 uInt numRemove = tcal.nrow() - rowidx ;
1509 //cout << "numRemove = " << numRemove << endl ;
1510 Vector<uInt> rows( numRemove ) ;
1511 indgen( rows, rowidx ) ;
1512 tcal.removeRow( rows ) ;
1513 }
1514
1515 }
1516 void setTcalColumn( String &col )
1517 {
1518 //colName = col ;
1519 tcalCol.attach( table, col ) ;
1520 }
1521private:
1522 Table &tcal;
1523 Record &rec;
1524 //map< String,Vector<uInt> > &rec;
1525 Int antenna;
1526 uInt rowidx;
1527 Bool process;
1528 Quantum<Double> qtime;
1529 TableRow row;
1530 String colName;
1531
1532 // MS SYSCAL columns
1533 ROScalarQuantColumn<Double> timeCol;
1534 ROArrayColumn<Float> tcalCol;
1535
1536 // TCAL columns
1537 RecordFieldPtr<uInt> idRF;
1538 RecordFieldPtr<String> timeRF;
1539 RecordFieldPtr< Vector<Float> > tcalRF;
1540};
1541
1542MSFiller::MSFiller( casa::CountedPtr<Scantable> stable )
1543 : table_( stable ),
1544 tablename_( "" ),
1545 antenna_( -1 ),
1546 antennaStr_(""),
1547 getPt_( True ),
1548 isFloatData_( False ),
1549 isData_( False ),
1550 isDoppler_( False ),
1551 isFlagCmd_( False ),
1552 isFreqOffset_( False ),
1553 isHistory_( False ),
1554 isProcessor_( False ),
1555 isSysCal_( False ),
1556 isWeather_( False ),
1557 colTsys_( "TSYS_SPECTRUM" ),
1558 colTcal_( "TCAL_SPECTRUM" )
1559{
1560 os_ = LogIO() ;
1561 os_.origin( LogOrigin( "MSFiller", "MSFiller()", WHERE ) ) ;
1562}
1563
1564MSFiller::~MSFiller()
1565{
1566 os_.origin( LogOrigin( "MSFiller", "~MSFiller()", WHERE ) ) ;
1567}
1568
1569bool MSFiller::open( const std::string &filename, const casa::Record &rec )
1570{
1571 os_.origin( LogOrigin( "MSFiller", "open()", WHERE ) ) ;
1572 //double startSec = mathutil::gettimeofday_sec() ;
1573 //os_ << "start MSFiller::open() startsec=" << startSec << LogIO::POST ;
1574 //os_ << " filename = " << filename << endl ;
1575
1576 // parsing MS options
1577 if ( rec.isDefined( "ms" ) ) {
1578 Record msrec = rec.asRecord( "ms" ) ;
1579 if ( msrec.isDefined( "getpt" ) ) {
1580 getPt_ = msrec.asBool( "getpt" ) ;
1581 }
1582 if ( msrec.isDefined( "antenna" ) ) {
1583 if ( msrec.type( msrec.fieldNumber( "antenna" ) ) == TpInt ) {
1584 antenna_ = msrec.asInt( "antenna" ) ;
1585 }
1586 else {
1587 //antenna_ = atoi( msrec.asString( "antenna" ).c_str() ) ;
1588 antennaStr_ = msrec.asString( "antenna" ) ;
1589 }
1590 }
1591 else {
1592 antenna_ = 0 ;
1593 }
1594 }
1595
1596 MeasurementSet *tmpMS = new MeasurementSet( filename, Table::Old ) ;
1597 tablename_ = tmpMS->tableName() ;
1598 if ( antenna_ == -1 && antennaStr_.size() > 0 ) {
1599 MSAntennaIndex msAntIdx( tmpMS->antenna() ) ;
1600 Vector<Int> id = msAntIdx.matchAntennaName( antennaStr_ ) ;
1601 if ( id.size() > 0 )
1602 antenna_ = id[0] ;
1603 }
1604
1605 os_ << "Parsing MS options" << endl ;
1606 os_ << " getPt = " << getPt_ << endl ;
1607 os_ << " antenna = " << antenna_ << endl ;
1608 os_ << " antennaStr = " << antennaStr_ << LogIO::POST ;
1609
1610 mstable_ = MeasurementSet( (*tmpMS)( tmpMS->col("ANTENNA1") == antenna_
1611 && tmpMS->col("ANTENNA1") == tmpMS->col("ANTENNA2") ) ) ;
1612
1613 delete tmpMS ;
1614
1615 // check which data column exists
1616 isFloatData_ = mstable_.tableDesc().isColumn( "FLOAT_DATA" ) ;
1617 isData_ = mstable_.tableDesc().isColumn( "DATA" ) ;
1618
1619 //double endSec = mathutil::gettimeofday_sec() ;
1620 //os_ << "end MSFiller::open() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1621 return true ;
1622}
1623
1624void MSFiller::fill()
1625{
1626 //double startSec = mathutil::gettimeofday_sec() ;
1627 //os_ << "start MSFiller::fill() startSec=" << startSec << LogIO::POST ;
1628
1629 os_.origin( LogOrigin( "MSFiller", "fill()", WHERE ) ) ;
1630
1631 // Initialize header
1632 STHeader sdh ;
1633 initHeader( sdh ) ;
1634 table_->setHeader( sdh ) ;
1635
1636 // check if optional table exists
1637 const TableRecord &msrec = mstable_.keywordSet() ;
1638 isDoppler_ = msrec.isDefined( "DOPPLER" ) ;
1639 if ( isDoppler_ )
1640 if ( mstable_.doppler().nrow() == 0 )
1641 isDoppler_ = False ;
1642 isFlagCmd_ = msrec.isDefined( "FLAG_CMD" ) ;
1643 if ( isFlagCmd_ )
1644 if ( mstable_.flagCmd().nrow() == 0 )
1645 isFlagCmd_ = False ;
1646 isFreqOffset_ = msrec.isDefined( "FREQ_OFFSET" ) ;
1647 if ( isFreqOffset_ )
1648 if ( mstable_.freqOffset().nrow() == 0 )
1649 isFreqOffset_ = False ;
1650 isHistory_ = msrec.isDefined( "HISTORY" ) ;
1651 if ( isHistory_ )
1652 if ( mstable_.history().nrow() == 0 )
1653 isHistory_ = False ;
1654 isProcessor_ = msrec.isDefined( "PROCESSOR" ) ;
1655 if ( isProcessor_ )
1656 if ( mstable_.processor().nrow() == 0 )
1657 isProcessor_ = False ;
1658 isSysCal_ = msrec.isDefined( "SYSCAL" ) ;
1659 if ( isSysCal_ )
1660 if ( mstable_.sysCal().nrow() == 0 )
1661 isSysCal_ = False ;
1662 isWeather_ = msrec.isDefined( "WEATHER" ) ;
1663 if ( isWeather_ )
1664 if ( mstable_.weather().nrow() == 0 )
1665 isWeather_ = False ;
1666
1667 // column name for Tsys and Tcal
1668 if ( isSysCal_ ) {
1669 const MSSysCal &caltab = mstable_.sysCal() ;
1670 if ( !caltab.tableDesc().isColumn( colTcal_ ) ) {
1671 colTcal_ = "TCAL" ;
1672 if ( !caltab.tableDesc().isColumn( colTcal_ ) )
1673 colTcal_ = "NONE" ;
1674 }
1675 if ( !caltab.tableDesc().isColumn( colTsys_ ) ) {
1676 colTsys_ = "TSYS" ;
1677 if ( !caltab.tableDesc().isColumn( colTcal_ ) )
1678 colTsys_ = "NONE" ;
1679 }
1680 }
1681 else {
1682 colTcal_ = "NONE" ;
1683 colTsys_ = "NONE" ;
1684 }
1685
1686 // Access to MS subtables
1687 //MSField &fieldtab = mstable_.field() ;
1688 //MSPolarization &poltab = mstable_.polarization() ;
1689 //MSDataDescription &ddtab = mstable_.dataDescription() ;
1690 //MSObservation &obstab = mstable_.observation() ;
1691 //MSSource &srctab = mstable_.source() ;
1692 //MSSpectralWindow &spwtab = mstable_.spectralWindow() ;
1693 //MSSysCal &caltab = mstable_.sysCal() ;
1694 MSPointing &pointtab = mstable_.pointing() ;
1695 //MSState &stattab = mstable_.state() ;
1696 //MSAntenna &anttab = mstable_.antenna() ;
1697
1698 // SUBTABLES: FREQUENCIES
1699 //string freqFrame = getFrame() ;
1700 string freqFrame = "LSRK" ;
1701 table_->frequencies().setFrame( freqFrame ) ;
1702 table_->frequencies().setFrame( freqFrame, True ) ;
1703
1704 // SUBTABLES: WEATHER
1705 fillWeather() ;
1706
1707 // SUBTABLES: FOCUS
1708 fillFocus() ;
1709
1710 // SUBTABLES: TCAL
1711 fillTcal() ;
1712
1713 // SUBTABLES: FIT
1714 //fillFit() ;
1715
1716 // SUBTABLES: HISTORY
1717 //fillHistory() ;
1718
1719 /***
1720 * Start iteration using TableVisitor
1721 ***/
1722 Table stab = table_->table() ;
1723 {
1724 static const char *cols[] = {
1725 "OBSERVATION_ID", "FEED1", "FIELD_ID", "DATA_DESC_ID", "SCAN_NUMBER",
1726 "STATE_ID", "TIME",
1727 NULL
1728 };
1729 static const TypeManagerImpl<Int> tmInt;
1730 static const TypeManagerImpl<Double> tmDouble;
1731 static const TypeManager *const tms[] = {
1732 &tmInt, &tmInt, &tmInt, &tmInt, &tmInt, &tmInt, &tmDouble, NULL
1733 };
1734 //double t0 = mathutil::gettimeofday_sec() ;
1735 MSFillerVisitor myVisitor(mstable_, *table_ );
1736 //double t1 = mathutil::gettimeofday_sec() ;
1737 //cout << "MSFillerVisitor(): elapsed time " << t1-t0 << " sec" << endl ;
1738 myVisitor.setAntenna( antenna_ ) ;
1739 //myVisitor.setHeader( sdh ) ;
1740 if ( getPt_ ) {
1741 Table ptsel = pointtab( pointtab.col("ANTENNA_ID")==antenna_ ).sort( "TIME" ) ;
1742 myVisitor.setPointingTable( ptsel ) ;
1743 }
1744 if ( isWeather_ )
1745 myVisitor.setWeatherTime( mwTime_, mwInterval_ ) ;
1746 if ( isSysCal_ )
1747 myVisitor.setSysCalRecord( tcalrec_ ) ;
1748
1749 //double t2 = mathutil::gettimeofday_sec() ;
1750 traverseTable(mstable_, cols, tms, &myVisitor);
1751 //double t3 = mathutil::gettimeofday_sec() ;
1752 //cout << "traverseTable(): elapsed time " << t3-t2 << " sec" << endl ;
1753
1754 sdh = myVisitor.getHeader() ;
1755 }
1756 /***
1757 * End iteration using TableVisitor
1758 ***/
1759
1760 // set header
1761 //sdh = myVisitor.getHeader() ;
1762 //table_->setHeader( sdh ) ;
1763
1764 // save path to POINTING table
1765 // 2011/07/06 TN
1766 // Path to POINTING table in original MS will not be written
1767 // if getPt_ is True
1768 Path datapath( tablename_ ) ;
1769 if ( !getPt_ ) {
1770 String pTabName = datapath.absoluteName() + "/POINTING" ;
1771 stab.rwKeywordSet().define( "POINTING", pTabName ) ;
1772 }
1773
1774 // for GBT
1775 if ( sdh.antennaname.contains( "GBT" ) ) {
1776 String goTabName = datapath.absoluteName() + "/GBT_GO" ;
1777 stab.rwKeywordSet().define( "GBT_GO", goTabName ) ;
1778 }
1779
1780 // for MS created from ASDM
1781 const TableRecord &msKeys = mstable_.keywordSet() ;
1782 uInt nfields = msKeys.nfields() ;
1783 for ( uInt ifield = 0 ; ifield < nfields ; ifield++ ) {
1784 String name = msKeys.name( ifield ) ;
1785 //os_ << "name = " << name << LogIO::POST ;
1786 if ( name.find( "ASDM" ) != String::npos ) {
1787 String asdmpath = msKeys.asTable( ifield ).tableName() ;
1788 os_ << "ASDM table: " << asdmpath << LogIO::POST ;
1789 stab.rwKeywordSet().define( name, asdmpath ) ;
1790 }
1791 }
1792
1793 //double endSec = mathutil::gettimeofday_sec() ;
1794 //os_ << "end MSFiller::fill() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1795}
1796
1797void MSFiller::close()
1798{
1799 //tablesel_.closeSubTables() ;
1800 mstable_.closeSubTables() ;
1801 //tablesel_.unlock() ;
1802 mstable_.unlock() ;
1803}
1804
1805void MSFiller::fillWeather()
1806{
1807 //double startSec = mathutil::gettimeofday_sec() ;
1808 //os_ << "start MSFiller::fillWeather() startSec=" << startSec << LogIO::POST ;
1809
1810 if ( !isWeather_ ) {
1811 // add dummy row
1812 table_->weather().table().addRow(1,True) ;
1813 return ;
1814 }
1815
1816 Table mWeather = mstable_.weather() ;
1817 //Table mWeatherSel = mWeather( mWeather.col("ANTENNA_ID") == antenna_ ).sort("TIME") ;
1818 Table mWeatherSel( mWeather( mWeather.col("ANTENNA_ID") == antenna_ ).sort("TIME") ) ;
1819 //os_ << "mWeatherSel.nrow() = " << mWeatherSel.nrow() << LogIO::POST ;
1820 if ( mWeatherSel.nrow() == 0 ) {
1821 os_ << "No rows with ANTENNA_ID = " << antenna_ << " in WEATHER table, Try -1..." << LogIO::POST ;
1822 mWeatherSel = Table( MSWeather( mWeather( mWeather.col("ANTENNA_ID") == -1 ) ) ) ;
1823 if ( mWeatherSel.nrow() == 0 ) {
1824 os_ << "No rows in WEATHER table" << LogIO::POST ;
1825 }
1826 }
1827 uInt wnrow = mWeatherSel.nrow() ;
1828 //os_ << "wnrow = " << wnrow << LogIO::POST ;
1829
1830 if ( wnrow == 0 )
1831 return ;
1832
1833 Table wtab = table_->weather().table() ;
1834 wtab.addRow( wnrow ) ;
1835
1836 Bool stationInfoExists = mWeatherSel.tableDesc().isColumn( "NS_WX_STATION_ID" ) ;
1837 Int stationId = -1 ;
1838 if ( stationInfoExists ) {
1839 // determine which station is closer
1840 ROScalarColumn<Int> stationCol( mWeatherSel, "NS_WX_STATION_ID" ) ;
1841 ROArrayColumn<Double> stationPosCol( mWeatherSel, "NS_WX_STATION_POSITION" ) ;
1842 Vector<Int> stationIds = stationCol.getColumn() ;
1843 Vector<Int> stationIdList( 0 ) ;
1844 Matrix<Double> stationPosList( 0, 3, 0.0 ) ;
1845 uInt numStation = 0 ;
1846 for ( uInt i = 0 ; i < stationIds.size() ; i++ ) {
1847 if ( !anyEQ( stationIdList, stationIds[i] ) ) {
1848 numStation++ ;
1849 stationIdList.resize( numStation, True ) ;
1850 stationIdList[numStation-1] = stationIds[i] ;
1851 stationPosList.resize( numStation, 3, True ) ;
1852 stationPosList.row( numStation-1 ) = stationPosCol( i ) ;
1853 }
1854 }
1855 //os_ << "staionIdList = " << stationIdList << endl ;
1856 Table mAntenna = mstable_.antenna() ;
1857 ROArrayColumn<Double> antposCol( mAntenna, "POSITION" ) ;
1858 Vector<Double> antpos = antposCol( antenna_ ) ;
1859 Double minDiff = -1.0 ;
1860 for ( uInt i = 0 ; i < stationIdList.size() ; i++ ) {
1861 Double diff = sum( square( antpos - stationPosList.row( i ) ) ) ;
1862 if ( minDiff < 0.0 || minDiff > diff ) {
1863 minDiff = diff ;
1864 stationId = stationIdList[i] ;
1865 }
1866 }
1867 }
1868 //os_ << "stationId = " << stationId << endl ;
1869
1870 ScalarColumn<Float> *fCol ;
1871 ROScalarColumn<Float> *sharedFloatCol ;
1872 if ( mWeatherSel.tableDesc().isColumn( "TEMPERATURE" ) ) {
1873 fCol = new ScalarColumn<Float>( wtab, "TEMPERATURE" ) ;
1874 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "TEMPERATURE" ) ;
1875 fCol->putColumn( *sharedFloatCol ) ;
1876 delete sharedFloatCol ;
1877 delete fCol ;
1878 }
1879 if ( mWeatherSel.tableDesc().isColumn( "PRESSURE" ) ) {
1880 fCol = new ScalarColumn<Float>( wtab, "PRESSURE" ) ;
1881 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "PRESSURE" ) ;
1882 fCol->putColumn( *sharedFloatCol ) ;
1883 delete sharedFloatCol ;
1884 delete fCol ;
1885 }
1886 if ( mWeatherSel.tableDesc().isColumn( "REL_HUMIDITY" ) ) {
1887 fCol = new ScalarColumn<Float>( wtab, "HUMIDITY" ) ;
1888 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "REL_HUMIDITY" ) ;
1889 fCol->putColumn( *sharedFloatCol ) ;
1890 delete sharedFloatCol ;
1891 delete fCol ;
1892 }
1893 if ( mWeatherSel.tableDesc().isColumn( "WIND_SPEED" ) ) {
1894 fCol = new ScalarColumn<Float>( wtab, "WINDSPEED" ) ;
1895 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "WIND_SPEED" ) ;
1896 fCol->putColumn( *sharedFloatCol ) ;
1897 delete sharedFloatCol ;
1898 delete fCol ;
1899 }
1900 if ( mWeatherSel.tableDesc().isColumn( "WIND_DIRECTION" ) ) {
1901 fCol = new ScalarColumn<Float>( wtab, "WINDAZ" ) ;
1902 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "WIND_DIRECTION" ) ;
1903 fCol->putColumn( *sharedFloatCol ) ;
1904 delete sharedFloatCol ;
1905 delete fCol ;
1906 }
1907 ScalarColumn<uInt> idCol( wtab, "ID" ) ;
1908 for ( uInt irow = 0 ; irow < wnrow ; irow++ )
1909 idCol.put( irow, irow ) ;
1910
1911 ROScalarQuantColumn<Double> tqCol( mWeatherSel, "TIME" ) ;
1912 ROScalarColumn<Double> tCol( mWeatherSel, "TIME" ) ;
1913 String tUnit = tqCol.getUnits() ;
1914 Vector<Double> mwTime = tCol.getColumn() ;
1915 if ( tUnit == "d" )
1916 mwTime *= 86400.0 ;
1917 tqCol.attach( mWeatherSel, "INTERVAL" ) ;
1918 tCol.attach( mWeatherSel, "INTERVAL" ) ;
1919 String iUnit = tqCol.getUnits() ;
1920 Vector<Double> mwInterval = tCol.getColumn() ;
1921 if ( iUnit == "d" )
1922 mwInterval *= 86400.0 ;
1923
1924 if ( stationId > 0 ) {
1925 ROScalarColumn<Int> stationCol( mWeatherSel, "NS_WX_STATION_ID" ) ;
1926 Vector<Int> stationVec = stationCol.getColumn() ;
1927 uInt wsnrow = ntrue( stationVec == stationId ) ;
1928 mwTime_.resize( wsnrow ) ;
1929 mwInterval_.resize( wsnrow ) ;
1930 mwIndex_.resize( wsnrow ) ;
1931 uInt wsidx = 0 ;
1932 for ( uInt irow = 0 ; irow < wnrow ; irow++ ) {
1933 if ( stationId == stationVec[irow] ) {
1934 mwTime_[wsidx] = mwTime[irow] ;
1935 mwInterval_[wsidx] = mwInterval[irow] ;
1936 mwIndex_[wsidx] = irow ;
1937 wsidx++ ;
1938 }
1939 }
1940 }
1941 else {
1942 mwTime_ = mwTime ;
1943 mwInterval_ = mwInterval ;
1944 mwIndex_.resize( mwTime_.size() ) ;
1945 indgen( mwIndex_ ) ;
1946 }
1947 //os_ << "mwTime[0] = " << mwTime_[0] << " mwInterval[0] = " << mwInterval_[0] << LogIO::POST ;
1948 //double endSec = mathutil::gettimeofday_sec() ;
1949 //os_ << "end MSFiller::fillWeather() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1950}
1951
1952void MSFiller::fillFocus()
1953{
1954 //double startSec = mathutil::gettimeofday_sec() ;
1955 //os_ << "start MSFiller::fillFocus() startSec=" << startSec << LogIO::POST ;
1956 // tentative
1957 table_->focus().addEntry( 0.0, 0.0, 0.0, 0.0 ) ;
1958 //double endSec = mathutil::gettimeofday_sec() ;
1959 //os_ << "end MSFiller::fillFocus() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1960}
1961
1962void MSFiller::fillTcal()
1963{
1964 //double startSec = mathutil::gettimeofday_sec() ;
1965 //os_ << "start MSFiller::fillTcal() startSec=" << startSec << LogIO::POST ;
1966
1967 if ( !isSysCal_ ) {
1968 // add dummy row
1969 os_ << "No SYSCAL rows" << LogIO::POST ;
1970 table_->tcal().table().addRow(1,True) ;
1971 Vector<Float> defaultTcal( 1, 1.0 ) ;
1972 ArrayColumn<Float> tcalCol( table_->tcal().table(), "TCAL" ) ;
1973 tcalCol.put( 0, defaultTcal ) ;
1974 return ;
1975 }
1976
1977 if ( colTcal_ == "NONE" ) {
1978 // add dummy row
1979 os_ << "No TCAL column" << LogIO::POST ;
1980 table_->tcal().table().addRow(1,True) ;
1981 Vector<Float> defaultTcal( 1, 1.0 ) ;
1982 ArrayColumn<Float> tcalCol( table_->tcal().table(), "TCAL" ) ;
1983 tcalCol.put( 0, defaultTcal ) ;
1984 return ;
1985 }
1986
1987 Table &sctab = mstable_.sysCal() ;
1988 if ( sctab.nrow() == 0 ) {
1989 os_ << "No SYSCAL rows" << LogIO::POST ;
1990 return ;
1991 }
1992 ROScalarColumn<Int> antCol( sctab, "ANTENNA_ID" ) ;
1993 Vector<Int> ant = antCol.getColumn() ;
1994 if ( allNE( ant, antenna_ ) ) {
1995 os_ << "No SYSCAL rows" << LogIO::POST ;
1996 return ;
1997 }
1998 ROTableColumn tcalCol( sctab, colTcal_ ) ;
1999 Bool notDefined = False ;
2000 for ( uInt irow = 0 ; irow < sctab.nrow() ; irow++ ) {
2001 if ( ant[irow] == antenna_ && !tcalCol.isDefined( irow ) ) {
2002 notDefined = True ;
2003 break ;
2004 }
2005 }
2006 if ( notDefined ) {
2007 os_ << "No TCAL value" << LogIO::POST ;
2008 table_->tcal().table().addRow(1,True) ;
2009 Vector<Float> defaultTcal( 1, 1.0 ) ;
2010 ArrayColumn<Float> tcalCol( table_->tcal().table(), "TCAL" ) ;
2011 tcalCol.put( 0, defaultTcal ) ;
2012 return ;
2013 }
2014
2015 static const char *cols[] = {
2016 "ANTENNA_ID", "FEED_ID", "SPECTRAL_WINDOW_ID", "TIME",
2017 NULL
2018 };
2019 static const TypeManagerImpl<Int> tmInt;
2020 static const TypeManagerImpl<Double> tmDouble;
2021 static const TypeManager *const tms[] = {
2022 &tmInt, &tmInt, &tmInt, &tmDouble, NULL
2023 };
2024 Table tab = table_->tcal().table() ;
2025 TcalVisitor visitor( sctab, tab, tcalrec_, antenna_ ) ;
2026 visitor.setTcalColumn( colTcal_ ) ;
2027
2028 traverseTable(sctab, cols, tms, &visitor);
2029
2030 //tcalrec_.print( std::cout ) ;
2031 //double endSec = mathutil::gettimeofday_sec() ;
2032 //os_ << "end MSFiller::fillTcal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2033}
2034
2035string MSFiller::getFrame()
2036{
2037 MFrequency::Types frame = MFrequency::DEFAULT ;
2038 ROTableColumn numChanCol( mstable_.spectralWindow(), "NUM_CHAN" ) ;
2039 ROTableColumn measFreqRefCol( mstable_.spectralWindow(), "MEAS_FREQ_REF" ) ;
2040 uInt nrow = numChanCol.nrow() ;
2041 Vector<Int> measFreqRef( nrow, MFrequency::DEFAULT ) ;
2042 uInt nref = 0 ;
2043 for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
2044 if ( numChanCol.asInt( irow ) != 4 ) { // exclude WVR
2045 measFreqRef[nref] = measFreqRefCol.asInt( irow ) ;
2046 nref++ ;
2047 }
2048 }
2049 if ( nref > 0 )
2050 frame = (MFrequency::Types)measFreqRef[0] ;
2051
2052 return MFrequency::showType( frame ) ;
2053}
2054
2055void MSFiller::initHeader( STHeader &header )
2056{
2057 header.nchan = 0 ;
2058 header.npol = 0 ;
2059 header.nif = 0 ;
2060 header.nbeam = 0 ;
2061 header.observer = "" ;
2062 header.project = "" ;
2063 header.obstype = "" ;
2064 header.antennaname = "" ;
2065 header.antennaposition.resize( 3 ) ;
2066 header.equinox = 0.0 ;
2067 header.freqref = "" ;
2068 header.reffreq = -1.0 ;
2069 header.bandwidth = 0.0 ;
2070 header.utc = 0.0 ;
2071 header.fluxunit = "" ;
2072 header.epoch = "" ;
2073 header.poltype = "" ;
2074}
2075
2076};
Note: See TracBrowser for help on using the repository browser.