source: branches/hpc33/src/MSFiller.cpp@ 2549

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

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Use approximate calculation of calcEarth.


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