source: trunk/src/MSFiller.cpp @ 2710

Last change on this file since 2710 was 2710, checked in by Takeshi Nakazato, 11 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Reference epoch for frequency frame conversion is taken from header
which is set as start time of the observation (OBSERVATION/TIME_RANGE[0]
for MS, ExecBlock?/startTime for ASDM).


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