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

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

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Use approximate calculation of calcEarth.


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