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

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

New Development: No

JIRA Issue: Yes CAS-4201

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Bug fix for the case when getpt is False.


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