source: trunk/src/MSFiller.cpp@ 2759

Last change on this file since 2759 was 2754, checked in by Takeshi Nakazato, 12 years ago

New Development: No

JIRA Issue: Yes CSV-2532 (may be related to CSV-1908 and CSV-2161)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: In tool level, added parameter 'freq_tolsr' to

scantable constructor and function sd.splitant.

Test Programs: test_sdsave, test_importasdm_sd

Put in Release Notes: Yes

Module(s): Module Names change impacts.

Description: Describe your changes here...

In importing MS to Scantable, frequency frame information is
imported as is by default, i.e., base frame in Scantable is
TOPO for ALMA data, which is forcibly converted to LSRK with
wrong time and direction reference.

Some functions have a boolean parameter 'freq_tolsr' that controls
the above behavior. If freq_tolsr is False (default), frequency
is imported as is, while frequency is converted to LSRK (wrongly)
when it is True.


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