source: trunk/src/MSFiller.cpp @ 2292

Last change on this file since 2292 was 2292, checked in by Takeshi Nakazato, 13 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...

Support MS without SYSCAL table.


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