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

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

New Development: No

JIRA Issue: Yes CAS-4201

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

Bug fix for the case when getpt is False.


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