source: trunk/src/MSFiller.cpp @ 2295

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

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: sd regressions, test_sdsave

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Bug fix: support the case that TCAL_SPECTRUM exists but empty.


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