source: trunk/src/MSFiller.cpp@ 2565

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

New Development: No

JIRA Issue: Yes CSV-1829

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...

Modified the code to be able to handle INCREMENT for spectral axis correctly
regardless of sign of MS/SPECTRA_WINDOW/CHAN_WIDTH frequency.


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